diff --git a/src/analyze/basic_block.rs b/src/analyze/basic_block.rs index 97cc7f89..cf0654e9 100644 --- a/src/analyze/basic_block.rs +++ b/src/analyze/basic_block.rs @@ -1067,9 +1067,12 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> { ) -> rty::Type { if let Some(def_ty) = self.ctx.def_ty_with_args(def_id, args) { let (impl_def_id, impl_args) = self.resolve_fn_def(def_id, args); - // otherwise nothing asks for a deferred impl method's type and its body goes unchecked + // an impl method annotated with its own spec is checked against that spec, not + // against the trait method's type, so the call must assume the impl's type if impl_def_id != def_id { - let _ = self.ctx.def_ty_with_args(impl_def_id, impl_args); + if let Some(impl_ty) = self.ctx.def_ty_with_args(impl_def_id, impl_args) { + return impl_ty.ty; + } } return def_ty.ty; } diff --git a/tests/ui/fail/trait_default_override_callable.rs b/tests/ui/fail/trait_default_override_callable.rs new file mode 100644 index 00000000..bb62b96a --- /dev/null +++ b/tests/ui/fail/trait_default_override_callable.rs @@ -0,0 +1,21 @@ +//@error-in-other-file: Unsat +//@compile-flags: -C debug-assertions=off + +trait Tr { + fn m(&self) -> i64 { + 2 + } +} + +struct A; + +impl Tr for A { + #[thrust::callable] + fn m(&self) -> i64 { + 1 + } +} + +fn main() { + assert!(A.m() == 2); +} diff --git a/tests/ui/pass/trait_default_override_callable.rs b/tests/ui/pass/trait_default_override_callable.rs new file mode 100644 index 00000000..4d927b5b --- /dev/null +++ b/tests/ui/pass/trait_default_override_callable.rs @@ -0,0 +1,21 @@ +//@check-pass +//@compile-flags: -C debug-assertions=off + +trait Tr { + fn m(&self) -> i64 { + 2 + } +} + +struct A; + +impl Tr for A { + #[thrust::callable] + fn m(&self) -> i64 { + 1 + } +} + +fn main() { + let _ = A.m(); +}