about summary refs log tree commit diff
path: root/src/libstd/ffi
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-09-14 22:21:41 +0000
committerbors <bors@rust-lang.org>2015-09-14 22:21:41 +0000
commite629dba0ee190cab49df0c5db299fb8d77264dda (patch)
tree7a7414911c1fd6bb6b4c79d9fa059fb20c6159c4 /src/libstd/ffi
parentbc6c3970a072ced531f39eaa918084acd43c785a (diff)
parent104902100d8894d7578694754590668d6d725a17 (diff)
downloadrust-e629dba0ee190cab49df0c5db299fb8d77264dda.tar.gz
rust-e629dba0ee190cab49df0c5db299fb8d77264dda.zip
Auto merge of #28256 - petrochenkov:conv, r=alexcrichton
This patch transforms functions of the form
```
fn f<Generic: AsRef<Concrete>>(arg: Generic) {
	let arg: &Concrete = arg.as_ref();
	// Code using arg
}
```
to the next form:
```
#[inline]
fn f<Generic: AsRef<Concrete>>(arg: Generic) {
	fn f_inner(arg: &Concrete) {
		// Code using arg
	}
	
	f_inner(arg.as_ref());
}
```

Therefore, most of the code is concrete and not duplicated during monomorphisation (unless inlined)
and only the tiny bit of conversion code is duplicated. This method was mentioned by @aturon in the
Conversion Traits RFC (https://github.com/rust-lang/rfcs/blame/master/text/0529-conversion-traits.md#L249) and similar techniques are not uncommon in C++ template libraries.

This patch goes to the extremes and applies the transformation even to smaller functions<sup>1</sup>
for purity of the experiment. *Some of them can be rolled back* if considered too ridiculous.

<sup>1</sup> However who knows how small are these functions are after inlining and everything.

The functions in question are mostly `fs`/`os` functions and not used especially often with variety
of argument types, so the code size reduction is rather small (but consistent). Here are the sizes
of stage2 artifacts before and after the patch:
https://gist.github.com/petrochenkov/e76a6b280f382da13c5d
https://gist.github.com/petrochenkov/6cc28727d5256dbdfed0

Note:
All the `inner` functions are concrete and unavailable for cross-crate inlining, some of them may
need `#[inline]` annotations in the future.

r? @aturon
Diffstat (limited to 'src/libstd/ffi')
-rw-r--r--src/libstd/ffi/c_str.rs5
-rw-r--r--src/libstd/ffi/os_str.rs20
2 files changed, 14 insertions, 11 deletions
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 3a1853a7a6c..7c9c2066ae9 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -181,7 +181,10 @@ impl CString {
     /// the position of the nul byte.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
-        let bytes = t.into();
+        Self::_new(t.into())
+    }
+
+    fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
         match bytes.iter().position(|x| *x == 0) {
             Some(i) => Err(NulError(i, bytes)),
             None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 751c76b9960..7409d9b45d2 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -73,18 +73,18 @@ impl OsString {
     /// convert; non UTF-8 data will produce `None`.
     #[unstable(feature = "convert", reason = "recently added", issue = "27704")]
     pub fn from_bytes<B>(bytes: B) -> Option<OsString> where B: Into<Vec<u8>> {
-        #[cfg(unix)]
-        fn from_bytes_inner(vec: Vec<u8>) -> Option<OsString> {
-            use os::unix::ffi::OsStringExt;
-            Some(OsString::from_vec(vec))
-        }
+        Self::_from_bytes(bytes.into())
+    }
 
-        #[cfg(windows)]
-        fn from_bytes_inner(vec: Vec<u8>) -> Option<OsString> {
-            String::from_utf8(vec).ok().map(OsString::from)
-        }
+    #[cfg(unix)]
+    fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
+        use os::unix::ffi::OsStringExt;
+        Some(OsString::from_vec(vec))
+    }
 
-        from_bytes_inner(bytes.into())
+    #[cfg(windows)]
+    fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
+        String::from_utf8(vec).ok().map(OsString::from)
     }
 
     /// Converts to an `OsStr` slice.