From 08aad526775212b30f3d263e9f59ee44f70bdf5a Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 25 Jan 2016 16:31:59 +0200 Subject: [PATCH] translate undefined intrinsics to an unreachable and a lint --- text/0000-undefined-intrinsic.md | 71 ++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 text/0000-undefined-intrinsic.md diff --git a/text/0000-undefined-intrinsic.md b/text/0000-undefined-intrinsic.md new file mode 100644 index 00000000000..f8d05cd1ff1 --- /dev/null +++ b/text/0000-undefined-intrinsic.md @@ -0,0 +1,71 @@ +- Feature Name: undefined_intrinsic +- Start Date: 2015-01-25 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +Translate undefined generic intrinsics to an LLVM `unreachable` +and a lint. + +# Motivation +[motivation]: #motivation + +Many generic intrinsics are only defined for particular type substitutions. For +example, `transmute` is only defined when both arguments have the same size, +and atomic operations are only defined for types with a CPU-supported size +and alignmen. + +Unsafe code often desires to do these operations opportunistically - for example, +to use an atomic operation if that is supported, and to otherwise default to +mutual exclusion. + +In addition, the precise constraints required by these operations are hard +to encode in the type-system, which means that even if we wanted to use +specialization for opportunsitic operations, we would be restricted. + +Finally, the current strategy for handling undefined intrinsics is +to cause compilation errors in a fairly fragmented and buggy way (that's +it, either rustc errors or LLVM assertions). As that kind of undefined +use is often unintentional, this has the useful effect of not causing +subtle crashes, but is obviously suboptimal. + +# Detailed design +[design]: #detailed-design + +When translating an undefined intrinsic, translate it to an LLVM `unreachable` +instruction, without causing an error or emitting invalid LLVM-IR. + +This is not a safety issue as intrinsics are unsafe, and unsafe code can +easily cause an LLVM `unreachable` through generating code that exhibits +UB. + +To retain the error-detecting effect of the previous strategy, introduce +a `undefined_intrinsic` lint, which should warn when an `unreachable` +is generated in this way. As intrinsics are generated by monomorphization, +the lint would need to be stored in metadata. + +# Drawbacks +[drawbacks]: #drawbacks + +Metadata lints are annoying and may pose implementation difficulties. In +addition they make intrinsic reexports more different from intrinsic +wrappers than they are now. + +If we do not check generic functions, we risk accidental modifications +causing hard-to-track `unreachable` generation and code erasure. Luckily, +unlike other kinds of UB, these `unreachable` instructions would still +appear in debug mode. + +# Alternatives +[alternatives]: #alternatives + + * Keep the current fragmented strategy, with its disadvantages. + * Do not do the `undefined_intrinsic` check on generic functions, or + cross-crate instantiations. + +# Unresolved questions +[unresolved]: #unresolved-questions + +What should we do with the lint? \ No newline at end of file