mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-25 16:25:25 +00:00
Replace "system crate" vs "user code" distinction with zombies everywhere.
This commit is contained in:
parent
633dff18bd
commit
dcd2c74054
@ -210,7 +210,7 @@ impl<'tcx> RecursivePointeeCache<'tcx> {
|
||||
cx.zombie_with_span(
|
||||
new_id,
|
||||
span,
|
||||
"Cannot create self-referential types, even through pointers",
|
||||
"cannot create self-referential types, even through pointers",
|
||||
);
|
||||
Some(new_id)
|
||||
}
|
||||
|
@ -171,7 +171,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
if invalid_seq_cst {
|
||||
self.zombie(
|
||||
semantics.def(self),
|
||||
"Cannot use AtomicOrdering=SequentiallyConsistent on Vulkan memory model. Check if AcquireRelease fits your needs.",
|
||||
"cannot use AtomicOrdering=SequentiallyConsistent on Vulkan memory model \
|
||||
(check if AcquireRelease fits your needs)",
|
||||
);
|
||||
}
|
||||
semantics
|
||||
@ -352,11 +353,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn zombie_convert_ptr_to_u(&self, def: Word) {
|
||||
self.zombie(def, "Cannot convert pointers to integers");
|
||||
self.zombie(def, "cannot convert pointers to integers");
|
||||
}
|
||||
|
||||
fn zombie_convert_u_to_ptr(&self, def: Word) {
|
||||
self.zombie(def, "Cannot convert integers to pointers");
|
||||
self.zombie(def, "cannot convert integers to pointers");
|
||||
}
|
||||
|
||||
fn zombie_ptr_equal(&self, def: Word, inst: &str) {
|
||||
@ -1453,21 +1454,16 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
.with_type(dest_ty);
|
||||
|
||||
if val_is_ptr || dest_is_ptr {
|
||||
if self.is_system_crate(self.span()) {
|
||||
self.zombie(
|
||||
result.def(self),
|
||||
&format!(
|
||||
"Cannot cast between pointer and non-pointer types. From: {}. To: {}.",
|
||||
self.debug_type(val.ty),
|
||||
self.debug_type(dest_ty)
|
||||
),
|
||||
);
|
||||
} else {
|
||||
self.struct_err("Cannot cast between pointer and non-pointer types")
|
||||
.note(&format!("from: {}", self.debug_type(val.ty)))
|
||||
.note(&format!("to: {}", self.debug_type(dest_ty)))
|
||||
.emit();
|
||||
}
|
||||
self.zombie(
|
||||
result.def(self),
|
||||
&format!(
|
||||
"cannot cast between pointer and non-pointer types\
|
||||
\nfrom `{}`\
|
||||
\n to `{}`",
|
||||
self.debug_type(val.ty),
|
||||
self.debug_type(dest_ty)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
result
|
||||
@ -1884,7 +1880,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
empty(),
|
||||
)
|
||||
.unwrap();
|
||||
self.zombie(dst.def(self), "Cannot memcpy dynamically sized data");
|
||||
self.zombie(dst.def(self), "cannot memcpy dynamically sized data");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ use rustc_target::abi::{Align, Size};
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn load_err(&mut self, original_type: Word, invalid_type: Word) -> SpirvValue {
|
||||
let mut err = self.struct_err(&format!(
|
||||
"Cannot load type {} in an untyped buffer load",
|
||||
"cannot load type {} in an untyped buffer load",
|
||||
self.debug_type(original_type)
|
||||
));
|
||||
if original_type != invalid_type {
|
||||
@ -206,7 +206,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
fn store_err(&mut self, original_type: Word, value: SpirvValue) -> Result<(), ErrorGuaranteed> {
|
||||
let mut err = self.struct_err(&format!(
|
||||
"Cannot store type {} in an untyped buffer store",
|
||||
"cannot store type {} in an untyped buffer store",
|
||||
self.debug_type(original_type)
|
||||
));
|
||||
if original_type != value.ty {
|
||||
|
@ -208,7 +208,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
.with_type(result_type);
|
||||
self.zombie(
|
||||
result.def(self),
|
||||
"Cannot offset a pointer to an arbitrary element",
|
||||
"cannot offset a pointer to an arbitrary element",
|
||||
);
|
||||
result
|
||||
}
|
||||
@ -219,7 +219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let width = match self.lookup_type(shift.ty) {
|
||||
SpirvType::Integer(width, _) => width,
|
||||
other => self.fatal(&format!(
|
||||
"Cannot rotate non-integer type: {}",
|
||||
"cannot rotate non-integer type: {}",
|
||||
other.debug(shift.ty, self)
|
||||
)),
|
||||
};
|
||||
|
@ -140,9 +140,7 @@ impl SpirvValue {
|
||||
IllegalConst::Indirect(cause) => cause.message(),
|
||||
};
|
||||
|
||||
// HACK(eddyb) we don't know whether this constant originated
|
||||
// in a system crate, so it's better to always zombie.
|
||||
cx.zombie_even_in_user_code(id, span, msg);
|
||||
cx.zombie_with_span(id, span, msg);
|
||||
|
||||
id
|
||||
}
|
||||
@ -158,25 +156,15 @@ impl SpirvValue {
|
||||
}
|
||||
|
||||
SpirvValueKind::FnAddr { .. } => {
|
||||
if cx.is_system_crate(span) {
|
||||
cx.builder
|
||||
.const_to_id
|
||||
.borrow()
|
||||
.get(&WithType {
|
||||
ty: self.ty,
|
||||
val: SpirvConst::ZombieUndefForFnAddr,
|
||||
})
|
||||
.expect("FnAddr didn't go through proper undef registration")
|
||||
.val
|
||||
} else {
|
||||
cx.tcx.sess.span_err(
|
||||
span,
|
||||
"Cannot use this function pointer for anything other than calls",
|
||||
);
|
||||
// Because we never get beyond compilation (into e.g. linking),
|
||||
// emitting an invalid ID reference here is OK.
|
||||
0
|
||||
}
|
||||
cx.builder
|
||||
.const_to_id
|
||||
.borrow()
|
||||
.get(&WithType {
|
||||
ty: self.ty,
|
||||
val: SpirvConst::ZombieUndefForFnAddr,
|
||||
})
|
||||
.expect("FnAddr didn't go through proper undef registration")
|
||||
.val
|
||||
}
|
||||
|
||||
SpirvValueKind::LogicalPtrCast {
|
||||
@ -184,24 +172,17 @@ impl SpirvValue {
|
||||
original_pointee_ty,
|
||||
zombie_target_undef,
|
||||
} => {
|
||||
if cx.is_system_crate(span) {
|
||||
cx.zombie_with_span(
|
||||
zombie_target_undef,
|
||||
span,
|
||||
&format!(
|
||||
"Cannot cast between pointer types. From: {}. To: {}.",
|
||||
cx.debug_type(original_pointee_ty),
|
||||
cx.debug_type(self.ty)
|
||||
),
|
||||
);
|
||||
} else {
|
||||
cx.tcx
|
||||
.sess
|
||||
.struct_span_err(span, "Cannot cast between pointer types")
|
||||
.note(&format!("from: *{}", cx.debug_type(original_pointee_ty)))
|
||||
.note(&format!("to: {}", cx.debug_type(self.ty)))
|
||||
.emit();
|
||||
}
|
||||
cx.zombie_with_span(
|
||||
zombie_target_undef,
|
||||
span,
|
||||
&format!(
|
||||
"cannot cast between pointer types\
|
||||
\nfrom `*{}`\
|
||||
\n to `{}`",
|
||||
cx.debug_type(original_pointee_ty),
|
||||
cx.debug_type(self.ty)
|
||||
),
|
||||
);
|
||||
|
||||
zombie_target_undef
|
||||
}
|
||||
|
@ -255,11 +255,8 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
|
||||
self.constant_null(ty)
|
||||
} else {
|
||||
let result = self.undef(ty);
|
||||
// HACK(eddyb) we don't know whether this constant originated
|
||||
// in a system crate, so it's better to always zombie.
|
||||
self.zombie_even_in_user_code(
|
||||
self.zombie_no_span(
|
||||
result.def_cx(self),
|
||||
DUMMY_SP,
|
||||
"pointer has non-null integer address",
|
||||
);
|
||||
result
|
||||
@ -408,7 +405,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
SpirvType::Void => self
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("Cannot create const alloc of type void"),
|
||||
.fatal("cannot create const alloc of type void"),
|
||||
SpirvType::Bool
|
||||
| SpirvType::Integer(..)
|
||||
| SpirvType::Float(_)
|
||||
@ -552,37 +549,36 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
*data = *c + asdf->y[*c];
|
||||
}
|
||||
*/
|
||||
// HACK(eddyb) we don't know whether this constant originated
|
||||
// in a system crate, so it's better to always zombie.
|
||||
self.zombie_even_in_user_code(
|
||||
result.def_cx(self),
|
||||
DUMMY_SP,
|
||||
"constant runtime array value",
|
||||
);
|
||||
// NOTE(eddyb) the above description is a bit outdated, it's now
|
||||
// clear `OpTypeRuntimeArray` does not belong in user code, and
|
||||
// is only for dynamically-sized SSBOs and descriptor indexing,
|
||||
// and a general solution looks similar to `union` handling, but
|
||||
// for the length of a fixed-length array.
|
||||
self.zombie_no_span(result.def_cx(self), "constant `OpTypeRuntimeArray` value");
|
||||
result
|
||||
}
|
||||
SpirvType::Function { .. } => self
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("TODO: SpirvType::Function not supported yet in create_const_alloc"),
|
||||
SpirvType::Image { .. } => self.tcx.sess.fatal("Cannot create a constant image value"),
|
||||
SpirvType::Image { .. } => self.tcx.sess.fatal("cannot create a constant image value"),
|
||||
SpirvType::Sampler => self
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("Cannot create a constant sampler value"),
|
||||
.fatal("cannot create a constant sampler value"),
|
||||
SpirvType::SampledImage { .. } => self
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("Cannot create a constant sampled image value"),
|
||||
.fatal("cannot create a constant sampled image value"),
|
||||
SpirvType::InterfaceBlock { .. } => self
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("Cannot create a constant interface block value"),
|
||||
.fatal("cannot create a constant interface block value"),
|
||||
SpirvType::AccelerationStructureKhr => self
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("Cannot create a constant acceleration structure"),
|
||||
SpirvType::RayQueryKhr => self.tcx.sess.fatal("Cannot create a constant ray query"),
|
||||
.fatal("cannot create a constant acceleration structure"),
|
||||
SpirvType::RayQueryKhr => self.tcx.sess.fatal("cannot create a constant ray query"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,8 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
.variable(ptr_ty, None, StorageClass::Private, None)
|
||||
.with_type(ptr_ty);
|
||||
// TODO: These should be StorageClass::Private, so just zombie for now.
|
||||
self.zombie_with_span(result.def_cx(self), span, "Globals are not supported yet");
|
||||
// FIXME(eddyb) why zombie? this looks like it should just work nowadays.
|
||||
self.zombie_with_span(result.def_cx(self), span, "globals are not supported yet");
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
} else {
|
||||
self.tcx
|
||||
.sess
|
||||
.span_err(span, format!("Cannot declare {name} as an entry point"));
|
||||
.span_err(span, format!("cannot declare {name} as an entry point"));
|
||||
return;
|
||||
};
|
||||
let body = self
|
||||
|
@ -25,7 +25,7 @@ use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt};
|
||||
use rustc_middle::ty::{Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{SourceFile, Span, DUMMY_SP};
|
||||
use rustc_target::abi::call::{FnAbi, PassMode};
|
||||
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
|
||||
@ -164,28 +164,16 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
}
|
||||
|
||||
/// Zombie system:
|
||||
/// When compiling libcore and other system libraries, if something unrepresentable is
|
||||
/// encountered, we don't want to fail the compilation. Instead, we emit something bogus
|
||||
/// (usually it's fairly faithful, though, e.g. u128 emits `OpTypeInt 128`), and then mark the
|
||||
/// resulting ID as a "zombie". We continue compiling the rest of the crate, then, at the very
|
||||
/// end, anything that transtively references a zombie value is stripped from the binary.
|
||||
///
|
||||
/// If an exported function is stripped, then we emit a special "zombie export" item, which is
|
||||
/// consumed by the linker, which continues to infect other values that reference it.
|
||||
/// If something unrepresentable is encountered, we don't want to fail
|
||||
/// the compilation. Instead, we emit something bogus (usually it's fairly
|
||||
/// faithful, though, e.g. `u128` emits `OpTypeInt 128 0`), and then mark the
|
||||
/// resulting ID as a "zombie". We continue compiling the rest of the crate,
|
||||
/// then, at the very end, anything that transitively references a zombie value
|
||||
/// is stripped from the binary.
|
||||
///
|
||||
/// Finally, if *user* code is marked as zombie, then this means that the user tried to do
|
||||
/// something that isn't supported, and should be an error.
|
||||
/// Errors will only be emitted (by `linker::zombies`) for reachable zombies.
|
||||
pub fn zombie_with_span(&self, word: Word, span: Span, reason: &str) {
|
||||
if self.is_system_crate(span) {
|
||||
self.zombie_even_in_user_code(word, span, reason);
|
||||
} else {
|
||||
self.tcx.sess.span_err(span, reason);
|
||||
}
|
||||
}
|
||||
pub fn zombie_no_span(&self, word: Word, reason: &str) {
|
||||
self.zombie_with_span(word, DUMMY_SP, reason);
|
||||
}
|
||||
pub fn zombie_even_in_user_code(&self, word: Word, span: Span, reason: &str) {
|
||||
self.zombie_decorations.borrow_mut().insert(
|
||||
word,
|
||||
(
|
||||
@ -198,31 +186,8 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns `true` if the originating crate of `span` (which could very well
|
||||
/// be a different crate, e.g. a generic/`#[inline]` function, or a macro),
|
||||
/// is a "system crate", and therefore allowed to have some errors deferred
|
||||
/// as "zombies" (see `zombie_with_span`'s docs above for more details).
|
||||
pub fn is_system_crate(&self, span: Span) -> bool {
|
||||
// HACK(eddyb) this ignores `.lo` vs `.hi` potentially resulting in
|
||||
// different `SourceFile`s (which is likely a bug anyway).
|
||||
let cnum = self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.lookup_source_file(span.data().lo)
|
||||
.cnum;
|
||||
|
||||
self.tcx
|
||||
.get_attr(cnum.as_def_id(), sym::compiler_builtins)
|
||||
.is_some()
|
||||
|| [
|
||||
sym::core,
|
||||
self.sym.spirv_std,
|
||||
self.sym.libm,
|
||||
self.sym.num_traits,
|
||||
]
|
||||
.contains(&self.tcx.crate_name(cnum))
|
||||
pub fn zombie_no_span(&self, word: Word, reason: &str) {
|
||||
self.zombie_with_span(word, DUMMY_SP, reason);
|
||||
}
|
||||
|
||||
pub fn finalize_module(self) -> Module {
|
||||
@ -796,11 +761,9 @@ impl<'tcx> MiscMethods<'tcx> for CodegenCx<'tcx> {
|
||||
}
|
||||
.def(span, self);
|
||||
|
||||
if self.is_system_crate(span) {
|
||||
// Create these undefs up front instead of on demand in SpirvValue::def because
|
||||
// SpirvValue::def can't use cx.emit()
|
||||
self.def_constant(ty, SpirvConst::ZombieUndefForFnAddr);
|
||||
}
|
||||
// Create these `OpUndef`s up front, instead of on-demand in `SpirvValue::def`,
|
||||
// because `SpirvValue::def` can't use `cx.emit()`.
|
||||
self.def_constant(ty, SpirvConst::ZombieUndefForFnAddr);
|
||||
|
||||
SpirvValue {
|
||||
kind: SpirvValueKind::FnAddr {
|
||||
|
@ -103,27 +103,28 @@ impl SpirvType<'_> {
|
||||
Self::Bool => cx.emit_global().type_bool_id(id),
|
||||
Self::Integer(width, signedness) => {
|
||||
let result = cx.emit_global().type_int_id(id, width, signedness as u32);
|
||||
let u_or_i = if signedness { "i" } else { "u" };
|
||||
match width {
|
||||
8 if !cx.builder.has_capability(Capability::Int8) => cx
|
||||
.zombie_even_in_user_code(result, def_span, "u8 without OpCapability Int8"),
|
||||
16 if !cx.builder.has_capability(Capability::Int16) => cx
|
||||
.zombie_even_in_user_code(
|
||||
result,
|
||||
def_span,
|
||||
"u16 without OpCapability Int16",
|
||||
),
|
||||
64 if !cx.builder.has_capability(Capability::Int64) => cx
|
||||
.zombie_even_in_user_code(
|
||||
result,
|
||||
def_span,
|
||||
"u64 without OpCapability Int64",
|
||||
),
|
||||
8 | 16 | 32 | 64 => (),
|
||||
128 => cx.zombie_with_span(result, def_span, "u128"),
|
||||
other => cx.zombie_with_span(
|
||||
8 if !cx.builder.has_capability(Capability::Int8) => cx.zombie_with_span(
|
||||
result,
|
||||
def_span,
|
||||
&format!("Integer width {other} invalid for spir-v"),
|
||||
&format!("`{u_or_i}8` without `OpCapability Int8`"),
|
||||
),
|
||||
16 if !cx.builder.has_capability(Capability::Int16) => cx.zombie_with_span(
|
||||
result,
|
||||
def_span,
|
||||
&format!("`{u_or_i}16` without `OpCapability Int16`"),
|
||||
),
|
||||
64 if !cx.builder.has_capability(Capability::Int64) => cx.zombie_with_span(
|
||||
result,
|
||||
def_span,
|
||||
&format!("`{u_or_i}64` without `OpCapability Int64`"),
|
||||
),
|
||||
8 | 16 | 32 | 64 => {}
|
||||
w => cx.zombie_with_span(
|
||||
result,
|
||||
def_span,
|
||||
&format!("`{u_or_i}{w}` unsupported in SPIR-V"),
|
||||
),
|
||||
};
|
||||
result
|
||||
@ -131,17 +132,16 @@ impl SpirvType<'_> {
|
||||
Self::Float(width) => {
|
||||
let result = cx.emit_global().type_float_id(id, width);
|
||||
match width {
|
||||
64 if !cx.builder.has_capability(Capability::Float64) => cx
|
||||
.zombie_even_in_user_code(
|
||||
result,
|
||||
def_span,
|
||||
"f64 without OpCapability Float64",
|
||||
),
|
||||
64 if !cx.builder.has_capability(Capability::Float64) => cx.zombie_with_span(
|
||||
result,
|
||||
def_span,
|
||||
"`f64` without `OpCapability Float64`",
|
||||
),
|
||||
32 | 64 => (),
|
||||
other => cx.zombie_with_span(
|
||||
result,
|
||||
def_span,
|
||||
&format!("Float width {other} invalid for spir-v"),
|
||||
&format!("`f{other}` unsupported in SPIR-V"),
|
||||
),
|
||||
};
|
||||
result
|
||||
@ -217,11 +217,8 @@ impl SpirvType<'_> {
|
||||
.type_pointer(id, StorageClass::Generic, pointee);
|
||||
// no pointers to functions
|
||||
if let SpirvType::Function { .. } = cx.lookup_type(pointee) {
|
||||
cx.zombie_even_in_user_code(
|
||||
result,
|
||||
def_span,
|
||||
"function pointer types are not allowed",
|
||||
);
|
||||
// FIXME(eddyb) use the `SPV_INTEL_function_pointers` extension.
|
||||
cx.zombie_with_span(result, def_span, "function pointer types are not allowed");
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -293,11 +290,8 @@ impl SpirvType<'_> {
|
||||
.type_pointer(Some(id), StorageClass::Generic, pointee);
|
||||
// no pointers to functions
|
||||
if let SpirvType::Function { .. } = cx.lookup_type(pointee) {
|
||||
cx.zombie_even_in_user_code(
|
||||
result,
|
||||
def_span,
|
||||
"function pointer types are not allowed",
|
||||
);
|
||||
// FIXME(eddyb) use the `SPV_INTEL_function_pointers` extension.
|
||||
cx.zombie_with_span(result, def_span, "function pointer types are not allowed");
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: Cannot memcpy dynamically sized data
|
||||
error: cannot memcpy dynamically sized data
|
||||
--> $CORE_SRC/intrinsics.rs:2460:9
|
||||
|
|
||||
2460 | copy(src, dst, count)
|
||||
|
@ -1,29 +1,59 @@
|
||||
error: Cannot cast between pointer types
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:23:5
|
||||
|
|
||||
23 | f(&s.y);
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: from: *u32
|
||||
= note: to: *struct B { }
|
||||
|
||||
error: Cannot cast between pointer types
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:28:5
|
||||
|
|
||||
28 | f(&s.y);
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: from: *struct S<usize, usize> { u32, u32 }
|
||||
= note: to: *struct B { }
|
||||
|
||||
error: Cannot cast between pointer types
|
||||
error: cannot cast between pointer types
|
||||
from `*struct (usize, usize) { u32, u32 }`
|
||||
to `*struct B { }`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:33:5
|
||||
|
|
||||
33 | f(&s.y);
|
||||
| ^^^^^^^
|
||||
| ^
|
||||
|
|
||||
= note: from: *struct (usize, usize) { u32, u32 }
|
||||
= note: to: *struct B { }
|
||||
note: used from within `zst_member_ref_arg_broken::main_scalar_scalar_pair_nested`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:33:5
|
||||
|
|
||||
33 | f(&s.y);
|
||||
| ^
|
||||
note: called by `main_scalar_scalar_pair_nested`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:31:1
|
||||
|
|
||||
31 | #[spirv(fragment)]
|
||||
| ^
|
||||
|
||||
error: cannot cast between pointer types
|
||||
from `*struct (usize, usize) { u32, u32 }`
|
||||
to `*struct B { }`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:33:5
|
||||
|
|
||||
33 | f(&s.y);
|
||||
| ^
|
||||
|
|
||||
note: used from within `zst_member_ref_arg_broken::main_scalar`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:23:5
|
||||
|
|
||||
23 | f(&s.y);
|
||||
| ^
|
||||
note: called by `main_scalar`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:21:1
|
||||
|
|
||||
21 | #[spirv(fragment)]
|
||||
| ^
|
||||
|
||||
error: cannot cast between pointer types
|
||||
from `*struct (usize, usize) { u32, u32 }`
|
||||
to `*struct B { }`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:33:5
|
||||
|
|
||||
33 | f(&s.y);
|
||||
| ^
|
||||
|
|
||||
note: used from within `zst_member_ref_arg_broken::main_scalar_pair`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:28:5
|
||||
|
|
||||
28 | f(&s.y);
|
||||
| ^
|
||||
note: called by `main_scalar_pair`
|
||||
--> $DIR/zst_member_ref_arg-broken.rs:26:1
|
||||
|
|
||||
26 | #[spirv(fragment)]
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user