Auto merge of #144166 - matthiaskrgr:rollup-wccepuo, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - rust-lang/rust#141076 (fix Zip unsoundness (again))
 - rust-lang/rust#142444 (adding run-make test to autodiff)
 - rust-lang/rust#143704 (Be a bit more careful around exotic cycles in in the inliner)
 - rust-lang/rust#144073 (Don't test panic=unwind in panic_main.rs on Fuchsia)
 - rust-lang/rust#144083 (miri sleep tests: increase slack)
 - rust-lang/rust#144092 (bootstrap: Detect musl hosts)
 - rust-lang/rust#144098 (Do not lint private-in-public for RPITIT)
 - rust-lang/rust#144103 (Rename `emit_unless` to `emit_unless_delay`)
 - rust-lang/rust#144108 (Ignore tests/run-make/link-eh-frame-terminator/rmake.rs when cross-compiling)
 - rust-lang/rust#144115 (fix outdated comment)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-07-19 11:10:04 +00:00
95 changed files with 1785 additions and 168 deletions
+1 -1
View File
@@ -1421,7 +1421,7 @@ pub fn emit(self) -> G::EmitResult {
///
/// See `emit` and `delay_as_bug` for details.
#[track_caller]
pub fn emit_unless(mut self, delay: bool) -> G::EmitResult {
pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
if delay {
self.downgrade_to_delayed_bug();
}
@@ -1173,7 +1173,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
bounds_span,
where_span,
})
.emit_unless(delay);
.emit_unless_delay(delay);
Err(reported)
}
@@ -1481,7 +1481,7 @@ fn compare_self_type<'tcx>(
} else {
err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
}
return Err(err.emit_unless(delay));
return Err(err.emit_unless_delay(delay));
}
(true, false) => {
@@ -1502,7 +1502,7 @@ fn compare_self_type<'tcx>(
err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
}
return Err(err.emit_unless(delay));
return Err(err.emit_unless_delay(delay));
}
}
@@ -1662,7 +1662,7 @@ fn compare_number_of_generics<'tcx>(
err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
}
let reported = err.emit_unless(delay);
let reported = err.emit_unless_delay(delay);
err_occurred = Some(reported);
}
}
@@ -1745,7 +1745,7 @@ fn compare_number_of_method_arguments<'tcx>(
),
);
return Err(err.emit_unless(delay));
return Err(err.emit_unless_delay(delay));
}
Ok(())
@@ -1872,7 +1872,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) -> Self::Result {
);
};
}
error_found = Some(err.emit_unless(delay));
error_found = Some(err.emit_unless_delay(delay));
}
}
if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
@@ -1974,7 +1974,7 @@ fn compare_generic_param_kinds<'tcx>(
err.span_label(impl_header_span, "");
err.span_label(param_impl_span, make_param_message("found", param_impl));
let reported = err.emit_unless(delay);
let reported = err.emit_unless_delay(delay);
return Err(reported);
}
}
@@ -2495,7 +2495,7 @@ fn deny_non_region_late_bound(
format!("late-bound {what} parameter not allowed on {where_}"),
);
let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
let guar = diag.emit_unless_delay(!tcx.features().non_lifetime_binders() || !first);
first = false;
*arg = ResolvedArg::Error(guar);
@@ -570,7 +570,7 @@ pub(crate) fn check_generic_arg_count(
gen_args,
def_id,
))
.emit_unless(all_params_are_binded)
.emit_unless_delay(all_params_are_binded)
});
Err(reported)
+1 -1
View File
@@ -1775,7 +1775,7 @@ pub(crate) fn coerce_inner<'a>(
);
}
let reported = err.emit_unless(unsized_return);
let reported = err.emit_unless_delay(unsized_return);
self.final_ty = Some(Ty::new_error(fcx.tcx, reported));
}
+3 -3
View File
@@ -1549,7 +1549,7 @@ fn expr_assign_expected_bool_error(
// If the assignment expression itself is ill-formed, don't
// bother emitting another error
err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error())
err.emit_unless_delay(lhs_ty.references_error() || rhs_ty.references_error())
}
pub(super) fn check_expr_let(
@@ -3865,7 +3865,7 @@ fn check_expr_offset_of(
self.dcx()
.create_err(NoVariantNamed { span: ident.span, ident, ty: container })
.with_span_label(field.span, "variant not found")
.emit_unless(container.references_error());
.emit_unless_delay(container.references_error());
break;
};
let Some(&subfield) = fields.next() else {
@@ -3897,7 +3897,7 @@ fn check_expr_offset_of(
enum_span: field.span,
field_span: subident.span,
})
.emit_unless(container.references_error());
.emit_unless_delay(container.references_error());
break;
};
@@ -700,6 +700,10 @@ struct LLVMRustSanitizerOptions {
#ifdef ENZYME
extern "C" void registerEnzymeAndPassPipeline(llvm::PassBuilder &PB,
/* augmentPassBuilder */ bool);
extern "C" {
extern llvm::cl::opt<std::string> EnzymeFunctionToAnalyze;
}
#endif
extern "C" LLVMRustResult LLVMRustOptimize(
@@ -1069,6 +1073,15 @@ extern "C" LLVMRustResult LLVMRustOptimize(
return LLVMRustResult::Failure;
}
// Check if PrintTAFn was used and add type analysis pass if needed
if (!EnzymeFunctionToAnalyze.empty()) {
if (auto Err = PB.parsePassPipeline(MPM, "print-type-analysis")) {
std::string ErrMsg = toString(std::move(Err));
LLVMRustSetLastError(ErrMsg.c_str());
return LLVMRustResult::Failure;
}
}
if (PrintAfterEnzyme) {
// Handle the Rust flag `-Zautodiff=PrintModAfter`.
std::string Banner = "Module after EnzymeNewPM";
@@ -64,15 +64,15 @@ fn process<'tcx>(
typing_env: ty::TypingEnv<'tcx>,
caller: ty::Instance<'tcx>,
target: LocalDefId,
seen: &mut FxHashSet<ty::Instance<'tcx>>,
seen: &mut FxHashMap<ty::Instance<'tcx>, bool>,
involved: &mut FxHashSet<LocalDefId>,
recursion_limiter: &mut FxHashMap<DefId, usize>,
recursion_limit: Limit,
) -> bool {
trace!(%caller);
let mut cycle_found = false;
let mut reaches_root = false;
for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
for &(callee_def_id, args) in tcx.mir_inliner_callees(caller.def) {
let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions(
tcx,
typing_env,
@@ -81,14 +81,17 @@ fn process<'tcx>(
trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping");
continue;
};
let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else {
trace!(?callee, "cannot resolve, skipping");
let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee_def_id, args)
else {
trace!(?callee_def_id, "cannot resolve, skipping");
continue;
};
// Found a path.
if callee.def_id() == target.to_def_id() {
cycle_found = true;
reaches_root = true;
seen.insert(callee, true);
continue;
}
if tcx.is_constructor(callee.def_id()) {
@@ -101,10 +104,17 @@ fn process<'tcx>(
continue;
}
if seen.insert(callee) {
let callee_reaches_root = if let Some(&c) = seen.get(&callee) {
// Even if we have seen this callee before, and thus don't need
// to recurse into it, we still need to propagate whether it reaches
// the root so that we can mark all the involved callers, in case we
// end up reaching that same recursive callee through some *other* cycle.
c
} else {
seen.insert(callee, false);
let recursion = recursion_limiter.entry(callee.def_id()).or_default();
trace!(?callee, recursion = *recursion);
let found_recursion = if recursion_limit.value_within_limit(*recursion) {
let callee_reaches_root = if recursion_limit.value_within_limit(*recursion) {
*recursion += 1;
ensure_sufficient_stack(|| {
process(
@@ -122,17 +132,19 @@ fn process<'tcx>(
// Pessimistically assume that there could be recursion.
true
};
if found_recursion {
if let Some(callee) = callee.def_id().as_local() {
// Calling `optimized_mir` of a non-local definition cannot cycle.
involved.insert(callee);
}
cycle_found = true;
seen.insert(callee, callee_reaches_root);
callee_reaches_root
};
if callee_reaches_root {
if let Some(callee_def_id) = callee.def_id().as_local() {
// Calling `optimized_mir` of a non-local definition cannot cycle.
involved.insert(callee_def_id);
}
reaches_root = true;
}
}
cycle_found
reaches_root
}
#[instrument(level = "debug", skip(tcx), ret)]
@@ -166,7 +178,7 @@ pub(crate) fn mir_callgraph_cyclic<'tcx>(
typing_env,
root_instance,
root,
&mut FxHashSet::default(),
&mut FxHashMap::default(),
&mut involved,
&mut FxHashMap::default(),
recursion_limit,
@@ -1219,10 +1219,8 @@ fn disqualify_auto_trait_candidate_due_to_possible_impl(
// the type (even if after unification and processing nested goals
// it does not hold) will disqualify the built-in auto impl.
//
// This differs from the current stable behavior and fixes #84857.
// Due to breakage found via crater, we currently instead lint
// patterns which can be used to exploit this unsoundness on stable,
// see #93367 for more details.
// We've originally had a more permissive check here which resulted
// in unsoundness, see #84857.
ty::Bool
| ty::Char
| ty::Int(_)
+8
View File
@@ -1624,6 +1624,10 @@ fn check_item(&mut self, id: ItemId) {
self.check(def_id, item_visibility, effective_vis).generics().predicates();
for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
continue;
}
self.check_assoc_item(assoc_item, item_visibility, effective_vis);
if assoc_item.is_type() {
@@ -1736,6 +1740,10 @@ fn check_item(&mut self, id: ItemId) {
check.ty().trait_ref();
for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
continue;
}
let impl_item_vis = if !of_trait {
min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
} else {
+1 -1
View File
@@ -2913,7 +2913,7 @@ fn with_generic_param_rib<'c, F>(
self.r
.dcx()
.create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span })
.emit_unless(is_raw_underscore_lifetime);
.emit_unless_delay(is_raw_underscore_lifetime);
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
continue;
+33 -41
View File
@@ -18,7 +18,6 @@ pub struct Zip<A, B> {
// index, len and a_len are only used by the specialized version of zip
index: usize,
len: usize,
a_len: usize,
}
impl<A: Iterator, B: Iterator> Zip<A, B> {
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
@@ -158,7 +157,6 @@ macro_rules! zip_impl_general_defaults {
b,
index: 0, // unused
len: 0, // unused
a_len: 0, // unused
}
}
@@ -299,9 +297,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
B: TrustedRandomAccess + Iterator,
{
fn new(a: A, b: B) -> Self {
let a_len = a.size();
let len = cmp::min(a_len, b.size());
Zip { a, b, index: 0, len, a_len }
let len = cmp::min(a.size(), b.size());
Zip { a, b, index: 0, len }
}
#[inline]
@@ -315,17 +312,6 @@ fn next(&mut self) -> Option<(A::Item, B::Item)> {
unsafe {
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
}
} else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len {
let i = self.index;
// as above, increment before executing code that may panic
self.index += 1;
self.len += 1;
// match the base implementation's potential side effects
// SAFETY: we just checked that `i` < `self.a.len()`
unsafe {
self.a.__iterator_get_unchecked(i);
}
None
} else {
None
}
@@ -371,36 +357,42 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator,
{
if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
let sz_a = self.a.size();
let sz_b = self.b.size();
// Adjust a, b to equal length, make sure that only the first call
// of `next_back` does this, otherwise we will break the restriction
// on calls to `self.next_back()` after calling `get_unchecked()`.
if sz_a != sz_b {
// No effects when the iterator is exhausted, to reduce the number of
// cases the unsafe code has to handle.
// See #137255 for a case where where too many epicycles lead to unsoundness.
if self.index < self.len {
let old_len = self.len;
// since get_unchecked and the side-effecting code can execute user code
// which can panic we decrement the counter beforehand
// so that the same index won't be accessed twice, as required by TrustedRandomAccess.
// Additionally this will ensure that the side-effects code won't run a second time.
self.len -= 1;
// Adjust a, b to equal length if we're iterating backwards.
if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
// note if some forward-iteration already happened then these aren't the real
// remaining lengths of the inner iterators, so we have to relate them to
// Zip's internal length-tracking.
let sz_a = self.a.size();
if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
for _ in 0..sz_a - self.len {
// since next_back() may panic we increment the counters beforehand
// to keep Zip's state in sync with the underlying iterator source
self.a_len -= 1;
self.a.next_back();
}
debug_assert_eq!(self.a_len, self.len);
}
let sz_b = self.b.size();
if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
for _ in 0..sz_b - self.len {
self.b.next_back();
// This condition can and must only be true on the first `next_back` call,
// otherwise we will break the restriction on calls to `self.next_back()`
// after calling `get_unchecked()`.
if sz_a != sz_b && (old_len == sz_a || old_len == sz_b) {
if A::MAY_HAVE_SIDE_EFFECT && sz_a > old_len {
for _ in 0..sz_a - old_len {
self.a.next_back();
}
}
if B::MAY_HAVE_SIDE_EFFECT && sz_b > old_len {
for _ in 0..sz_b - old_len {
self.b.next_back();
}
}
debug_assert_eq!(self.a.size(), self.b.size());
}
}
}
if self.index < self.len {
// since get_unchecked executes code which can panic we increment the counters beforehand
// so that the same index won't be accessed twice, as required by TrustedRandomAccess
self.len -= 1;
self.a_len -= 1;
let i = self.len;
// SAFETY: `i` is smaller than the previous value of `self.len`,
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
@@ -31,7 +31,8 @@ fn test_cloned_side_effects() {
.zip(&[1]);
for _ in iter {}
}
assert_eq!(count, 2);
// Zip documentation provides some leeway about side-effects
assert!([1, 2].iter().any(|v| *v == count));
}
#[test]
+86 -33
View File
@@ -107,9 +107,19 @@ fn test_zip_next_back_side_effects_exhausted() {
iter.next();
iter.next();
iter.next();
iter.next();
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
assert!(a.starts_with(&[1, 2, 3]));
let a_len = a.len();
// Tail-side-effects of forward-iteration are "at most one" per next().
// And for reverse iteration we don't guarantee much either.
// But we can put some bounds on the possible behaviors.
assert!(a_len <= 6);
assert!(a_len >= 3);
a.sort();
assert_eq!(a, &[1, 2, 3, 4, 5, 6][..a.len()]);
assert_eq!(b, vec![200, 300, 400]);
}
@@ -120,7 +130,8 @@ fn test_zip_cloned_sideffectful() {
for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}
assert_eq!(&xs, &[1, 1, 1, 0][..]);
// Zip documentation permits either case.
assert!([&[1, 1, 1, 0], &[1, 1, 0, 0]].iter().any(|v| &xs == *v));
assert_eq!(&ys, &[1, 1][..]);
let xs = [CountClone::new(), CountClone::new()];
@@ -139,7 +150,8 @@ fn test_zip_map_sideffectful() {
for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}
assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
// Zip documentation permits either case.
assert!([&[1, 1, 1, 1, 1, 0], &[1, 1, 1, 1, 0, 0]].iter().any(|v| &xs == *v));
assert_eq!(&ys, &[1, 1, 1, 1]);
let mut xs = [0; 4];
@@ -168,7 +180,8 @@ fn test_zip_map_rev_sideffectful() {
{
let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1));
(&mut it).take(5).count();
// the current impl only trims the tails if the iterator isn't exhausted
(&mut it).take(3).count();
it.next_back();
}
assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]);
@@ -211,9 +224,18 @@ fn test_zip_nth_back_side_effects_exhausted() {
iter.next();
iter.next();
iter.next();
iter.next();
assert_eq!(iter.next(), None);
assert_eq!(iter.nth_back(0), None);
assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
assert!(a.starts_with(&[1, 2, 3]));
let a_len = a.len();
// Tail-side-effects of forward-iteration are "at most one" per next().
// And for reverse iteration we don't guarantee much either.
// But we can put some bounds on the possible behaviors.
assert!(a_len <= 6);
assert!(a_len >= 3);
a.sort();
assert_eq!(a, &[1, 2, 3, 4, 5, 6][..a.len()]);
assert_eq!(b, vec![200, 300, 400]);
}
@@ -237,32 +259,6 @@ fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
assert_eq!(z2.next().unwrap(), ((1, 1), 1));
}
#[test]
#[cfg(panic = "unwind")]
fn test_zip_trusted_random_access_next_back_drop() {
use std::panic::{AssertUnwindSafe, catch_unwind};
let mut counter = 0;
let it = [42].iter().map(|e| {
let c = counter;
counter += 1;
if c == 0 {
panic!("bomb");
}
e
});
let it2 = [(); 0].iter();
let mut zip = it.zip(it2);
catch_unwind(AssertUnwindSafe(|| {
zip.next_back();
}))
.unwrap_err();
assert!(zip.next().is_none());
assert_eq!(counter, 1);
}
#[test]
fn test_double_ended_zip() {
let xs = [1, 2, 3, 4, 5, 6];
@@ -275,6 +271,63 @@ fn test_double_ended_zip() {
assert_eq!(it.next(), None);
}
#[test]
#[cfg(panic = "unwind")]
/// Regresion test for #137255
/// A previous implementation of Zip TrustedRandomAccess specializations tried to do a lot of work
/// to preserve side-effects of equalizing the iterator lengths during backwards iteration.
/// This lead to several cases of unsoundness, twice due to being left in an inconsistent state
/// after panics.
/// The new implementation does not try as hard, but we still need panic-safety.
fn test_nested_zip_panic_safety() {
use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
use std::sync::atomic::{AtomicUsize, Ordering};
let mut panic = true;
// keeps track of how often element get visited, must be at most once each
let witness = [8, 9, 10, 11, 12].map(|i| (i, AtomicUsize::new(0)));
let a = witness.as_slice().iter().map(|e| {
e.1.fetch_add(1, Ordering::Relaxed);
if panic {
panic = false;
resume_unwind(Box::new(()))
}
e.0
});
// shorter than `a`, so `a` will get trimmed
let b = [1, 2, 3, 4].as_slice().iter().copied();
// shorter still, so `ab` will get trimmed.`
let c = [5, 6, 7].as_slice().iter().copied();
// This will panic during backwards trimming.
let ab = zip(a, b);
// This being Zip + TrustedRandomAccess means it will only call `next_back``
// during trimming and otherwise do calls `__iterator_get_unchecked` on `ab`.
let mut abc = zip(ab, c);
assert_eq!(abc.len(), 3);
// This will first trigger backwards trimming before it would normally obtain the
// actual element if it weren't for the panic.
// This used to corrupt the internal state of `abc`, which then lead to
// TrustedRandomAccess safety contract violations in calls to `ab`,
// which ultimately lead to UB.
catch_unwind(AssertUnwindSafe(|| abc.next_back())).ok();
// check for sane outward behavior after the panic, which indicates a sane internal state.
// Technically these outcomes are not required because a panic frees us from correctness obligations.
assert_eq!(abc.len(), 2);
assert_eq!(abc.next(), Some(((8, 1), 5)));
assert_eq!(abc.next_back(), Some(((9, 2), 6)));
for (i, (_, w)) in witness.iter().enumerate() {
let v = w.load(Ordering::Relaxed);
// required by TRA contract
assert!(v <= 1, "expected idx {i} to be visited at most once, actual: {v}");
}
// Trimming panicked and should only run once, so this one won't be visited.
// Implementation detail, but not trying to run it again is what keeps
// things simple.
assert_eq!(witness[3].1.load(Ordering::Relaxed), 0);
}
#[test]
fn test_issue_82282() {
fn overflowed_zip(arr: &[i32]) -> impl Iterator<Item = (i32, &())> {
+6 -1
View File
@@ -8,6 +8,7 @@ import re
import shutil
import subprocess
import sys
import sysconfig
import tarfile
import tempfile
@@ -333,7 +334,11 @@ def default_build_triple(verbose):
if ostype == "Android":
kernel = "linux-android"
else:
kernel = "unknown-linux-gnu"
python_soabi = sysconfig.get_config_var("SOABI")
if python_soabi is not None and "musl" in python_soabi:
kernel = "unknown-linux-musl"
else:
kernel = "unknown-linux-gnu"
elif kernel == "SunOS":
kernel = "pc-solaris"
# On Solaris, uname -m will return a machine classification instead
@@ -336,7 +336,7 @@ fn test_nanosleep() {
let remainder = ptr::null_mut::<libc::timespec>();
let is_error = unsafe { libc::nanosleep(&duration_zero, remainder) };
assert_eq!(is_error, 0);
assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
let start_test_sleep = Instant::now();
let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 };
@@ -390,7 +390,7 @@ pub fn absolute() {
)
};
assert_eq!(error, 0);
assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
let start_test_sleep = Instant::now();
let hunderd_millis_after_start = add_100_millis(timespec_now(libc::CLOCK_MONOTONIC));
@@ -417,7 +417,7 @@ pub fn relative() {
libc::clock_nanosleep(libc::CLOCK_MONOTONIC, NO_FLAGS, &duration_zero, remainder)
};
assert_eq!(error, 0);
assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
let start_test_sleep = Instant::now();
let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 };
@@ -0,0 +1,48 @@
- // MIR for `a` before Inline
+ // MIR for `a` after Inline
fn a() -> () {
let mut _0: ();
let _1: ();
let mut _2: ();
let _3: ();
let mut _4: ();
+ let mut _5: fn() {a};
+ let mut _6: fn() {b};
+ scope 1 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
+ }
+ scope 2 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
+ }
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = ();
- _1 = <fn() {a} as FnOnce<()>>::call_once(a, move _2) -> [return: bb1, unwind unreachable];
+ StorageLive(_5);
+ _5 = a;
+ _1 = move _5() -> [return: bb1, unwind unreachable];
}
bb1: {
+ StorageDead(_5);
StorageDead(_2);
StorageDead(_1);
StorageLive(_3);
StorageLive(_4);
_4 = ();
- _3 = <fn() {b} as FnOnce<()>>::call_once(b, move _4) -> [return: bb2, unwind unreachable];
+ StorageLive(_6);
+ _6 = b;
+ _3 = move _6() -> [return: bb2, unwind unreachable];
}
bb2: {
+ StorageDead(_6);
StorageDead(_4);
StorageDead(_3);
_0 = const ();
return;
}
}
@@ -0,0 +1,48 @@
- // MIR for `a` before Inline
+ // MIR for `a` after Inline
fn a() -> () {
let mut _0: ();
let _1: ();
let mut _2: ();
let _3: ();
let mut _4: ();
+ let mut _5: fn() {a};
+ let mut _6: fn() {b};
+ scope 1 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
+ }
+ scope 2 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
+ }
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = ();
- _1 = <fn() {a} as FnOnce<()>>::call_once(a, move _2) -> [return: bb1, unwind continue];
+ StorageLive(_5);
+ _5 = a;
+ _1 = move _5() -> [return: bb1, unwind continue];
}
bb1: {
+ StorageDead(_5);
StorageDead(_2);
StorageDead(_1);
StorageLive(_3);
StorageLive(_4);
_4 = ();
- _3 = <fn() {b} as FnOnce<()>>::call_once(b, move _4) -> [return: bb2, unwind continue];
+ StorageLive(_6);
+ _6 = b;
+ _3 = move _6() -> [return: bb2, unwind continue];
}
bb2: {
+ StorageDead(_6);
StorageDead(_4);
StorageDead(_3);
_0 = const ();
return;
}
}
@@ -0,0 +1,48 @@
- // MIR for `b` before Inline
+ // MIR for `b` after Inline
fn b() -> () {
let mut _0: ();
let _1: ();
let mut _2: ();
let _3: ();
let mut _4: ();
+ let mut _5: fn() {b};
+ let mut _6: fn() {a};
+ scope 1 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
+ }
+ scope 2 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
+ }
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = ();
- _1 = <fn() {b} as FnOnce<()>>::call_once(b, move _2) -> [return: bb1, unwind unreachable];
+ StorageLive(_5);
+ _5 = b;
+ _1 = move _5() -> [return: bb1, unwind unreachable];
}
bb1: {
+ StorageDead(_5);
StorageDead(_2);
StorageDead(_1);
StorageLive(_3);
StorageLive(_4);
_4 = ();
- _3 = <fn() {a} as FnOnce<()>>::call_once(a, move _4) -> [return: bb2, unwind unreachable];
+ StorageLive(_6);
+ _6 = a;
+ _3 = move _6() -> [return: bb2, unwind unreachable];
}
bb2: {
+ StorageDead(_6);
StorageDead(_4);
StorageDead(_3);
_0 = const ();
return;
}
}
@@ -0,0 +1,48 @@
- // MIR for `b` before Inline
+ // MIR for `b` after Inline
fn b() -> () {
let mut _0: ();
let _1: ();
let mut _2: ();
let _3: ();
let mut _4: ();
+ let mut _5: fn() {b};
+ let mut _6: fn() {a};
+ scope 1 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
+ }
+ scope 2 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
+ }
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = ();
- _1 = <fn() {b} as FnOnce<()>>::call_once(b, move _2) -> [return: bb1, unwind continue];
+ StorageLive(_5);
+ _5 = b;
+ _1 = move _5() -> [return: bb1, unwind continue];
}
bb1: {
+ StorageDead(_5);
StorageDead(_2);
StorageDead(_1);
StorageLive(_3);
StorageLive(_4);
_4 = ();
- _3 = <fn() {a} as FnOnce<()>>::call_once(a, move _4) -> [return: bb2, unwind continue];
+ StorageLive(_6);
+ _6 = a;
+ _3 = move _6() -> [return: bb2, unwind continue];
}
bb2: {
+ StorageDead(_6);
StorageDead(_4);
StorageDead(_3);
_0 = const ();
return;
}
}
+22
View File
@@ -0,0 +1,22 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
// skip-filecheck
//@ test-mir-pass: Inline
//@ edition: 2021
//@ compile-flags: -Zinline-mir --crate-type=lib
// EMIT_MIR inline_double_cycle.a.Inline.diff
// EMIT_MIR inline_double_cycle.b.Inline.diff
#![feature(fn_traits)]
#[inline]
pub fn a() {
FnOnce::call_once(a, ());
FnOnce::call_once(b, ());
}
#[inline]
pub fn b() {
FnOnce::call_once(b, ());
FnOnce::call_once(a, ());
}
@@ -0,0 +1,13 @@
# Autodiff Type-Trees Type Analysis Tests
This directory contains run-make tests for the autodiff type-trees type analysis functionality. These tests verify that the autodiff compiler correctly analyzes and tracks type information for different Rust types during automatic differentiation.
## What These Tests Do
Each test compiles a simple Rust function with the `#[autodiff_reverse]` attribute and verifies that the compiler:
1. **Correctly identifies type information** in the generated LLVM IR
2. **Tracks type annotations** for variables and operations
3. **Preserves type context** through the autodiff transformation process
The tests capture the stdout from the autodiff compiler (which contains type analysis information) and verify it matches expected patterns using FileCheck.
@@ -0,0 +1,26 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 4, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 4, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,20 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &[f32; 3]) -> f32 {
x[0] * x[0] + x[1] * x[1] + x[2] * x[2]
}
fn main() {
let x = [1.0f32, 2.0, 3.0];
let mut df_dx = [0.0f32; 3];
let out = callee(&x);
let out_ = d_square(&x, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(2.0, df_dx[0]);
assert_eq!(4.0, df_dx[1]);
assert_eq!(6.0, df_dx[2]);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("array.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("array.stdout", stdout);
rfs::write("array.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("array.check").stdin_buf(rfs::read("array.stdout")).run();
}
@@ -0,0 +1,54 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ 0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x [2 x float]], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x float], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ 0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x [2 x float]], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x float], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,32 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &[[[f32; 2]; 2]; 2]) -> f32 {
let mut sum = 0.0;
for i in 0..2 {
for j in 0..2 {
for k in 0..2 {
sum += x[i][j][k] * x[i][j][k];
}
}
}
sum
}
fn main() {
let x = [[[1.0f32, 2.0], [3.0, 4.0]], [[5.0, 6.0], [7.0, 8.0]]];
let mut df_dx = [[[0.0f32; 2]; 2]; 2];
let out = callee(&x);
let out_ = d_square(&x, &mut df_dx, 1.0);
assert_eq!(out, out_);
for i in 0..2 {
for j in 0..2 {
for k in 0..2 {
assert_eq!(df_dx[i][j][k], 2.0 * x[i][j][k]);
}
}
}
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("array3d.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("array3d.stdout", stdout);
rfs::write("array3d.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("array3d.check").stdin_buf(rfs::read("array3d.stdout")).run();
}
@@ -0,0 +1,12 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !{{[0-9]+}}, !align !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !{{[0-9]+}}, !align !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,18 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &Box<f32>) -> f32 {
**x * **x
}
fn main() {
let x = Box::new(7.0f32);
let mut df_dx = Box::new(0.0f32);
let out = callee(&x);
let out_ = d_square(&x, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(14.0, *df_dx);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("box.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("box.stdout", stdout);
rfs::write("box.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("box.check").stdin_buf(rfs::read("box.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,18 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: *const f32) -> f32 {
unsafe { *x * *x }
}
fn main() {
let x: f32 = 7.0;
let out = callee(&x as *const f32);
let mut df_dx: f32 = 0.0;
let out_ = d_square(&x as *const f32, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(14.0, df_dx);
}
@@ -0,0 +1,31 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("const_pointer.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("const_pointer.stdout", stdout);
rfs::write("const_pointer.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck()
.patterns("const_pointer.check")
.stdin_buf(rfs::read("const_pointer.stdout"))
.run();
}
@@ -0,0 +1,12 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,19 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &f32) -> f32 {
*x * *x
}
fn main() {
let x: f32 = 7.0;
let mut df_dx: f32 = 0.0;
let out = callee(&x);
let out_ = d_square(&x, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(14.0, df_dx);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("f32.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("f32.stdout", stdout);
rfs::write("f32.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("f32.check").stdin_buf(rfs::read("f32.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Float@double} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@double}
// CHECK-DAG: %{{[0-9]+}} = load double, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@double}
// CHECK-DAG: %{{[0-9]+}} = fmul double %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@double}
// CHECK-DAG: ret double %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@double} |{[-1]:Pointer, [-1,0]:Float@double}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@double}
// CHECK-DAG: %{{[0-9]+}} = load double, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@double}
// CHECK-DAG: %{{[0-9]+}} = fmul double %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@double}
// CHECK-DAG: ret double %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,20 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_callee, Duplicated, Active)]
#[no_mangle]
fn callee(x: &f64) -> f64 {
x * x
}
fn main() {
let x = std::hint::black_box(3.0);
let output = callee(&x);
assert_eq!(9.0, output);
let mut df_dx = 0.0;
let output_ = d_callee(&x, &mut df_dx, 1.0);
assert_eq!(output, output_);
assert_eq!(6.0, df_dx);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("f64.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("f64.stdout", stdout);
rfs::write("f64.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("f64.check").stdin_buf(rfs::read("f64.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &i128) -> i128 {
*x * *x
}
fn main() {
let x: i128 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("i128.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("i128.stdout", stdout);
rfs::write("i128.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("i128.check").stdin_buf(rfs::read("i128.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &i16) -> i16 {
*x * *x
}
fn main() {
let x: i16 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("i16.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("i16.stdout", stdout);
rfs::write("i16.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("i16.check").stdin_buf(rfs::read("i16.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &i32) -> i32 {
*x * *x
}
fn main() {
let x: i32 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("i32.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("i32.stdout", stdout);
rfs::write("i32.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("i32.check").stdin_buf(rfs::read("i32.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &i8) -> i8 {
*x * *x
}
fn main() {
let x: i8 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("i8.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("i8.stdout", stdout);
rfs::write("i8.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("i8.check").stdin_buf(rfs::read("i8.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &isize) -> isize {
*x * *x
}
fn main() {
let x: isize = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("isize.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("isize.stdout", stdout);
rfs::write("isize.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("isize.check").stdin_buf(rfs::read("isize.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,18 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: *mut f32) -> f32 {
unsafe { *x * *x }
}
fn main() {
let mut x: f32 = 7.0;
let out = callee(&mut x as *mut f32);
let mut df_dx: f32 = 0.0;
let out_ = d_square(&mut x as *mut f32, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(14.0, df_dx);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("mut_pointer.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("mut_pointer.stdout", stdout);
rfs::write("mut_pointer.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("mut_pointer.check").stdin_buf(rfs::read("mut_pointer.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,18 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &mut f32) -> f32 {
*x * *x
}
fn main() {
let mut x: f32 = 7.0;
let mut df_dx: f32 = 0.0;
let out = callee(&mut x);
let out_ = d_square(&mut x, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(14.0, df_dx);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("mut_ref.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("mut_ref.stdout", stdout);
rfs::write("mut_ref.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("mut_ref.check").stdin_buf(rfs::read("mut_ref.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,18 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &f32) -> f32 {
*x * *x
}
fn main() {
let x: f32 = 7.0;
let mut df_dx: f32 = 0.0;
let out = callee(&x);
let out_ = d_square(&x, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(14.0, df_dx);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("ref.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("ref.stdout", stdout);
rfs::write("ref.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("ref.check").stdin_buf(rfs::read("ref.stdout")).run();
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("struct.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("struct.stdout", stdout);
rfs::write("struct.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("struct.check").stdin_buf(rfs::read("struct.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,23 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[derive(Copy, Clone)]
struct MyStruct {
f: f32,
}
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &MyStruct) -> f32 {
x.f * x.f
}
fn main() {
let x = MyStruct { f: 7.0 };
let mut df_dx = MyStruct { f: 0.0 };
let out = callee(&x);
let out_ = d_square(&x, &mut df_dx, 1.0);
assert_eq!(out, out_);
assert_eq!(14.0, df_dx.f);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("u128.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("u128.stdout", stdout);
rfs::write("u128.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("u128.check").stdin_buf(rfs::read("u128.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &u128) -> u128 {
*x * *x
}
fn main() {
let x: u128 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("u16.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("u16.stdout", stdout);
rfs::write("u16.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("u16.check").stdin_buf(rfs::read("u16.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &u16) -> u16 {
*x * *x
}
fn main() {
let x: u16 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("u32.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("u32.stdout", stdout);
rfs::write("u32.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("u32.check").stdin_buf(rfs::read("u32.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &u32) -> u32 {
*x * *x
}
fn main() {
let x: u32 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("u8.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("u8.stdout", stdout);
rfs::write("u8.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("u8.check").stdin_buf(rfs::read("u8.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &u8) -> u8 {
*x * *x
}
fn main() {
let x: u8 = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("union.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("union.stdout", stdout);
rfs::write("union.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("union.check").stdin_buf(rfs::read("union.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,20 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[allow(dead_code)]
union MyUnion {
f: f32,
i: i32,
}
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &MyUnion) -> f32 {
unsafe { x.f * x.f }
}
fn main() {
let x = MyUnion { f: 7.0 };
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("usize.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("usize.stdout", stdout);
rfs::write("usize.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("usize.check").stdin_buf(rfs::read("usize.stdout")).run();
}
@@ -0,0 +1,10 @@
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(x: &usize) -> usize {
*x * *x
}
fn main() {
let x: usize = 7;
let _ = callee(&x);
}
@@ -0,0 +1,28 @@
//@ needs-enzyme
//@ ignore-cross-compile
use std::fs;
use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
// Compile the Rust file with the required flags, capturing both stdout and stderr
let output = rustc()
.input("vec.rs")
.arg("-Zautodiff=Enable,PrintTAFn=callee")
.arg("-Zautodiff=NoPostopt")
.opt_level("3")
.arg("-Clto=fat")
.arg("-g")
.run();
let stdout = output.stdout_utf8();
let stderr = output.stderr_utf8();
// Write the outputs to files
rfs::write("vec.stdout", stdout);
rfs::write("vec.stderr", stderr);
// Run FileCheck on the stdout using the check file
llvm_filecheck().patterns("vec.check").stdin_buf(rfs::read("vec.stdout")).run();
}
@@ -0,0 +1,18 @@
// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer}
// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !102, !noundef !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 16, !dbg !{{[0-9]+}}: {[-1]:Pointer}
// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = icmp eq i64 %{{[0-9]+}}, 0, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %{{[0-9]+}} ], [ 0, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ -0.000000e+00, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: %{{[0-9]+}} = add nuw i64 %{{[0-9]+}}, 1, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: %{{[0-9]+}} = icmp eq i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
// CHECK-DAG: %{{[0-9]+}} = phi float [ -0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
@@ -0,0 +1,14 @@
#![feature(autodiff)]
use std::autodiff::autodiff_reverse;
#[autodiff_reverse(d_square, Duplicated, Active)]
#[no_mangle]
fn callee(arg: &std::vec::Vec<f32>) -> f32 {
arg.iter().sum()
}
fn main() {
let v = vec![1.0f32, 2.0, 3.0];
let _ = callee(&v);
}
@@ -9,6 +9,7 @@
//@ ignore-32bit
// Reason: the usage of a large array in the test causes an out-of-memory
// error on 32 bit systems.
//@ ignore-cross-compile
use run_make_support::{bin_name, llvm_objdump, run, rustc};
+3
View File
@@ -14,12 +14,15 @@
//@[unwind-zero] compile-flags: -Cpanic=unwind
//@[unwind-zero] exec-env:RUST_BACKTRACE=0
//@[unwind-zero] needs-unwind
//@[unwind-one] compile-flags: -Cpanic=unwind
//@[unwind-one] exec-env:RUST_BACKTRACE=1
//@[unwind-one] needs-unwind
//@[unwind-full] compile-flags: -Cpanic=unwind
//@[unwind-full] exec-env:RUST_BACKTRACE=full
//@[unwind-full] needs-unwind
//@ run-fail
//@ error-pattern:moop
+11 -1
View File
@@ -35,6 +35,7 @@ impl PubTr for Pub {
mod traits {
trait PrivTr {}
impl PrivTr for () {}
pub struct Pub<T>(T);
pub trait PubTr {}
@@ -45,7 +46,10 @@ pub trait Tr2<T: PrivTr> {} //~ ERROR trait `traits::PrivTr` is more private tha
pub trait Tr3 {
type Alias: PrivTr;
//~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::Alias`
fn f<T: PrivTr>(arg: T) {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
fn f<T: PrivTr>(arg: T) {}
//~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
fn g() -> impl PrivTr;
fn h() -> impl PrivTr {}
}
impl<T: PrivTr> Pub<T> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Pub<T>`
impl<T: PrivTr> PubTr for Pub<T> {} // OK, trait impl predicates
@@ -75,12 +79,18 @@ mod generics {
pub struct Pub<T = u8>(T);
trait PrivTr<T> {}
pub trait PubTr<T> {}
impl PrivTr<Priv<()>> for () {}
pub trait Tr1: PrivTr<Pub> {}
//~^ ERROR trait `generics::PrivTr<generics::Pub>` is more private than the item `generics::Tr1`
pub trait Tr2: PubTr<Priv> {} //~ ERROR type `generics::Priv` is more private than the item `generics::Tr2`
pub trait Tr3: PubTr<[Priv; 1]> {} //~ ERROR type `generics::Priv` is more private than the item `generics::Tr3`
pub trait Tr4: PubTr<Pub<Priv>> {} //~ ERROR type `generics::Priv` is more private than the item `Tr4`
pub trait Tr5 {
fn required() -> impl PrivTr<Priv<()>>;
fn provided() -> impl PrivTr<Priv<()>> {}
}
}
mod impls {
+37 -37
View File
@@ -130,7 +130,7 @@ LL | type Alias = Priv;
| ^^^^^^^^^^ can't leak private type
error: trait `traits::PrivTr` is more private than the item `traits::Alias`
--> $DIR/private-in-public-warn.rs:41:5
--> $DIR/private-in-public-warn.rs:42:5
|
LL | pub type Alias<T: PrivTr> = T;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ type alias `traits::Alias` is reachable at visibility `pub(crate)`
@@ -147,7 +147,7 @@ LL | #![deny(private_interfaces, private_bounds)]
| ^^^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr1`
--> $DIR/private-in-public-warn.rs:43:5
--> $DIR/private-in-public-warn.rs:44:5
|
LL | pub trait Tr1: PrivTr {}
| ^^^^^^^^^^^^^^^^^^^^^ trait `traits::Tr1` is reachable at visibility `pub(crate)`
@@ -159,7 +159,7 @@ LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr2`
--> $DIR/private-in-public-warn.rs:44:5
--> $DIR/private-in-public-warn.rs:45:5
|
LL | pub trait Tr2<T: PrivTr> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ trait `traits::Tr2` is reachable at visibility `pub(crate)`
@@ -171,7 +171,7 @@ LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr3::Alias`
--> $DIR/private-in-public-warn.rs:46:9
--> $DIR/private-in-public-warn.rs:47:9
|
LL | type Alias: PrivTr;
| ^^^^^^^^^^^^^^^^^^ associated type `traits::Tr3::Alias` is reachable at visibility `pub(crate)`
@@ -183,7 +183,7 @@ LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
--> $DIR/private-in-public-warn.rs:48:9
--> $DIR/private-in-public-warn.rs:49:9
|
LL | fn f<T: PrivTr>(arg: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits::Tr3::f` is reachable at visibility `pub(crate)`
@@ -195,7 +195,7 @@ LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Pub<T>`
--> $DIR/private-in-public-warn.rs:50:5
--> $DIR/private-in-public-warn.rs:54:5
|
LL | impl<T: PrivTr> Pub<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^ implementation `traits::Pub<T>` is reachable at visibility `pub(crate)`
@@ -207,103 +207,103 @@ LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Alias`
--> $DIR/private-in-public-warn.rs:59:5
--> $DIR/private-in-public-warn.rs:63:5
|
LL | pub type Alias<T> where T: PrivTr = T;
| ^^^^^^^^^^^^^^^^^ type alias `traits_where::Alias` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:55:5
--> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2`
--> $DIR/private-in-public-warn.rs:62:5
--> $DIR/private-in-public-warn.rs:66:5
|
LL | pub trait Tr2<T> where T: PrivTr {}
| ^^^^^^^^^^^^^^^^ trait `traits_where::Tr2` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:55:5
--> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr3::f`
--> $DIR/private-in-public-warn.rs:65:9
--> $DIR/private-in-public-warn.rs:69:9
|
LL | fn f<T>(arg: T) where T: PrivTr {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits_where::Tr3::f` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:55:5
--> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Pub<T>`
--> $DIR/private-in-public-warn.rs:68:5
--> $DIR/private-in-public-warn.rs:72:5
|
LL | impl<T> Pub<T> where T: PrivTr {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation `traits_where::Pub<T>` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:55:5
--> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `generics::PrivTr<generics::Pub>` is more private than the item `generics::Tr1`
--> $DIR/private-in-public-warn.rs:79:5
--> $DIR/private-in-public-warn.rs:84:5
|
LL | pub trait Tr1: PrivTr<Pub> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr1` is reachable at visibility `pub(crate)`
|
note: but trait `generics::PrivTr<generics::Pub>` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:76:5
--> $DIR/private-in-public-warn.rs:80:5
|
LL | trait PrivTr<T> {}
| ^^^^^^^^^^^^^^^
error: type `generics::Priv` is more private than the item `generics::Tr2`
--> $DIR/private-in-public-warn.rs:81:5
--> $DIR/private-in-public-warn.rs:86:5
|
LL | pub trait Tr2: PubTr<Priv> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr2` is reachable at visibility `pub(crate)`
|
note: but type `generics::Priv` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:74:5
--> $DIR/private-in-public-warn.rs:78:5
|
LL | struct Priv<T = u8>(T);
| ^^^^^^^^^^^^^^^^^^^
error: type `generics::Priv` is more private than the item `generics::Tr3`
--> $DIR/private-in-public-warn.rs:82:5
--> $DIR/private-in-public-warn.rs:87:5
|
LL | pub trait Tr3: PubTr<[Priv; 1]> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr3` is reachable at visibility `pub(crate)`
|
note: but type `generics::Priv` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:74:5
--> $DIR/private-in-public-warn.rs:78:5
|
LL | struct Priv<T = u8>(T);
| ^^^^^^^^^^^^^^^^^^^
error: type `generics::Priv` is more private than the item `Tr4`
--> $DIR/private-in-public-warn.rs:83:5
--> $DIR/private-in-public-warn.rs:88:5
|
LL | pub trait Tr4: PubTr<Pub<Priv>> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `Tr4` is reachable at visibility `pub(crate)`
|
note: but type `generics::Priv` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:74:5
--> $DIR/private-in-public-warn.rs:78:5
|
LL | struct Priv<T = u8>(T);
| ^^^^^^^^^^^^^^^^^^^
error[E0446]: private type `impls::Priv` in public interface
--> $DIR/private-in-public-warn.rs:109:9
--> $DIR/private-in-public-warn.rs:119:9
|
LL | struct Priv;
| ----------- `impls::Priv` declared as private
@@ -312,19 +312,19 @@ LL | type Alias = Priv;
| ^^^^^^^^^^ can't leak private type
error: type `aliases_pub::Priv` is more private than the item `aliases_pub::<impl Pub2>::f`
--> $DIR/private-in-public-warn.rs:180:9
--> $DIR/private-in-public-warn.rs:190:9
|
LL | pub fn f(arg: Priv) {}
| ^^^^^^^^^^^^^^^^^^^ associated function `aliases_pub::<impl Pub2>::f` is reachable at visibility `pub(crate)`
|
note: but type `aliases_pub::Priv` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:153:5
--> $DIR/private-in-public-warn.rs:163:5
|
LL | struct Priv;
| ^^^^^^^^^^^
error[E0446]: private type `aliases_pub::Priv` in public interface
--> $DIR/private-in-public-warn.rs:183:9
--> $DIR/private-in-public-warn.rs:193:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -333,7 +333,7 @@ LL | type Check = Priv;
| ^^^^^^^^^^ can't leak private type
error[E0446]: private type `aliases_pub::Priv` in public interface
--> $DIR/private-in-public-warn.rs:186:9
--> $DIR/private-in-public-warn.rs:196:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -342,7 +342,7 @@ LL | type Check = Priv;
| ^^^^^^^^^^ can't leak private type
error[E0446]: private type `aliases_pub::Priv` in public interface
--> $DIR/private-in-public-warn.rs:189:9
--> $DIR/private-in-public-warn.rs:199:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -351,7 +351,7 @@ LL | type Check = Priv;
| ^^^^^^^^^^ can't leak private type
error[E0446]: private type `aliases_pub::Priv` in public interface
--> $DIR/private-in-public-warn.rs:192:9
--> $DIR/private-in-public-warn.rs:202:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -360,43 +360,43 @@ LL | type Check = Priv;
| ^^^^^^^^^^ can't leak private type
error: trait `PrivTr1` is more private than the item `aliases_priv::Tr1`
--> $DIR/private-in-public-warn.rs:222:5
--> $DIR/private-in-public-warn.rs:232:5
|
LL | pub trait Tr1: PrivUseAliasTr {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr1` is reachable at visibility `pub(crate)`
|
note: but trait `PrivTr1` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:208:5
--> $DIR/private-in-public-warn.rs:218:5
|
LL | trait PrivTr1<T = u8> {
| ^^^^^^^^^^^^^^^^^^^^^
error: trait `PrivTr1<Priv2>` is more private than the item `aliases_priv::Tr2`
--> $DIR/private-in-public-warn.rs:224:5
--> $DIR/private-in-public-warn.rs:234:5
|
LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)`
|
note: but trait `PrivTr1<Priv2>` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:208:5
--> $DIR/private-in-public-warn.rs:218:5
|
LL | trait PrivTr1<T = u8> {
| ^^^^^^^^^^^^^^^^^^^^^
error: type `Priv2` is more private than the item `aliases_priv::Tr2`
--> $DIR/private-in-public-warn.rs:224:5
--> $DIR/private-in-public-warn.rs:234:5
|
LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)`
|
note: but type `Priv2` is only usable at visibility `pub(self)`
--> $DIR/private-in-public-warn.rs:206:5
--> $DIR/private-in-public-warn.rs:216:5
|
LL | struct Priv2;
| ^^^^^^^^^^^^
warning: bounds on generic parameters in type aliases are not enforced
--> $DIR/private-in-public-warn.rs:41:23
--> $DIR/private-in-public-warn.rs:42:23
|
LL | pub type Alias<T: PrivTr> = T;
| --^^^^^^
@@ -410,7 +410,7 @@ LL | pub type Alias<T: PrivTr> = T;
= note: `#[warn(type_alias_bounds)]` on by default
warning: where clauses on type aliases are not enforced
--> $DIR/private-in-public-warn.rs:59:29
--> $DIR/private-in-public-warn.rs:63:29
|
LL | pub type Alias<T> where T: PrivTr = T;
| ------^^^^^^^^^
@@ -1,5 +1,6 @@
pub struct OtherType;
pub trait OtherTrait {}
impl OtherTrait for OtherType {}
#[macro_export]
macro_rules! m {
+5 -1
View File
@@ -44,8 +44,12 @@ fn priv_fn(param: OtherType) {}
pub trait MyPubTrait {
type Foo: OtherTrait;
//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
fn required() -> impl OtherTrait;
fn provided() -> impl OtherTrait { OtherType }
}
//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
pub trait WithSuperTrait: OtherTrait {}
//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
+15 -15
View File
@@ -11,31 +11,31 @@ LL | #![deny(exported_private_dependencies)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: macro `m` from private dependency 'priv_dep' is re-exported
--> $DIR/pub-priv1.rs:94:9
--> $DIR/pub-priv1.rs:98:9
|
LL | pub use priv_dep::m;
| ^^^^^^^^^^^
error: macro `fn_like` from private dependency 'pm' is re-exported
--> $DIR/pub-priv1.rs:96:9
--> $DIR/pub-priv1.rs:100:9
|
LL | pub use pm::fn_like;
| ^^^^^^^^^^^
error: derive macro `PmDerive` from private dependency 'pm' is re-exported
--> $DIR/pub-priv1.rs:98:9
--> $DIR/pub-priv1.rs:102:9
|
LL | pub use pm::PmDerive;
| ^^^^^^^^^^^^
error: attribute macro `pm_attr` from private dependency 'pm' is re-exported
--> $DIR/pub-priv1.rs:100:9
--> $DIR/pub-priv1.rs:104:9
|
LL | pub use pm::pm_attr;
| ^^^^^^^^^^^
error: variant `V1` from private dependency 'priv_dep' is re-exported
--> $DIR/pub-priv1.rs:103:9
--> $DIR/pub-priv1.rs:107:9
|
LL | pub use priv_dep::E::V1;
| ^^^^^^^^^^^^^^^
@@ -65,61 +65,61 @@ LL | type Foo: OtherTrait;
| ^^^^^^^^^^^^^^^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:50:1
--> $DIR/pub-priv1.rs:54:1
|
LL | pub trait WithSuperTrait: OtherTrait {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:59:5
--> $DIR/pub-priv1.rs:63:5
|
LL | type X = OtherType;
| ^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:63:1
--> $DIR/pub-priv1.rs:67:1
|
LL | pub fn in_bounds<T: OtherTrait>(x: T) { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:66:1
--> $DIR/pub-priv1.rs:70:1
|
LL | pub fn private_in_generic() -> std::num::Saturating<OtherType> { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:69:1
--> $DIR/pub-priv1.rs:73:1
|
LL | pub static STATIC: OtherType = OtherType;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:72:1
--> $DIR/pub-priv1.rs:76:1
|
LL | pub const CONST: OtherType = OtherType;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:75:1
--> $DIR/pub-priv1.rs:79:1
|
LL | pub type Alias = OtherType;
| ^^^^^^^^^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:80:1
--> $DIR/pub-priv1.rs:84:1
|
LL | impl OtherTrait for PublicWithPrivateImpl {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:85:1
--> $DIR/pub-priv1.rs:89:1
|
LL | impl PubTraitOnPrivate for OtherType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
--> $DIR/pub-priv1.rs:85:1
--> $DIR/pub-priv1.rs:89:1
|
LL | impl PubTraitOnPrivate for OtherType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^