diff --git a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs index bd8f614569..ebd37a9ad7 100644 --- a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs +++ b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs @@ -237,10 +237,18 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> super::Result<() let mut any_err = None; for inst in module.functions[index].all_inst_iter() { if inst.class.opcode == Op::FunctionCall { - let callee = func_id_to_idx[&inst.operands[0].unwrap_id_ref()]; - let callee_had_err = - visit(sess, module, visited, stack, names, callee, func_id_to_idx).err(); - any_err = any_err.or(callee_had_err); + let callee_id = inst.operands[0].unwrap_id_ref(); + if let Some(&callee) = func_id_to_idx.get(&callee_id) { + if let Err(e) = + visit(sess, module, visited, stack, names, callee, func_id_to_idx) + { + any_err = any_err.or(Some(e)); + } + } else { + // Indirect or external callee: nothing to traverse. + // Keep scanning this function for forbidden fragment ops. + continue; + } } if matches!( inst.class.opcode, diff --git a/tests/compiletests/ui/lang/issue-452.rs b/tests/compiletests/ui/lang/issue-452.rs new file mode 100644 index 0000000000..585ff99183 --- /dev/null +++ b/tests/compiletests/ui/lang/issue-452.rs @@ -0,0 +1,18 @@ +// build-fail + +use spirv_std::spirv; + +#[derive(Clone, Copy)] +struct Position(u32); + +fn use_cmp(cmp: fn(&Position) -> u32) { + let a = Position(0); + let b = Position(1); + + let _ = if cmp(&a) <= cmp(&b) { a } else { b }; +} + +#[spirv(compute(threads(1)))] +pub fn main() { + use_cmp(|p| p.0); +} diff --git a/tests/compiletests/ui/lang/issue-452.stderr b/tests/compiletests/ui/lang/issue-452.stderr new file mode 100644 index 0000000000..adc228530a --- /dev/null +++ b/tests/compiletests/ui/lang/issue-452.stderr @@ -0,0 +1,47 @@ +error: function pointer types are not allowed + --> $DIR/issue-452.rs:8:1 + | +LL | fn use_cmp(cmp: fn(&Position) -> u32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: used by unnamed global (%10) +note: used from within `issue_452::use_cmp` + --> $DIR/issue-452.rs:8:4 + | +LL | fn use_cmp(cmp: fn(&Position) -> u32) { + | ^^^^^^^ +note: called by `issue_452::main` + --> $DIR/issue-452.rs:17:5 + | +LL | use_cmp(|p| p.0); + | ^^^^^^^^^^^^^^^^ +note: called by `main` + --> $DIR/issue-452.rs:16:8 + | +LL | pub fn main() { + | ^^^^ + +error: indirect calls are not supported in SPIR-V + --> $DIR/issue-452.rs:12:27 + | +LL | let _ = if cmp(&a) <= cmp(&b) { a } else { b }; + | ^^^^^^^ + | +note: used from within `issue_452::use_cmp` + --> $DIR/issue-452.rs:8:4 + | +LL | fn use_cmp(cmp: fn(&Position) -> u32) { + | ^^^^^^^ +note: called by `issue_452::main` + --> $DIR/issue-452.rs:17:5 + | +LL | use_cmp(|p| p.0); + | ^^^^^^^^^^^^^^^^ +note: called by `main` + --> $DIR/issue-452.rs:16:8 + | +LL | pub fn main() { + | ^^^^ + +error: aborting due to 2 previous errors +