]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #41209 - aidanhs:aphs-quiet-sccache, r=alexcrichton
authorCorey Farwell <coreyf@rwell.org>
Tue, 11 Apr 2017 22:36:16 +0000 (18:36 -0400)
committerGitHub <noreply@github.com>
Tue, 11 Apr 2017 22:36:16 +0000 (18:36 -0400)
Make sccache a bit quieter

...and remove the single mention of `SCCACHE_LOG_LEVEL` that would only take effect on Docker (i.e. Linux) builds since it had no effect anyway (because [`RUST_LOG` takes priority](https://github.com/mozilla/sccache/blob/ec10cdb2ddeb3dde9891bea1fa095e504a60a28a/src/main.rs#L124-L128)).

r? @frewsxcv

141 files changed:
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/linker-flavor.md [new file with mode: 0644]
src/doc/unstable-book/src/manually-drop.md [new file with mode: 0644]
src/doc/unstable-book/src/str-mut-extras.md [new file with mode: 0644]
src/liballoc_jemalloc/build.rs
src/liballoc_jemalloc/lib.rs
src/libcollections/lib.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcore/char.rs
src/libcore/cmp.rs
src/libcore/intrinsics.rs
src/libcore/mem.rs
src/libcore/ops.rs
src/libcore/slice/sort.rs
src/libcore/str/mod.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc_back/lib.rs
src/librustc_back/target/aarch64_apple_ios.rs
src/librustc_back/target/aarch64_linux_android.rs
src/librustc_back/target/aarch64_unknown_freebsd.rs
src/librustc_back/target/aarch64_unknown_fuchsia.rs
src/librustc_back/target/aarch64_unknown_linux_gnu.rs
src/librustc_back/target/android_base.rs
src/librustc_back/target/apple_base.rs
src/librustc_back/target/apple_ios_base.rs
src/librustc_back/target/arm_linux_androideabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
src/librustc_back/target/arm_unknown_linux_musleabi.rs
src/librustc_back/target/arm_unknown_linux_musleabihf.rs
src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
src/librustc_back/target/armv7_apple_ios.rs
src/librustc_back/target/armv7_linux_androideabi.rs
src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
src/librustc_back/target/armv7s_apple_ios.rs
src/librustc_back/target/asmjs_unknown_emscripten.rs
src/librustc_back/target/dragonfly_base.rs
src/librustc_back/target/freebsd_base.rs
src/librustc_back/target/fuchsia_base.rs
src/librustc_back/target/i386_apple_ios.rs
src/librustc_back/target/i686_apple_darwin.rs
src/librustc_back/target/i686_linux_android.rs
src/librustc_back/target/i686_pc_windows_gnu.rs
src/librustc_back/target/i686_pc_windows_msvc.rs
src/librustc_back/target/i686_unknown_dragonfly.rs
src/librustc_back/target/i686_unknown_freebsd.rs
src/librustc_back/target/i686_unknown_haiku.rs
src/librustc_back/target/i686_unknown_linux_gnu.rs
src/librustc_back/target/i686_unknown_linux_musl.rs
src/librustc_back/target/i686_unknown_netbsd.rs
src/librustc_back/target/i686_unknown_openbsd.rs
src/librustc_back/target/le32_unknown_nacl.rs
src/librustc_back/target/linux_base.rs
src/librustc_back/target/linux_musl_base.rs
src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs
src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs
src/librustc_back/target/mips_unknown_linux_gnu.rs
src/librustc_back/target/mips_unknown_linux_musl.rs
src/librustc_back/target/mips_unknown_linux_uclibc.rs
src/librustc_back/target/mipsel_unknown_linux_gnu.rs
src/librustc_back/target/mipsel_unknown_linux_musl.rs
src/librustc_back/target/mipsel_unknown_linux_uclibc.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/netbsd_base.rs
src/librustc_back/target/openbsd_base.rs
src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
src/librustc_back/target/powerpc_unknown_linux_gnu.rs
src/librustc_back/target/redox_base.rs
src/librustc_back/target/s390x_unknown_linux_gnu.rs
src/librustc_back/target/sparc64_unknown_linux_gnu.rs
src/librustc_back/target/sparc64_unknown_netbsd.rs
src/librustc_back/target/sparcv9_sun_solaris.rs
src/librustc_back/target/thumbv6m_none_eabi.rs
src/librustc_back/target/thumbv7em_none_eabi.rs
src/librustc_back/target/thumbv7em_none_eabihf.rs
src/librustc_back/target/thumbv7m_none_eabi.rs
src/librustc_back/target/wasm32_unknown_emscripten.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/windows_msvc_base.rs
src/librustc_back/target/x86_64_apple_darwin.rs
src/librustc_back/target/x86_64_apple_ios.rs
src/librustc_back/target/x86_64_pc_windows_gnu.rs
src/librustc_back/target/x86_64_pc_windows_msvc.rs
src/librustc_back/target/x86_64_rumprun_netbsd.rs
src/librustc_back/target/x86_64_sun_solaris.rs
src/librustc_back/target/x86_64_unknown_bitrig.rs
src/librustc_back/target/x86_64_unknown_dragonfly.rs
src/librustc_back/target/x86_64_unknown_freebsd.rs
src/librustc_back/target/x86_64_unknown_fuchsia.rs
src/librustc_back/target/x86_64_unknown_haiku.rs
src/librustc_back/target/x86_64_unknown_linux_gnu.rs
src/librustc_back/target/x86_64_unknown_linux_musl.rs
src/librustc_back/target/x86_64_unknown_netbsd.rs
src/librustc_back/target/x86_64_unknown_openbsd.rs
src/librustc_back/target/x86_64_unknown_redox.rs
src/librustc_data_structures/array_vec.rs
src/librustc_data_structures/lib.rs
src/librustc_driver/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/mir/mod.rs
src/librustc_typeck/check/intrinsic.rs
src/librustdoc/html/markdown.rs
src/libstd/ascii.rs
src/libstd/lib.rs
src/libstd/primitive_docs.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/parser.rs
src/libsyntax_pos/lib.rs
src/test/compile-fail/feature-gate-linker-flavor.rs [new file with mode: 0644]
src/test/compile-fail/forget-init-unsafe.rs
src/test/compile-fail/impl-trait/equality.rs [deleted file]
src/test/run-make/target-specs/my-awesome-platform.json
src/test/run-make/target-specs/my-incomplete-platform.json
src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json
src/test/run-pass/optimization-fuel-0.rs [new file with mode: 0644]
src/test/run-pass/optimization-fuel-1.rs [new file with mode: 0644]
src/test/run-pass/type-sizes.rs
src/test/ui/impl-trait/equality.rs [new file with mode: 0644]
src/test/ui/impl-trait/equality.stderr [new file with mode: 0644]
src/test/ui/mismatched_types/binops.rs [new file with mode: 0644]
src/test/ui/mismatched_types/binops.stderr [new file with mode: 0644]
src/test/ui/print-fuel/print-fuel.rs [new file with mode: 0644]
src/test/ui/print-fuel/print-fuel.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/nullable.stdout
src/test/ui/print_type_sizes/packed.stdout
src/test/ui/print_type_sizes/padding.stdout
src/test/ui/span/multiline-span-simple.stderr
src/test/ui/token/issue-41155.rs [new file with mode: 0644]
src/test/ui/token/issue-41155.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs

index d86766bac02a2829e15b97f433211f7eca237c70..54e602a81db7389e93e2eb682e8c2371ce423223 100644 (file)
 - [link_llvm_intrinsics](link-llvm-intrinsics.md)
 - [linkage](linkage.md)
 - [linked_list_extras](linked-list-extras.md)
+- [linker_flavor](linker-flavor.md)
 - [log_syntax](log-syntax.md)
 - [lookup_host](lookup-host.md)
 - [loop_break_value](loop-break-value.md)
 - [macro_reexport](macro-reexport.md)
 - [main](main.md)
+- [manually_drop](manually-drop.md)
 - [map_entry_recover_keys](map-entry-recover-keys.md)
 - [mpsc_select](mpsc-select.md)
 - [n16](n16.md)
 - [str_checked_slicing](str-checked-slicing.md)
 - [str_escape](str-escape.md)
 - [str_internals](str-internals.md)
+- [str_mut_extras](str-mut-extras.md)
 - [struct_field_attributes](struct-field-attributes.md)
 - [structural_match](structural-match.md)
 - [target_feature](target-feature.md)
diff --git a/src/doc/unstable-book/src/linker-flavor.md b/src/doc/unstable-book/src/linker-flavor.md
new file mode 100644 (file)
index 0000000..3965960
--- /dev/null
@@ -0,0 +1,61 @@
+# `linker-flavor`
+
+The tracking issue for this feature is: None
+
+------------------------
+
+Every `rustc` target defaults to some linker. For example, Linux targets default
+to gcc. In some cases, you may want to override the default; you can do that
+with the unstable CLI argument: `-Z linker-flavor`.
+
+Here how you would use this flag to link a Rust binary for the
+`thumbv7m-none-eabi` using LLD instead of GCC.
+
+``` text
+$ xargo rustc --target thumbv7m-none-eabi -- \
+    -C linker=ld.lld \
+    -Z linker-flavor=ld \
+    -Z print-link-args | tr ' ' '\n'
+"ld.lld"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c.0.o"
+"-o"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c"
+"--gc-sections"
+"-L"
+"$PWD/target/thumbv7m-none-eabi/debug/deps"
+"-L"
+"$PWD/target/debug/deps"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"-Bstatic"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib"
+"-Bdynamic"
+```
+
+Whereas the default is:
+
+``` text
+$ xargo rustc --target thumbv7m-none-eabi -- \
+    -C link-arg=-nostartfiles \
+    -Z print-link-args | tr ' ' '\n'
+"arm-none-eabi-gcc"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9.0.o"
+"-o"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9"
+"-Wl,--gc-sections"
+"-nodefaultlibs"
+"-L"
+"$PWD/target/thumbv7m-none-eabi/debug/deps"
+"-L"
+"$PWD/target/debug/deps"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"-Wl,-Bstatic"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib"
+"-nostartfiles"
+"-Wl,-Bdynamic"
+```
diff --git a/src/doc/unstable-book/src/manually-drop.md b/src/doc/unstable-book/src/manually-drop.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/doc/unstable-book/src/str-mut-extras.md b/src/doc/unstable-book/src/str-mut-extras.md
new file mode 100644 (file)
index 0000000..df4f358
--- /dev/null
@@ -0,0 +1,8 @@
+# `str_mut_extras`
+
+The tracking issue for this feature is: [#str_mut_extras]
+
+[#str_mut_extras]: https://github.com/rust-lang/rust/issues/41119
+
+------------------------
+
index ae040a23906595683cc072cf30d7021209349a27..f3a0eebe6984d2a11ca73d93871b6c4314683c15 100644 (file)
@@ -129,7 +129,7 @@ fn main() {
         // should be good to go!
         cmd.arg("--with-jemalloc-prefix=je_");
         cmd.arg("--disable-tls");
-    } else if target.contains("dragonfly") {
+    } else if target.contains("dragonfly") || target.contains("musl") {
         cmd.arg("--with-jemalloc-prefix=je_");
     }
 
index a7a67ef76d4f75599be5998d701b67340ea34d07..83cc1ef09c29c2fdf93e1085a1dda309ec7879dd 100644 (file)
@@ -35,23 +35,23 @@ mod imp {
     // request it as unprefixing cause segfaults (mismatches in allocators).
     extern "C" {
         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows"),
+                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                    link_name = "je_mallocx")]
         fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows"),
+                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                    link_name = "je_rallocx")]
         fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows"),
+                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                    link_name = "je_xallocx")]
         fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows"),
+                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                    link_name = "je_sdallocx")]
         fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows"),
+                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                    link_name = "je_nallocx")]
         fn nallocx(size: size_t, flags: c_int) -> size_t;
     }
index 79ae2d411b6fd5128c75ba96685cd5db0760b162..99afd08e81183eb451df419c93a633b43456bb9c 100644 (file)
@@ -44,6 +44,7 @@
 #![feature(heap_api)]
 #![feature(inclusive_range)]
 #![feature(lang_items)]
+#![feature(manually_drop)]
 #![feature(nonzero)]
 #![feature(pattern)]
 #![feature(placement_in)]
@@ -57,6 +58,7 @@
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(str_internals)]
+#![feature(str_mut_extras)]
 #![feature(trusted_len)]
 #![feature(unicode)]
 #![feature(unique)]
index 6cff315a6ccd9eb28083d2b1f5b2afa9e8dc2430..3069adb12e92cd127c5bd29d03d266da23d49df4 100644 (file)
@@ -1558,7 +1558,7 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
             //    performance than with the 2nd method.
             //
             // All methods were benchmarked, and the 3rd showed best results. So we chose that one.
-            let mut tmp = NoDrop { value: ptr::read(&v[0]) };
+            let mut tmp = mem::ManuallyDrop::new(ptr::read(&v[0]));
 
             // Intermediate state of the insertion process is always tracked by `hole`, which
             // serves two purposes:
@@ -1571,13 +1571,13 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
             // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
             // initially held exactly once.
             let mut hole = InsertionHole {
-                src: &mut tmp.value,
+                src: &mut *tmp,
                 dest: &mut v[1],
             };
             ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
 
             for i in 2..v.len() {
-                if !is_less(&v[i], &tmp.value) {
+                if !is_less(&v[i], &*tmp) {
                     break;
                 }
                 ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
@@ -1587,12 +1587,6 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
         }
     }
 
-    // Holds a value, but never drops it.
-    #[allow(unions_with_drop_fields)]
-    union NoDrop<T> {
-        value: T
-    }
-
     // When dropped, copies from `src` into `dest`.
     struct InsertionHole<T> {
         src: *mut T,
index c37a4fa6b5572757681971170e2984577d7d3385..d04f414250ade9ee8a70f00a6e571fda980b481d 100644 (file)
@@ -72,7 +72,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use core::str::{from_utf8_unchecked, ParseBoolError};
+pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use std_unicode::str::SplitWhitespace;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -294,6 +294,13 @@ pub fn as_bytes(&self) -> &[u8] {
         core_str::StrExt::as_bytes(self)
     }
 
+    /// Converts a mutable string slice to a mutable byte slice.
+    #[unstable(feature = "str_mut_extras", issue = "41119")]
+    #[inline(always)]
+    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+        core_str::StrExt::as_bytes_mut(self)
+    }
+
     /// Converts a string slice to a raw pointer.
     ///
     /// As string slices are a slice of bytes, the raw pointer points to a
index 0ee4c8b8e95a60bec3e8d06cea73460f03bcb274..7d9d7276201bd1ed3f85c5ef2e22b3470a5fb377 100644 (file)
@@ -1790,7 +1790,7 @@ fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
 impl ops::IndexMut<ops::RangeFull> for String {
     #[inline]
     fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
-        unsafe { mem::transmute(&mut *self.vec) }
+        unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
     }
 }
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
@@ -1822,7 +1822,7 @@ fn deref(&self) -> &str {
 impl ops::DerefMut for String {
     #[inline]
     fn deref_mut(&mut self) -> &mut str {
-        unsafe { mem::transmute(&mut *self.vec) }
+        unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
     }
 }
 
index b27c801cf89d5d26f3d74ba331a3b0e497e5ddc5..98268e3813fac1897e8d7dd66bff9903ecf8dc2d 100644 (file)
@@ -19,6 +19,7 @@
 use convert::TryFrom;
 use fmt::{self, Write};
 use slice;
+use str::from_utf8_unchecked_mut;
 use iter::FusedIterator;
 use mem::transmute;
 
@@ -448,7 +449,7 @@ fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
                     code,
                     dst.len())
             };
-            transmute(slice::from_raw_parts_mut(dst.as_mut_ptr(), len))
+            from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
         }
     }
 
index 74ded948b18e74a8dad5126880f24bea19585372..d4544dadaeb0c6af0d70693baa787223a25e6859 100644 (file)
 /// ```
 #[lang = "eq"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used
     /// by `==`.
@@ -550,6 +551,7 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 /// ```
 #[lang = "ord"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// This method returns an ordering between `self` and `other` values if one exists.
     ///
index e0a4707ff665f58c0bdedbb8fed6f6e29bc897be..b0287631585125a9febd3fb903e5d51e2358ae8e 100644 (file)
     /// initialize memory previous set to the result of `uninit`.
     pub fn uninit<T>() -> T;
 
-    /// Moves a value out of scope without running drop glue.
-    pub fn forget<T>(_: T) -> ();
-
     /// Reinterprets the bits of a value of one type as another type.
     ///
     /// Both types must have the same size. Neither the original, nor the result,
index f5cf3724d0711d8183e685a02d08878f37ad3e95..7be927b28ed7eb7ecfef5fcc8da2ab1d0cdc9410 100644 (file)
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn forget<T>(t: T) {
-    unsafe { intrinsics::forget(t) }
+    ManuallyDrop::new(t);
 }
 
 /// Returns the size of a type in bytes.
@@ -736,3 +736,121 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
     }
 }
 
+
+/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
+///
+/// This wrapper is 0-cost.
+///
+/// # Examples
+///
+/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
+/// the type:
+///
+/// ```rust
+/// # #![feature(manually_drop)]
+/// use std::mem::ManuallyDrop;
+/// struct Peach;
+/// struct Banana;
+/// struct Melon;
+/// struct FruitBox {
+///     // Immediately clear there’s something non-trivial going on with these fields.
+///     peach: ManuallyDrop<Peach>,
+///     melon: Melon, // Field that’s independent of the other two.
+///     banana: ManuallyDrop<Banana>,
+/// }
+///
+/// impl Drop for FruitBox {
+///     fn drop(&mut self) {
+///         unsafe {
+///             // Explicit ordering in which field destructors are run specified in the intuitive
+///             // location â€“ the destructor of the structure containing the fields.
+///             // Moreover, one can now reorder fields within the struct however much they want.
+///             ManuallyDrop::drop(&mut self.peach);
+///             ManuallyDrop::drop(&mut self.banana);
+///         }
+///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
+///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
+///     }
+/// }
+/// ```
+#[unstable(feature = "manually_drop", issue = "40673")]
+#[allow(unions_with_drop_fields)]
+pub union ManuallyDrop<T>{ value: T }
+
+impl<T> ManuallyDrop<T> {
+    /// Wrap a value to be manually dropped.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # #![feature(manually_drop)]
+    /// use std::mem::ManuallyDrop;
+    /// ManuallyDrop::new(Box::new(()));
+    /// ```
+    #[unstable(feature = "manually_drop", issue = "40673")]
+    #[inline]
+    pub fn new(value: T) -> ManuallyDrop<T> {
+        ManuallyDrop { value: value }
+    }
+
+    /// Extract the value from the ManuallyDrop container.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # #![feature(manually_drop)]
+    /// use std::mem::ManuallyDrop;
+    /// let x = ManuallyDrop::new(Box::new(()));
+    /// let _: Box<()> = ManuallyDrop::into_inner(x);
+    /// ```
+    #[unstable(feature = "manually_drop", issue = "40673")]
+    #[inline]
+    pub fn into_inner(slot: ManuallyDrop<T>) -> T {
+        unsafe {
+            slot.value
+        }
+    }
+
+    /// Manually drops the contained value.
+    ///
+    /// # Unsafety
+    ///
+    /// This function runs the destructor of the contained value and thus the wrapped value
+    /// now represents uninitialized data. It is up to the user of this method to ensure the
+    /// uninitialized data is not actually used.
+    #[unstable(feature = "manually_drop", issue = "40673")]
+    #[inline]
+    pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
+        ptr::drop_in_place(&mut slot.value)
+    }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T> ::ops::Deref for ManuallyDrop<T> {
+    type Target = T;
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            &self.value
+        }
+    }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T> ::ops::DerefMut for ManuallyDrop<T> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe {
+            &mut self.value
+        }
+    }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
+    fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
+        unsafe {
+            fmt.debug_tuple("ManuallyDrop").field(&self.value).finish()
+        }
+    }
+}
index d203b68c0dfd57fd1e8461968bf607a9089de01c..175b3a5a69ac15c86c51109154a6cdf3ef9ffac9 100644 (file)
@@ -242,6 +242,7 @@ pub trait Drop {
 /// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
 #[lang = "add"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"]
 pub trait Add<RHS=Self> {
     /// The resulting type after applying the `+` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -315,6 +316,7 @@ fn add(self, other: $t) -> $t { self + other }
 /// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
 #[lang = "sub"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
 pub trait Sub<RHS=Self> {
     /// The resulting type after applying the `-` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -437,6 +439,7 @@ fn sub(self, other: $t) -> $t { self - other }
 /// ```
 #[lang = "mul"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
 pub trait Mul<RHS=Self> {
     /// The resulting type after applying the `*` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -565,6 +568,7 @@ fn mul(self, other: $t) -> $t { self * other }
 /// ```
 #[lang = "div"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
 pub trait Div<RHS=Self> {
     /// The resulting type after applying the `/` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -644,6 +648,7 @@ fn div(self, other: $t) -> $t { self / other }
 /// ```
 #[lang = "rem"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
 pub trait Rem<RHS=Self> {
     /// The resulting type after applying the `%` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -883,6 +888,7 @@ fn not(self) -> $t { !self }
 /// ```
 #[lang = "bitand"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
 pub trait BitAnd<RHS=Self> {
     /// The resulting type after applying the `&` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -966,6 +972,7 @@ fn bitand(self, rhs: $t) -> $t { self & rhs }
 /// ```
 #[lang = "bitor"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
 pub trait BitOr<RHS=Self> {
     /// The resulting type after applying the `|` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1052,6 +1059,7 @@ fn bitor(self, rhs: $t) -> $t { self | rhs }
 /// ```
 #[lang = "bitxor"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
 pub trait BitXor<RHS=Self> {
     /// The resulting type after applying the `^` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1134,6 +1142,7 @@ fn bitxor(self, other: $t) -> $t { self ^ other }
 /// ```
 #[lang = "shl"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
 pub trait Shl<RHS> {
     /// The resulting type after applying the `<<` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1237,6 +1246,7 @@ macro_rules! shl_impl_all {
 /// ```
 #[lang = "shr"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
 pub trait Shr<RHS> {
     /// The resulting type after applying the `>>` operator
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1321,6 +1331,7 @@ macro_rules! shr_impl_all {
 /// ```
 #[lang = "add_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
 pub trait AddAssign<Rhs=Self> {
     /// The method for the `+=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1377,6 +1388,7 @@ fn add_assign(&mut self, other: $t) { *self += other }
 /// ```
 #[lang = "sub_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
 pub trait SubAssign<Rhs=Self> {
     /// The method for the `-=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1422,6 +1434,7 @@ fn sub_assign(&mut self, other: $t) { *self -= other }
 /// ```
 #[lang = "mul_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
 pub trait MulAssign<Rhs=Self> {
     /// The method for the `*=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1467,6 +1480,7 @@ fn mul_assign(&mut self, other: $t) { *self *= other }
 /// ```
 #[lang = "div_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
 pub trait DivAssign<Rhs=Self> {
     /// The method for the `/=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1511,6 +1525,7 @@ fn div_assign(&mut self, other: $t) { *self /= other }
 /// ```
 #[lang = "rem_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
 pub trait RemAssign<Rhs=Self> {
     /// The method for the `%=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1597,6 +1612,7 @@ fn rem_assign(&mut self, other: $t) { *self %= other }
 /// ```
 #[lang = "bitand_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
 pub trait BitAndAssign<Rhs=Self> {
     /// The method for the `&=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1641,6 +1657,7 @@ fn bitand_assign(&mut self, other: $t) { *self &= other }
 /// ```
 #[lang = "bitor_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
 pub trait BitOrAssign<Rhs=Self> {
     /// The method for the `|=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1685,6 +1702,7 @@ fn bitor_assign(&mut self, other: $t) { *self |= other }
 /// ```
 #[lang = "bitxor_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
 pub trait BitXorAssign<Rhs=Self> {
     /// The method for the `^=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1729,6 +1747,7 @@ fn bitxor_assign(&mut self, other: $t) { *self ^= other }
 /// ```
 #[lang = "shl_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
 pub trait ShlAssign<Rhs> {
     /// The method for the `<<=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -1794,6 +1813,7 @@ macro_rules! shl_assign_impl_all {
 /// ```
 #[lang = "shr_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
 pub trait ShrAssign<Rhs=Self> {
     /// The method for the `>>=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
index 7065fdb79fc4040a6ca225634408141e1871a830..6f9f2915dfe102c1fe6022d660816e69279152ed 100644 (file)
 use mem;
 use ptr;
 
-/// Holds a value, but never drops it.
-#[allow(unions_with_drop_fields)]
-union NoDrop<T> {
-    value: T
-}
-
 /// When dropped, copies from `src` into `dest`.
 struct CopyOnDrop<T> {
     src: *mut T,
@@ -49,15 +43,15 @@ fn shift_head<T, F>(v: &mut [T], is_less: &mut F)
             // Read the first element into a stack-allocated variable. If a following comparison
             // operation panics, `hole` will get dropped and automatically write the element back
             // into the slice.
-            let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(0)) };
+            let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
             let mut hole = CopyOnDrop {
-                src: &mut tmp.value,
+                src: &mut *tmp,
                 dest: v.get_unchecked_mut(1),
             };
             ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1);
 
             for i in 2..len {
-                if !is_less(v.get_unchecked(i), &tmp.value) {
+                if !is_less(v.get_unchecked(i), &*tmp) {
                     break;
                 }
 
@@ -81,15 +75,15 @@ fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
             // Read the last element into a stack-allocated variable. If a following comparison
             // operation panics, `hole` will get dropped and automatically write the element back
             // into the slice.
-            let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(len - 1)) };
+            let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
             let mut hole = CopyOnDrop {
-                src: &mut tmp.value,
+                src: &mut *tmp,
                 dest: v.get_unchecked_mut(len - 2),
             };
             ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1);
 
             for i in (0..len-2).rev() {
-                if !is_less(&tmp.value, v.get_unchecked(i)) {
+                if !is_less(&*tmp, v.get_unchecked(i)) {
                     break;
                 }
 
@@ -403,12 +397,12 @@ fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
 
         // Read the pivot into a stack-allocated variable for efficiency. If a following comparison
         // operation panics, the pivot will be automatically written back into the slice.
-        let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+        let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
         let _pivot_guard = CopyOnDrop {
-            src: unsafe { &mut tmp.value },
+            src: &mut *tmp,
             dest: pivot,
         };
-        let pivot = unsafe { &tmp.value };
+        let pivot = &*tmp;
 
         // Find the first pair of out-of-order elements.
         let mut l = 0;
@@ -452,12 +446,12 @@ fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
 
     // Read the pivot into a stack-allocated variable for efficiency. If a following comparison
     // operation panics, the pivot will be automatically written back into the slice.
-    let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+    let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
     let _pivot_guard = CopyOnDrop {
-        src: unsafe { &mut tmp.value },
+        src: &mut *tmp,
         dest: pivot,
     };
-    let pivot = unsafe { &tmp.value };
+    let pivot = &*tmp;
 
     // Now partition the slice.
     let mut l = 0;
index 352cc926994e3685ae5ca5554eba5f9fbfd3e3c6..2ceef54ffed6a6ddd37535419ca26ab4043e6ab1 100644 (file)
@@ -21,8 +21,8 @@
 use convert::TryFrom;
 use fmt;
 use iter::{Map, Cloned, FusedIterator};
-use mem;
 use slice::{self, SliceIndex};
+use mem;
 
 pub mod pattern;
 
@@ -300,6 +300,13 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     Ok(unsafe { from_utf8_unchecked(v) })
 }
 
+/// Converts a mutable slice of bytes to a mutable string slice.
+#[unstable(feature = "str_mut_extras", issue = "41119")]
+pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
+    run_utf8_validation(v)?;
+    Ok(unsafe { from_utf8_unchecked_mut(v) })
+}
+
 /// Forms a str from a pointer and a length.
 ///
 /// The `len` argument is the number of bytes in the string.
@@ -325,7 +332,7 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 /// str is returned.
 ///
 unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
-    mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
+    from_utf8_unchecked_mut(slice::from_raw_parts_mut(p, len))
 }
 
 /// Converts a slice of bytes to a string slice without checking
@@ -365,6 +372,18 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
     mem::transmute(v)
 }
 
+/// Converts a slice of bytes to a string slice without checking
+/// that the string contains valid UTF-8; mutable version.
+///
+/// See the immutable version, [`from_utf8_unchecked()`][fromutf8], for more information.
+///
+/// [fromutf8]: fn.from_utf8_unchecked.html
+#[inline(always)]
+#[unstable(feature = "str_mut_extras", issue = "41119")]
+pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
+    mem::transmute(v)
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Utf8Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -1474,7 +1493,6 @@ pub fn utf8_char_width(b: u8) -> usize {
 mod traits {
     use cmp::Ordering;
     use ops;
-    use mem;
     use slice::{self, SliceIndex};
     use str::eq_slice;
 
@@ -1811,7 +1829,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
             let ptr = slice.as_ptr().offset(self.start as isize);
             let len = self.end - self.start;
-            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
+            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
@@ -1859,7 +1877,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
             let ptr = slice.as_ptr();
-            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
+            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
@@ -1905,7 +1923,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
             let ptr = slice.as_ptr().offset(self.start as isize);
             let len = slice.len() - self.start;
-            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
+            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
@@ -1998,7 +2016,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
             let ptr = slice.as_ptr();
-            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
+            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
@@ -2096,6 +2114,8 @@ fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
     fn is_char_boundary(&self, index: usize) -> bool;
     #[stable(feature = "core", since = "1.6.0")]
     fn as_bytes(&self) -> &[u8];
+    #[unstable(feature = "str_mut_extras", issue = "0")]
+    unsafe fn as_bytes_mut(&mut self) -> &mut [u8];
     #[stable(feature = "core", since = "1.6.0")]
     fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
     #[stable(feature = "core", since = "1.6.0")]
@@ -2373,6 +2393,11 @@ fn as_bytes(&self) -> &[u8] {
         unsafe { mem::transmute(self) }
     }
 
+    #[inline]
+    unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+        mem::transmute(self)
+    }
+
     fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
         pat.into_searcher(self).next_match().map(|(i, _)| i)
     }
index a0603c5795247c75fb98911daae1c1b3c7ddd284..b9a974045bced110527e953ebffe296dccceb6b6 100644 (file)
@@ -19,7 +19,7 @@
 use session::{early_error, early_warn, Session};
 use session::search_paths::SearchPaths;
 
-use rustc_back::PanicStrategy;
+use rustc_back::{LinkerFlavor, PanicStrategy};
 use rustc_back::target::Target;
 use lint;
 use middle::cstore;
@@ -641,12 +641,16 @@ mod $mod_desc {
             Some("either `panic` or `abort`");
         pub const parse_sanitizer: Option<&'static str> =
             Some("one of: `address`, `leak`, `memory` or `thread`");
+        pub const parse_linker_flavor: Option<&'static str> =
+            Some(::rustc_back::LinkerFlavor::one_of());
+        pub const parse_optimization_fuel: Option<&'static str> =
+            Some("crate=integer");
     }
 
     #[allow(dead_code)]
     mod $mod_set {
         use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
-        use rustc_back::PanicStrategy;
+        use rustc_back::{LinkerFlavor, PanicStrategy};
 
         $(
             pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -777,6 +781,29 @@ fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
             }
             true
         }
+
+        fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
+            match v.and_then(LinkerFlavor::from_str) {
+                Some(lf) => *slote = Some(lf),
+                _ => return false,
+            }
+            true
+        }
+
+        fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> bool {
+            match v {
+                None => false,
+                Some(s) => {
+                    let parts = s.split('=').collect::<Vec<_>>();
+                    if parts.len() != 2 { return false; }
+                    let crate_name = parts[0].to_string();
+                    let fuel = parts[1].parse::<u64>();
+                    if fuel.is_err() { return false; }
+                    *slot = Some((crate_name, fuel.unwrap()));
+                    true
+                }
+            }
+        }
     }
 ) }
 
@@ -979,6 +1006,12 @@ fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
           "pass `-install_name @rpath/...` to the macOS linker"),
     sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
                                    "Use a sanitizer"),
+    linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
+                                           "Linker flavor"),
+    fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
+        "Set the optimization fuel quota for a crate."),
+    print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
+        "Make Rustc print the total optimization fuel used by a crate."),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1772,11 +1805,13 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
 
     impl_dep_tracking_hash_via_hash!(bool);
     impl_dep_tracking_hash_via_hash!(usize);
+    impl_dep_tracking_hash_via_hash!(u64);
     impl_dep_tracking_hash_via_hash!(String);
     impl_dep_tracking_hash_via_hash!(lint::Level);
     impl_dep_tracking_hash_via_hash!(Option<bool>);
     impl_dep_tracking_hash_via_hash!(Option<usize>);
     impl_dep_tracking_hash_via_hash!(Option<String>);
+    impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
     impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
     impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
     impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
@@ -1798,6 +1833,7 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
     impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
     impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
                                                  Option<cstore::NativeLibraryKind>));
+    impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
     impl DepTrackingHash for SearchPaths {
         fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
             let mut elems: Vec<_> = self
index 3ba82f34c3266a804fece8554e94707fb562c796..039db3d9ee9117484aa69847768089bbfcdf608b 100644 (file)
@@ -36,7 +36,7 @@
 use syntax::feature_gate::AttributeType;
 use syntax_pos::{Span, MultiSpan};
 
-use rustc_back::PanicStrategy;
+use rustc_back::{LinkerFlavor, PanicStrategy};
 use rustc_back::target::Target;
 use rustc_data_structures::flock;
 use llvm;
@@ -123,6 +123,20 @@ pub struct Session {
     pub code_stats: RefCell<CodeStats>,
 
     next_node_id: Cell<ast::NodeId>,
+
+    /// If -zfuel=crate=n is specified, Some(crate).
+    optimization_fuel_crate: Option<String>,
+    /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
+    optimization_fuel_limit: Cell<u64>,
+    /// We're rejecting all further optimizations.
+    out_of_fuel: Cell<bool>,
+
+    // The next two are public because the driver needs to read them.
+
+    /// If -zprint-fuel=crate, Some(crate).
+    pub print_fuel_crate: Option<String>,
+    /// Always set to zero and incremented so that we can print fuel expended by a crate.
+    pub print_fuel: Cell<u64>,
 }
 
 pub struct PerfStats {
@@ -363,6 +377,9 @@ pub fn lto(&self) -> bool {
     pub fn panic_strategy(&self) -> PanicStrategy {
         self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy)
     }
+    pub fn linker_flavor(&self) -> LinkerFlavor {
+        self.opts.debugging_opts.linker_flavor.unwrap_or(self.target.target.linker_flavor)
+    }
     pub fn no_landing_pads(&self) -> bool {
         self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort
     }
@@ -504,6 +521,32 @@ pub fn print_perf_stats(&self) {
         println!("Total time spent decoding DefPath tables:      {}",
                  duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get()));
     }
+
+    /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
+    /// This expends fuel if applicable, and records fuel if applicable.
+    pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
+        let mut ret = true;
+        match self.optimization_fuel_crate {
+            Some(ref c) if c == crate_name => {
+                let fuel = self.optimization_fuel_limit.get();
+                ret = fuel != 0;
+                if fuel == 0 && !self.out_of_fuel.get() {
+                    println!("optimization-fuel-exhausted: {}", msg());
+                    self.out_of_fuel.set(true);
+                } else if fuel > 0 {
+                    self.optimization_fuel_limit.set(fuel-1);
+                }
+            }
+            _ => {}
+        }
+        match self.print_fuel_crate {
+            Some(ref c) if c == crate_name=> {
+                self.print_fuel.set(self.print_fuel.get()+1);
+            },
+            _ => {}
+        }
+        ret
+    }
 }
 
 pub fn build_session(sopts: config::Options,
@@ -599,6 +642,12 @@ pub fn build_session_(sopts: config::Options,
         }
     );
 
+    let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
+    let optimization_fuel_limit = Cell::new(sopts.debugging_opts.fuel.as_ref()
+        .map(|i| i.1).unwrap_or(0));
+    let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
+    let print_fuel = Cell::new(0);
+
     let sess = Session {
         dep_graph: dep_graph.clone(),
         target: target_cfg,
@@ -640,6 +689,11 @@ pub fn build_session_(sopts: config::Options,
             decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
         },
         code_stats: RefCell::new(CodeStats::new()),
+        optimization_fuel_crate: optimization_fuel_crate,
+        optimization_fuel_limit: optimization_fuel_limit,
+        print_fuel_crate: print_fuel_crate,
+        print_fuel: print_fuel,
+        out_of_fuel: Cell::new(false),
     };
 
     init_llvm(&sess);
index 152dd6ac3000f71f8b6beb69a5525b64350cd3ff..931c77badad222009ee0e6da53af98e99d2b5ee1 100644 (file)
@@ -524,15 +524,8 @@ pub fn report_selection_error(&self,
                             "the trait bound `{}` is not satisfied{}",
                             trait_ref.to_predicate(),
                             post_message);
-                        err.span_label(span,
-                                        &format!("{}the trait `{}` is not \
-                                                    implemented for `{}`",
-                                                pre_message,
-                                                trait_ref,
-                                                trait_ref.self_ty()));
 
                         // Try to report a help message
-
                         if !trait_ref.has_infer_types() &&
                             self.predicate_can_apply(trait_ref) {
                             // If a where-clause may be useful, remind the
@@ -544,17 +537,21 @@ pub fn report_selection_error(&self,
                             // which is somewhat confusing.
                             err.help(&format!("consider adding a `where {}` bound",
                                                 trait_ref.to_predicate()));
-                        } else if let Some(s) = self.on_unimplemented_note(trait_ref,
-                                                                            obligation) {
+                        } else if let Some(s) = self.on_unimplemented_note(trait_ref, obligation) {
                             // If it has a custom "#[rustc_on_unimplemented]"
                             // error message, let's display it!
                             err.note(&s);
                         } else {
-                            // If we can't show anything useful, try to find
-                            // similar impls.
+                            // Can't show anything else useful, try to find similar impls.
                             let impl_candidates = self.find_similar_impl_candidates(trait_ref);
                             self.report_similar_impl_candidates(impl_candidates, &mut err);
                         }
+
+                        err.span_label(span,
+                                       &format!("{}the trait `{}` is not implemented for `{}`",
+                                                pre_message,
+                                                trait_ref,
+                                                trait_ref.self_ty()));
                         err
                     }
 
@@ -997,3 +994,4 @@ fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
                           suggested_limit));
     }
 }
+
index da56514ea82fbf9e485c3f1f761ff9253f9b54cc..8b7438c0bfad2ed5f73efbfece42ffbbd22978d4 100644 (file)
@@ -732,6 +732,11 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             ast_ty_to_ty_cache: RefCell::new(NodeMap()),
        }, f)
     }
+
+    pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
+        let cname = self.crate_name(LOCAL_CRATE).as_str();
+        self.sess.consider_optimizing(&cname, msg)
+    }
 }
 
 impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
index 54e5de3909086d55728f54d8c35d6884b5ebda32..d7a4b3fda63bb84054d49fde393e1f2ef62e9fe3 100644 (file)
@@ -580,7 +580,6 @@ enum StructKind {
 }
 
 impl<'a, 'gcx, 'tcx> Struct {
-    // FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
     fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
                   repr: &ReprOptions, kind: StructKind,
                   scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
@@ -598,12 +597,8 @@ fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
         // Neither do  1-member and 2-member structs.
         // In addition, code in trans assume that 2-element structs can become pairs.
         // It's easier to just short-circuit here.
-        let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
-            && ! (repr.c || repr.packed);
-
-        // Disable field reordering until we can decide what to do.
-        // The odd pattern here avoids a warning about the value never being read.
-        if can_optimize { can_optimize = false; }
+        let can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
+            && !(repr.c || repr.packed || repr.linear || repr.simd);
 
         let (optimize, sort_ascending) = match kind {
             StructKind::AlwaysSizedUnivariant => (can_optimize, false),
index 292e30e3d41f19403353bfdd2a055ac4c1066daf..a2c356c20db09d563afa0e532dc964c39f139138 100644 (file)
@@ -1411,13 +1411,16 @@ pub struct ReprOptions {
     pub packed: bool,
     pub simd: bool,
     pub int: Option<attr::IntType>,
+    // Internal only for now. If true, don't reorder fields.
+    pub linear: bool,
 }
 
 impl_stable_hash_for!(struct ReprOptions {
     c,
     packed,
     simd,
-    int
+    int,
+    linear
 });
 
 impl ReprOptions {
@@ -1440,6 +1443,9 @@ pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
             ret.simd = true;
         }
 
+        // This is here instead of layout because the choice must make it into metadata.
+        ret.linear = !tcx.consider_optimizing(|| format!("Reorder fields of {:?}",
+            tcx.item_path_str(did)));
         ret
     }
 
index 000e4eb59bf05c7f65981c10f58629c64030896d..6679cc73029c7e119edd15ff81fdb00f36d5c52d 100644 (file)
 
 use serialize::json::{Json, ToJson};
 
+macro_rules! linker_flavor {
+    ($(($variant:ident, $string:expr),)+) => {
+        #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
+                 RustcEncodable, RustcDecodable)]
+        pub enum LinkerFlavor {
+            $($variant,)+
+        }
+
+        impl LinkerFlavor {
+            pub const fn one_of() -> &'static str {
+                concat!("one of: ", $($string, " ",)+)
+            }
+
+            pub fn from_str(s: &str) -> Option<Self> {
+                Some(match s {
+                    $($string => LinkerFlavor::$variant,)+
+                    _ => return None,
+                })
+            }
+
+            pub fn desc(&self) -> &str {
+                match *self {
+                    $(LinkerFlavor::$variant => $string,)+
+                }
+            }
+        }
+
+        impl ToJson for LinkerFlavor {
+            fn to_json(&self) -> Json {
+                self.desc().to_json()
+            }
+        }
+    }
+}
+
+linker_flavor! {
+    (Em, "em"),
+    (Gcc, "gcc"),
+    (Ld, "ld"),
+    (Msvc, "msvc"),
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub enum PanicStrategy {
     Unwind,
index 5ef79359140f775bc6bd6396c22926dfd0d04b5d..802a8c77db05bc3c77cad41642f91dfece4b24ff 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "ios".to_string(),
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+cyclone".to_string(),
             eliminate_frame_pointer: false,
index 54eead94986cc9b441854d5ccd207bdaa6d27d9a..7d8610b4a36841bc277d218bfd1e31c6c3ca610e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
@@ -28,6 +29,7 @@ pub fn target() -> TargetResult {
         target_os: "android".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 3c5d6308ee6bad7b052ae03eb71991b809554c52..c5cfff0be03ad05851fb1461454492a264dc0b7b 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -26,6 +27,7 @@ pub fn target() -> TargetResult {
         target_os: "freebsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 6ba1732e67f7930937fc493cda5ee3c4aa92b776..5d680504a02d00bff5bb9f1391977cdc4cf1447c 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -23,6 +24,7 @@ pub fn target() -> TargetResult {
         target_os: "fuchsia".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 5f6335d405f5ea40fe49b1e7827c51a9ecc6ead1..043bd881c7290c6062cde4331f495641e9b10b45 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -26,6 +27,7 @@ pub fn target() -> TargetResult {
         arch: "aarch64".to_string(),
         target_os: "linux".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 9791520e9339bbd8ad6908b74e70256abbf83673..49baa1b96cee3b4bdf61dec87801898f386f7ea1 100644 (file)
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::TargetOptions;
 
 pub fn opts() -> TargetOptions {
     let mut base = super::linux_base::opts();
     // Many of the symbols defined in compiler-rt are also defined in libgcc.
     // Android's linker doesn't like that by default.
-    base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
+    base.pre_link_args
+        .get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--allow-multiple-definition".to_string());
     base.is_like_android = true;
     base.position_independent_executables = true;
     base.has_elf_tls = false;
index 3a551a2b124b7cc69edc9856c2660f05a15178b9..159f93a74c68352276ec630b8a2d9b6b05259c9d 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::env;
 
-use target::TargetOptions;
+use target::{LinkArgs, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
@@ -43,7 +43,7 @@ pub fn opts() -> TargetOptions {
         dll_prefix: "lib".to_string(),
         dll_suffix: ".dylib".to_string(),
         archive_format: "bsd".to_string(),
-        pre_link_args: Vec::new(),
+        pre_link_args: LinkArgs::new(),
         exe_allocation_crate: super::maybe_jemalloc(),
         has_elf_tls: version >= (10, 7),
         .. Default::default()
index 17492b8bdcb64bf6537b9e71964872d8639ca41a..2e7d30d969ec4b140c773d744f0e41ca0d9a161f 100644 (file)
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use std::io;
 use std::process::Command;
-use target::TargetOptions;
+use target::{LinkArgs, TargetOptions};
 
 use self::Arch::*;
 
@@ -60,7 +61,7 @@ pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
     }
 }
 
-fn build_pre_link_args(arch: Arch) -> Result<Vec<String>, String> {
+fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
     let sdk_name = match arch {
         Armv7 | Armv7s | Arm64 => "iphoneos",
         I386 | X86_64 => "iphonesimulator"
@@ -70,8 +71,14 @@ fn build_pre_link_args(arch: Arch) -> Result<Vec<String>, String> {
 
     let sdk_root = get_sdk_root(sdk_name)?;
 
-    Ok(vec!["-arch".to_string(), arch_name.to_string(),
-         "-Wl,-syslibroot".to_string(), sdk_root])
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc,
+                vec!["-arch".to_string(),
+                     arch_name.to_string(),
+                     "-Wl,-syslibroot".to_string(),
+                     sdk_root]);
+
+    Ok(args)
 }
 
 fn target_cpu(arch: Arch) -> String {
index c7d2df4344cb1efad4e8b22e6e4551751e25cbb5..bccd5a41ab1155b64d7c5cb9baf1e17b4434613f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -24,6 +25,7 @@ pub fn target() -> TargetResult {
         target_os: "android".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 77d35edfbd09cc465ef90a0a9afe03684a9d56d5..165d34fe6c7cee980c32489f0e8eec8ecfd35bf1 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             features: "+v6".to_string(),
index b183412be1934853bed150bfe546c3141d014cd3..731021d979bc4158db8115bcf560a20f9b569f8e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             features: "+v6,+vfp2".to_string(),
index 261d4353c7a09f6b2623b2c109ed7df084e41cb0..f81bcd78b03aada993d5d78bb13b759df4685a9e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -29,6 +30,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 1443dcf5bad418327f65be7807ee1bf31f4fe504..6c47678ede6adb4067417f33a56504dbc4c57e6d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -29,6 +30,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 37216e20762d4970754319718206dcb94899f2b1..200c6ab74cc6db2a6c9dadd977b908a3a5aafe62 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -21,6 +22,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             features: "+soft-float".to_string(),
@@ -31,4 +33,3 @@ pub fn target() -> TargetResult {
         }
     })
 }
-
index 9e9c443930624311c36e6f8483f8624b5bcf9f13..4d8745828329431459dee1f0120ffff270a92bbf 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "ios".to_string(),
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             features: "+v7,+vfp3,+neon".to_string(),
             max_atomic_width: Some(64),
index 36f409b7948c27ace4ef2e8b6698bff9036ac2f9..0c90e834006f16734761a850aa3fc694abdaf832 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 // See https://developer.android.com/ndk/guides/abis.html#v7a
@@ -27,6 +28,7 @@ pub fn target() -> TargetResult {
         target_os: "android".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 96ccedd5bea5c4b59a0f6a37349d97550e8784c9..d3a6a68449c39f0ad217d7ed4108bbd4bf3e7538 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -21,6 +22,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
@@ -32,4 +34,3 @@ pub fn target() -> TargetResult {
         }
     })
 }
-
index 8f66e6a4f58d484ac385ff5830575eb7fcb47436..5086cd44f7ac947522ba5688231a3e095c1fee24 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -30,6 +31,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
index 6edde6e73efd34415ce62bd70a9b77dd347dcfdc..96c89a7ed3bd58e21caebb77511832f1f1e35468 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "ios".to_string(),
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".to_string(),
             max_atomic_width: Some(64),
index 4d38b0d1705962afa24e58c81801073ea0569d67..b884d4e54101e8ef6eac7705b1f4048b2d99173a 100644 (file)
@@ -8,10 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Target, TargetOptions};
+use LinkerFlavor;
+use super::{LinkArgs, Target, TargetOptions};
 use super::emscripten_base::{cmd};
 
 pub fn target() -> Result<Target, String> {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Em,
+                vec!["-s".to_string(),
+                     "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
+
     let opts = TargetOptions {
         linker: cmd("emcc"),
         ar: cmd("emar"),
@@ -24,7 +30,7 @@ pub fn target() -> Result<Target, String> {
         obj_is_bitcode: true,
         is_like_emscripten: true,
         max_atomic_width: Some(32),
-        post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
+        post_link_args: args,
         target_family: Some("unix".to_string()),
         .. Default::default()
     };
@@ -37,6 +43,7 @@ pub fn target() -> Result<Target, String> {
         target_vendor: "unknown".to_string(),
         data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
         arch: "asmjs".to_string(),
+        linker_flavor: LinkerFlavor::Em,
         options: opts,
     })
 }
index dca33e45af7c7ffc656b02609dedf9dc537b4fa5..e44cd393289be3a23afdd0911c4b2e5e5c7dcb6f 100644 (file)
@@ -8,26 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        // GNU-style linkers will use this to omit linking to libraries
+        // which don't actually fulfill any relocations, but only for
+        // libraries which follow this flag.  Thus, use it before
+        // specifying libraries to link to.
+        "-Wl,--as-needed".to_string(),
+
+        // Always enable NX protection when it is available
+        "-Wl,-z,noexecstack".to_string(),
+    ]);
+
     TargetOptions {
         dynamic_linking: true,
         executables: true,
         target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
-        pre_link_args: vec![
-            // GNU-style linkers will use this to omit linking to libraries
-            // which don't actually fulfill any relocations, but only for
-            // libraries which follow this flag.  Thus, use it before
-            // specifying libraries to link to.
-            "-Wl,--as-needed".to_string(),
-
-            // Always enable NX protection when it is available
-            "-Wl,-z,noexecstack".to_string(),
-        ],
+        pre_link_args: args,
         position_independent_executables: true,
         exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
index dca33e45af7c7ffc656b02609dedf9dc537b4fa5..e44cd393289be3a23afdd0911c4b2e5e5c7dcb6f 100644 (file)
@@ -8,26 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        // GNU-style linkers will use this to omit linking to libraries
+        // which don't actually fulfill any relocations, but only for
+        // libraries which follow this flag.  Thus, use it before
+        // specifying libraries to link to.
+        "-Wl,--as-needed".to_string(),
+
+        // Always enable NX protection when it is available
+        "-Wl,-z,noexecstack".to_string(),
+    ]);
+
     TargetOptions {
         dynamic_linking: true,
         executables: true,
         target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
-        pre_link_args: vec![
-            // GNU-style linkers will use this to omit linking to libraries
-            // which don't actually fulfill any relocations, but only for
-            // libraries which follow this flag.  Thus, use it before
-            // specifying libraries to link to.
-            "-Wl,--as-needed".to_string(),
-
-            // Always enable NX protection when it is available
-            "-Wl,-z,noexecstack".to_string(),
-        ],
+        pre_link_args: args,
         position_independent_executables: true,
         exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
index 8c517224201b2fe7b2e44b5a7812055c9a5cbfb0..c6207cdc4d9c18efa6a76a1102af11b7bb897024 100644 (file)
@@ -8,30 +8,34 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        // We want to be able to strip as much executable code as possible
+        // from the linker command line, and this flag indicates to the
+        // linker that it can avoid linking in dynamic libraries that don't
+        // actually satisfy any symbols up to that point (as with many other
+        // resolutions the linker does). This option only applies to all
+        // following libraries so we're sure to pass it as one of the first
+        // arguments.
+        // FIXME: figure out whether these linker args are desirable
+        //"-Wl,--as-needed".to_string(),
+
+        // Always enable NX protection when it is available
+        //"-Wl,-z,noexecstack".to_string(),
+    ]);
+
     TargetOptions {
         dynamic_linking: true,
         executables: true,
         target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
-        pre_link_args: vec![
-            // We want to be able to strip as much executable code as possible
-            // from the linker command line, and this flag indicates to the
-            // linker that it can avoid linking in dynamic libraries that don't
-            // actually satisfy any symbols up to that point (as with many other
-            // resolutions the linker does). This option only applies to all
-            // following libraries so we're sure to pass it as one of the first
-            // arguments.
-            // FIXME: figure out whether these linker args are desirable
-            //"-Wl,--as-needed".to_string(),
-
-            // Always enable NX protection when it is available
-            //"-Wl,-z,noexecstack".to_string(),
-        ],
+        pre_link_args: args,
         position_independent_executables: true,
         exe_allocation_crate: "alloc_system".to_string(),
         has_elf_tls: true,
index 319ada4f8e17c11b05f56aa50fdebd75c805aca2..a6383179f3ae60292fb2b9baf7d38430a6002a71 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "ios".to_string(),
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             max_atomic_width: Some(64),
             .. base
index d3b09d9a0f1121354a76ce92cb56194e27b0b031..6b14972e9f7543d3613b8f0c8e16071c4f4b00ab 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
     base.cpu = "yonah".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
 
     Ok(Target {
         llvm_target: "i686-apple-darwin".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "macos".to_string(),
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index f8a8f5a3500befb6a1d7a789e7fb2ff078d07421..a5390cbfb725803f68587dd303e2e664da7e9dff 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 // See https://developer.android.com/ndk/guides/abis.html#x86
@@ -31,6 +32,7 @@ pub fn target() -> TargetResult {
         target_os: "android".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 29477261392079332e3e03ed3ba4b13c3fa3c992..4a736a93be7d7867fc9dd60d69c1e65cb72505ff 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -18,7 +19,8 @@ pub fn target() -> TargetResult {
 
     // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
     // space available to x86 Windows binaries on x86_64.
-    base.pre_link_args.push("-Wl,--large-address-aware".to_string());
+    base.pre_link_args
+        .get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--large-address-aware".to_string());
 
     Ok(Target {
         llvm_target: "i686-pc-windows-gnu".to_string(),
@@ -29,6 +31,7 @@ pub fn target() -> TargetResult {
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "pc".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 2290d2057f13076f28ae40ba66e9a9bbaeceaf3e..17fe306804f4a673abfe39d48dc16de527c1ca43 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -17,12 +18,13 @@ pub fn target() -> TargetResult {
 
     // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
     // space available to x86 Windows binaries on x86_64.
-    base.pre_link_args.push("/LARGEADDRESSAWARE".to_string());
+    base.pre_link_args
+        .get_mut(&LinkerFlavor::Msvc).unwrap().push("/LARGEADDRESSAWARE".to_string());
 
     // Ensure the linker will only produce an image if it can also produce a table of
     // the image's safe exception handlers.
     // https://msdn.microsoft.com/en-us/library/9a89h429.aspx
-    base.pre_link_args.push("/SAFESEH".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/SAFESEH".to_string());
 
     Ok(Target {
         llvm_target: "i686-pc-windows-msvc".to_string(),
@@ -33,6 +35,7 @@ pub fn target() -> TargetResult {
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
         target_vendor: "pc".to_string(),
+        linker_flavor: LinkerFlavor::Msvc,
         options: base,
     })
 }
index d8f8431e66e7fa51b3937a8ced9dfedb78d09c3f..052bc23c119ea0a85e013153411d2aae42b69ff6 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
 
     Ok(Target {
         llvm_target: "i686-unknown-dragonfly".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "dragonfly".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index ddbc74f25c9cdd9533283ea759a040239b808a26..d77a9cca2683d9904f50a90320b1093cf34ba035 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
 
     Ok(Target {
         llvm_target: "i686-unknown-freebsd".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "freebsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 9078206c9e069cf3b98ee93c19626d217299d0c3..b0e67bd90ddde351fbc689c37d2b61d69b34912f 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::haiku_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
 
     Ok(Target {
         llvm_target: "i686-unknown-haiku".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "haiku".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index bf9c28b0c10e5ada26c1c2b13462aab4aeb4ff07..3c5c10676260ef9dd847589abd383bdfd51c17c0 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
 
     Ok(Target {
         llvm_target: "i686-unknown-linux-gnu".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index ced59448f7f65d83b3118368408ab92a471dc7b1..3ed8c94d0bf2a834c3798fe1897e5c00736ec04a 100644 (file)
@@ -8,14 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
-    base.pre_link_args.push("-Wl,-melf_i386".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-melf_i386".to_string());
 
     // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind
     // implementation, apparently relies on frame pointers existing... somehow.
@@ -40,6 +41,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index e7e2ee3f9056a09f8af19394836052c9b8fc81e9..fc92e5aee6af1857bb603bbf65fa460eca8b54c6 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
 
     Ok(Target {
         llvm_target: "i686-unknown-netbsdelf".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "netbsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 81efd37386a0f9232148e4d83c068526f3c634be..7ef68bd6d9c3a3164c83a6817ca4fe863a0d2127 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::openbsd_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
 
     Ok(Target {
         llvm_target: "i686-unknown-openbsd".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "openbsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 891e7dda14a2a4d931e3171966e97d4e7a53fb1e..f4265e0eb1462d2bd7bc5abf466088aa369ad869 100644 (file)
@@ -8,17 +8,25 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Target, TargetOptions, TargetResult};
+use LinkerFlavor;
+use super::{LinkArgs, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
+    let mut pre_link_args = LinkArgs::new();
+    pre_link_args.insert(LinkerFlavor::Gcc,
+                         vec!["--pnacl-exceptions=sjlj".to_string(),
+                              "--target=le32-unknown-nacl".to_string(),
+                              "-Wl,--start-group".to_string()]);
+    let mut post_link_args = LinkArgs::new();
+    post_link_args.insert(LinkerFlavor::Gcc,
+                          vec!["-Wl,--end-group".to_string()]);
+
     let opts = TargetOptions {
         linker: "pnacl-clang".to_string(),
         ar: "pnacl-ar".to_string(),
 
-        pre_link_args: vec!["--pnacl-exceptions=sjlj".to_string(),
-                            "--target=le32-unknown-nacl".to_string(),
-                            "-Wl,--start-group".to_string()],
-        post_link_args: vec!["-Wl,--end-group".to_string()],
+        pre_link_args: pre_link_args,
+        post_link_args: post_link_args,
         dynamic_linking: false,
         executables: true,
         exe_suffix: ".pexe".to_string(),
@@ -36,6 +44,7 @@ pub fn target() -> TargetResult {
         target_vendor: "unknown".to_string(),
         data_layout: "e-i64:64:64-p:32:32:32-v128:32:32".to_string(),
         arch: "le32".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: opts,
     })
 }
index 4b2ae9c8e699c1e23ca0f056afff69d02faf1ea1..722d2fa16ef7a06a23689366bbf3af017cc0984f 100644 (file)
@@ -8,29 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        // We want to be able to strip as much executable code as possible
+        // from the linker command line, and this flag indicates to the
+        // linker that it can avoid linking in dynamic libraries that don't
+        // actually satisfy any symbols up to that point (as with many other
+        // resolutions the linker does). This option only applies to all
+        // following libraries so we're sure to pass it as one of the first
+        // arguments.
+        "-Wl,--as-needed".to_string(),
+
+        // Always enable NX protection when it is available
+        "-Wl,-z,noexecstack".to_string(),
+    ]);
+
     TargetOptions {
         dynamic_linking: true,
         executables: true,
         target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
-        pre_link_args: vec![
-            // We want to be able to strip as much executable code as possible
-            // from the linker command line, and this flag indicates to the
-            // linker that it can avoid linking in dynamic libraries that don't
-            // actually satisfy any symbols up to that point (as with many other
-            // resolutions the linker does). This option only applies to all
-            // following libraries so we're sure to pass it as one of the first
-            // arguments.
-            "-Wl,--as-needed".to_string(),
-
-            // Always enable NX protection when it is available
-            "-Wl,-z,noexecstack".to_string(),
-        ],
+        pre_link_args: args,
         position_independent_executables: true,
         exe_allocation_crate: super::maybe_jemalloc(),
         has_elf_tls: true,
index 18cca425a32c8c43452f34f304d3c8cc5cf4bbf3..236f2c1ef0aa3a983b1b3df47eca904fa8264d22 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::TargetOptions;
 
 pub fn opts() -> TargetOptions {
@@ -15,13 +16,13 @@ pub fn opts() -> TargetOptions {
 
     // Make sure that the linker/gcc really don't pull in anything, including
     // default objects, libs, etc.
-    base.pre_link_args.push("-nostdlib".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
 
     // At least when this was tested, the linker would not add the
     // `GNU_EH_FRAME` program header to executables generated, which is required
     // when unwinding to locate the unwinding information. I'm not sure why this
     // argument is *not* necessary for normal builds, but it can't hurt!
-    base.pre_link_args.push("-Wl,--eh-frame-hdr".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--eh-frame-hdr".to_string());
 
     // There's a whole bunch of circular dependencies when dealing with MUSL
     // unfortunately. To put this in perspective libc is statically linked to
@@ -45,8 +46,8 @@ pub fn opts() -> TargetOptions {
     // link everything as a group, not stripping anything out until everything
     // is processed. The linker will still perform a pass to strip out object
     // files but it won't do so until all objects/archives have been processed.
-    base.pre_link_args.push("-Wl,-(".to_string());
-    base.post_link_args.push("-Wl,-)".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-(".to_string());
+    base.post_link_args.insert(LinkerFlavor::Gcc, vec!["-Wl,-)".to_string()]);
 
     // When generating a statically linked executable there's generally some
     // small setup needed which is listed in these files. These are provided by
index c284840ecb4bdbdc3b06714732a85fabbe51d93d..038a70ed6b17ee3e700405f71d6a988e8f9b094a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".to_string(),
index 17895836fe87b54dba7020dbd5b2d00be9c0ecfd..aed4c4fbb08deb90479fac1533c2d6e848b90847 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".to_string(),
index a6d8fae2536cae8628ab3d3b09fb64553ff442d1..9ef61f9caddcdbaf6bd59001ca142f3e340f8d2b 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             cpu: "mips32r2".to_string(),
             features: "+mips32r2".to_string(),
index e4a6d2a55d9813ea4ea188540edae6126447ff1d..f54790bab970b85b0c67d39b22386db08fca0e80 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+soft-float".to_string(),
index ccc64ea393b7885694640f22b6373ed7dfedf4f3..59c07efe0fdc1818fe7125413d9dceecf0a89c3d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "uclibc".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+soft-float".to_string(),
index 9b8b1d5713f1d950771a36d3da49fe750208d944..ec19cc1a536ad7f45a5b9efffdd6a8ec8630c291 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             cpu: "mips32".to_string(),
index 5693bddd0488a51c780e53dbc07c2e641748e345..00085d18e6d09eb7f8953993d866fc25e5b41a0d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             cpu: "mips32".to_string(),
             features: "+mips32,+soft-float".to_string(),
index 3acade5a474445f1431585dbc0d62a79fed5a369..b3ca2edec1eda57d60122665c2b3d6654d8e3fe7 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -20,6 +21,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "uclibc".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             cpu: "mips32".to_string(),
index 559418d2c4f5ffae02822040f3ed612b3d8b3085..ca6894a7b70411ae74cb94db2d386f09bc0aa3ae 100644 (file)
@@ -50,7 +50,7 @@
 use std::io::prelude::*;
 use syntax::abi::{Abi, lookup as lookup_abi};
 
-use PanicStrategy;
+use {LinkerFlavor, PanicStrategy};
 
 mod android_base;
 mod apple_base;
@@ -72,6 +72,7 @@
 mod fuchsia_base;
 mod redox_base;
 
+pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
 pub type TargetResult = Result<Target, String>;
 
 macro_rules! supported_targets {
@@ -241,6 +242,8 @@ pub struct Target {
     pub arch: String,
     /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
     pub data_layout: String,
+    /// Linker flavor
+    pub linker_flavor: LinkerFlavor,
     /// Optional settings with defaults.
     pub options: TargetOptions,
 }
@@ -261,7 +264,7 @@ pub struct TargetOptions {
 
     /// Linker arguments that are unconditionally passed *before* any
     /// user-defined libraries.
-    pub pre_link_args: Vec<String>,
+    pub pre_link_args: LinkArgs,
     /// Objects to link before all others, always found within the
     /// sysroot folder.
     pub pre_link_objects_exe: Vec<String>, // ... when linking an executable
@@ -269,13 +272,13 @@ pub struct TargetOptions {
     /// Linker arguments that are unconditionally passed after any
     /// user-defined but before post_link_objects.  Standard platform
     /// libraries that should be always be linked to, usually go here.
-    pub late_link_args: Vec<String>,
+    pub late_link_args: LinkArgs,
     /// Objects to link after all others, always found within the
     /// sysroot folder.
     pub post_link_objects: Vec<String>,
     /// Linker arguments that are unconditionally passed *after* any
     /// user-defined libraries.
-    pub post_link_args: Vec<String>,
+    pub post_link_args: LinkArgs,
 
     /// Extra arguments to pass to the external assembler (when used)
     pub asm_args: Vec<String>,
@@ -412,8 +415,8 @@ fn default() -> TargetOptions {
             is_builtin: false,
             linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(),
             ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(),
-            pre_link_args: Vec::new(),
-            post_link_args: Vec::new(),
+            pre_link_args: LinkArgs::new(),
+            post_link_args: LinkArgs::new(),
             asm_args: Vec::new(),
             cpu: "generic".to_string(),
             features: "".to_string(),
@@ -445,7 +448,7 @@ fn default() -> TargetOptions {
             pre_link_objects_exe: Vec::new(),
             pre_link_objects_dll: Vec::new(),
             post_link_objects: Vec::new(),
-            late_link_args: Vec::new(),
+            late_link_args: LinkArgs::new(),
             archive_format: "gnu".to_string(),
             custom_unwind_resume: false,
             lib_allocation_crate: "alloc_system".to_string(),
@@ -529,6 +532,10 @@ pub fn from_json(obj: Json) -> TargetResult {
             target_os: get_req_field("os")?,
             target_env: get_opt_field("env", ""),
             target_vendor: get_opt_field("vendor", "unknown"),
+            linker_flavor: LinkerFlavor::from_str(&*get_req_field("linker-flavor")?)
+                .ok_or_else(|| {
+                    format!("linker flavor must be {}", LinkerFlavor::one_of())
+                })?,
             options: Default::default(),
         };
 
@@ -579,17 +586,49 @@ macro_rules! key {
                         .map(|s| s.to_string() );
                 }
             } );
+            ($key_name:ident, LinkerFlavor) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                obj.find(&name[..]).and_then(|o| o.as_string().map(|s| {
+                    LinkerFlavor::from_str(&s).ok_or_else(|| {
+                        Err(format!("'{}' is not a valid value for linker-flavor. \
+                                     Use 'em', 'gcc', 'ld' or 'msvc.", s))
+                    })
+                })).unwrap_or(Ok(()))
+            } );
+            ($key_name:ident, link_args) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                if let Some(obj) = obj.find(&name[..]).and_then(|o| o.as_object()) {
+                    let mut args = LinkArgs::new();
+                    for (k, v) in obj {
+                        let k = LinkerFlavor::from_str(&k).ok_or_else(|| {
+                            format!("{}: '{}' is not a valid value for linker-flavor. \
+                                     Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
+                        })?;
+
+                        let v = v.as_array().map(|a| {
+                            a
+                                .iter()
+                                .filter_map(|o| o.as_string())
+                                .map(|s| s.to_owned())
+                                .collect::<Vec<_>>()
+                        }).unwrap_or(vec![]);
+
+                        args.insert(k, v);
+                    }
+                    base.options.$key_name = args;
+                }
+            } );
         }
 
         key!(is_builtin, bool);
         key!(linker);
         key!(ar);
-        key!(pre_link_args, list);
+        key!(pre_link_args, link_args);
         key!(pre_link_objects_exe, list);
         key!(pre_link_objects_dll, list);
-        key!(late_link_args, list);
+        key!(late_link_args, link_args);
         key!(post_link_objects, list);
-        key!(post_link_args, list);
+        key!(post_link_args, link_args);
         key!(asm_args, list);
         key!(cpu);
         key!(features);
@@ -734,6 +773,16 @@ macro_rules! target_option_val {
                     d.insert(name.to_string(), self.options.$attr.to_json());
                 }
             } );
+            (link_args - $attr:ident) => ( {
+                let name = (stringify!($attr)).replace("_", "-");
+                if default.$attr != self.options.$attr {
+                    let obj = self.options.$attr
+                        .iter()
+                        .map(|(k, v)| (k.desc().to_owned(), v.clone()))
+                        .collect::<BTreeMap<_, _>>();
+                    d.insert(name.to_string(), obj.to_json());
+                }
+            } );
         }
 
         target_val!(llvm_target);
@@ -743,18 +792,18 @@ macro_rules! target_option_val {
         target_val!(target_os, "os");
         target_val!(target_env, "env");
         target_val!(target_vendor, "vendor");
-        target_val!(arch);
         target_val!(data_layout);
+        target_val!(linker_flavor);
 
         target_option_val!(is_builtin);
         target_option_val!(linker);
         target_option_val!(ar);
-        target_option_val!(pre_link_args);
+        target_option_val!(link_args - pre_link_args);
         target_option_val!(pre_link_objects_exe);
         target_option_val!(pre_link_objects_dll);
-        target_option_val!(late_link_args);
+        target_option_val!(link_args - late_link_args);
         target_option_val!(post_link_objects);
-        target_option_val!(post_link_args);
+        target_option_val!(link_args - post_link_args);
         target_option_val!(asm_args);
         target_option_val!(cpu);
         target_option_val!(features);
index 57179a68afd8e9ccdc79bb1f459296277bca6339..63245fcae767b34841a6cf9448b21c2518ef1a6c 100644 (file)
@@ -8,26 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        // GNU-style linkers will use this to omit linking to libraries
+        // which don't actually fulfill any relocations, but only for
+        // libraries which follow this flag.  Thus, use it before
+        // specifying libraries to link to.
+        "-Wl,--as-needed".to_string(),
+
+        // Always enable NX protection when it is available
+        "-Wl,-z,noexecstack".to_string(),
+    ]);
+
     TargetOptions {
         dynamic_linking: true,
         executables: true,
         target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
-        pre_link_args: vec![
-            // GNU-style linkers will use this to omit linking to libraries
-            // which don't actually fulfill any relocations, but only for
-            // libraries which follow this flag.  Thus, use it before
-            // specifying libraries to link to.
-            "-Wl,--as-needed".to_string(),
-
-            // Always enable NX protection when it is available
-            "-Wl,-z,noexecstack".to_string(),
-        ],
+        pre_link_args: args,
         position_independent_executables: true,
         .. Default::default()
     }
index 12b8e8bdc88fd931e776664af40136cacf0afd81..2df9b8e03ff535866f8428d5ac9aa88f23693ba4 100644 (file)
@@ -8,10 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        // GNU-style linkers will use this to omit linking to libraries
+        // which don't actually fulfill any relocations, but only for
+        // libraries which follow this flag.  Thus, use it before
+        // specifying libraries to link to.
+        "-Wl,--as-needed".to_string(),
+
+        // Always enable NX protection when it is available
+        "-Wl,-z,noexecstack".to_string(),
+    ]);
+
     TargetOptions {
         dynamic_linking: true,
         executables: true,
@@ -19,16 +32,7 @@ pub fn opts() -> TargetOptions {
         linker_is_gnu: true,
         has_rpath: true,
         is_like_openbsd: true,
-        pre_link_args: vec![
-            // GNU-style linkers will use this to omit linking to libraries
-            // which don't actually fulfill any relocations, but only for
-            // libraries which follow this flag.  Thus, use it before
-            // specifying libraries to link to.
-            "-Wl,--as-needed".to_string(),
-
-            // Always enable NX protection when it is available
-            "-Wl,-z,noexecstack".to_string(),
-        ],
+        pre_link_args: args,
         position_independent_executables: true,
         exe_allocation_crate: "alloc_system".to_string(),
         .. Default::default()
index 909c5488dcb70374eaae5535870fe9606428af24..55a5bfd1e674621bf02d294439bba4c10a1485a3 100644 (file)
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "ppc64".to_string();
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
 
     // see #36994
@@ -28,6 +29,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index a692346ca0ffeeb95a88bf2183f3eea8b6ca4f90..c22bc3b041a4ee2d41dd0903347015dbab12546b 100644 (file)
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "ppc64le".to_string();
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
 
     // see #36994
@@ -28,6 +29,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 284772c43319aedf193fd12af276ea1586adbd14..677d198b1a379a315158c8d13428fe5401ca4665 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
-    base.pre_link_args.push("-m32".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
     base.max_atomic_width = Some(32);
 
     // see #36994
@@ -27,6 +28,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index c5e1e107753ffa80c56b543d5e04e29daa5c689b..f26a86d4bdc0f13c4bc60de2626eaf442e3e882b 100644 (file)
@@ -8,25 +8,28 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use PanicStrategy;
-use target::TargetOptions;
+use {LinkerFlavor, PanicStrategy};
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
-    TargetOptions {
-        pre_link_args: vec![
-            // We want to be able to strip as much executable code as possible
-            // from the linker command line, and this flag indicates to the
-            // linker that it can avoid linking in dynamic libraries that don't
-            // actually satisfy any symbols up to that point (as with many other
-            // resolutions the linker does). This option only applies to all
-            // following libraries so we're sure to pass it as one of the first
-            // arguments.
-            "-Wl,--as-needed".to_string(),
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        // We want to be able to strip as much executable code as possible
+        // from the linker command line, and this flag indicates to the
+        // linker that it can avoid linking in dynamic libraries that don't
+        // actually satisfy any symbols up to that point (as with many other
+        // resolutions the linker does). This option only applies to all
+        // following libraries so we're sure to pass it as one of the first
+        // arguments.
+        "-Wl,--as-needed".to_string(),
+
+        // Always enable NX protection when it is available
+        "-Wl,-z,noexecstack".to_string()
+    ]);
 
-            // Always enable NX protection when it is available
-            "-Wl,-z,noexecstack".to_string()
-        ],
+    TargetOptions {
+        pre_link_args: args,
         executables: true,
         relocation_model: "static".to_string(),
         disable_redzone: true,
index 671fb4f4319b35f5d1c592aee2ddf4145dac6524..cc8eb7c4e84243e281e54086220474d7f22c0366 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -31,6 +32,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index f627cc18f0b3d709dbdd513e0ad3de4fba6e2b43..1bd51ac62581f06ee4e5104607376285694473e5 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index f30cebbc2d5a7e91c292eb875d10919794056b9f..bc65a17ce6ea93063743a2d44646133437201150 100644 (file)
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
     base.cpu = "v9".to_string();
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
 
     Ok(Target {
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "netbsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index c88e5a402f2f545e0719b0178848d9314730368d..122b38968a9c0355e74e258c11084408102be7fc 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::solaris_base::opts();
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
     // llvm calls this "v9"
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
@@ -30,6 +31,7 @@ pub fn target() -> TargetResult {
         target_os: "solaris".to_string(),
         target_env: "".to_string(),
         target_vendor: "sun".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 6c22f98538459ea5711308df1729b475ec60ab97..08bf145e5518ac8911a5ae34c676565437aaea80 100644 (file)
@@ -10,6 +10,7 @@
 
 // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "none".to_string(),
         target_env: "".to_string(),
         target_vendor: "".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
index ddad4e3624f3cef16a960f8f5058fcf82f2370e1..13f9cc5f65fb9bd3db0f2ba1fdd66b5a48e0a5c5 100644 (file)
@@ -19,6 +19,7 @@
 // To opt-in to hardware accelerated floating point operations, you can use, for example,
 // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -31,6 +32,7 @@ pub fn target() -> TargetResult {
         target_os: "none".to_string(),
         target_env: "".to_string(),
         target_vendor: "".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             max_atomic_width: Some(32),
index a9fac48e8e5ac39c549ea88439af6d99851d8102..929b6db6fb2c60b7914139ddd3f80776c7d0d37e 100644 (file)
@@ -18,6 +18,7 @@
 //
 // To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -30,6 +31,7 @@ pub fn target() -> TargetResult {
         target_os: "none".to_string(),
         target_env: "".to_string(),
         target_vendor: "".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
index ed61dd0459b4d7c23ac8a5012d83ba514d846a12..8d46e7cb90760bb5903a9b6dc29814edd8a18f91 100644 (file)
@@ -10,6 +10,7 @@
 
 // Targets the Cortex-M3 processor (ARMv7-M)
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "none".to_string(),
         target_env: "".to_string(),
         target_vendor: "".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
             max_atomic_width: Some(32),
index b1967fa8f37a7aea5c3052d48d45e24bfbbf4098..a51f59d6ff1925e9222fce68a01ef378c92dec12 100644 (file)
@@ -8,10 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Target, TargetOptions};
+use LinkerFlavor;
+use super::{LinkArgs, Target, TargetOptions};
 use super::emscripten_base::{cmd};
 
 pub fn target() -> Result<Target, String> {
+    let mut post_link_args = LinkArgs::new();
+    post_link_args.insert(LinkerFlavor::Gcc,
+                          vec!["-s".to_string(),
+                               "BINARYEN=1".to_string(),
+                               "-s".to_string(),
+                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
+
     let opts = TargetOptions {
         linker: cmd("emcc"),
         ar: cmd("emar"),
@@ -26,8 +34,7 @@ pub fn target() -> Result<Target, String> {
         obj_is_bitcode: true,
         is_like_emscripten: true,
         max_atomic_width: Some(32),
-        post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(),
-                             "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
+        post_link_args: post_link_args,
         target_family: Some("unix".to_string()),
         .. Default::default()
     };
@@ -40,6 +47,7 @@ pub fn target() -> Result<Target, String> {
         target_vendor: "unknown".to_string(),
         data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
         arch: "wasm32".to_string(),
+        linker_flavor: LinkerFlavor::Em,
         options: opts,
     })
 }
index db02e142fcc8efac34aca9480845a87696be1cdf..9bde24a28dd9b253ed14c0a1a5f8e3fe4d244921 100644 (file)
@@ -8,26 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
-    TargetOptions {
-        // FIXME(#13846) this should be enabled for windows
-        function_sections: false,
-        linker: "gcc".to_string(),
-        dynamic_linking: true,
-        executables: true,
-        dll_prefix: "".to_string(),
-        dll_suffix: ".dll".to_string(),
-        exe_suffix: ".exe".to_string(),
-        staticlib_prefix: "".to_string(),
-        staticlib_suffix: ".lib".to_string(),
-        no_default_libraries: true,
-        target_family: Some("windows".to_string()),
-        is_like_windows: true,
-        allows_weak_linkage: false,
-        pre_link_args: vec![
+    let mut pre_link_args = LinkArgs::new();
+    pre_link_args.insert(LinkerFlavor::Gcc, vec![
             // And here, we see obscure linker flags #45. On windows, it has been
             // found to be necessary to have this flag to compile liblibc.
             //
@@ -64,7 +51,34 @@ pub fn opts() -> TargetOptions {
 
             // Do not use the standard system startup files or libraries when linking
             "-nostdlib".to_string(),
-        ],
+        ]);
+
+    let mut late_link_args = LinkArgs::new();
+    late_link_args.insert(LinkerFlavor::Gcc, vec![
+        "-lmingwex".to_string(),
+        "-lmingw32".to_string(),
+        "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
+        "-lmsvcrt".to_string(),
+        "-luser32".to_string(),
+        "-lkernel32".to_string(),
+    ]);
+
+    TargetOptions {
+        // FIXME(#13846) this should be enabled for windows
+        function_sections: false,
+        linker: "gcc".to_string(),
+        dynamic_linking: true,
+        executables: true,
+        dll_prefix: "".to_string(),
+        dll_suffix: ".dll".to_string(),
+        exe_suffix: ".exe".to_string(),
+        staticlib_prefix: "".to_string(),
+        staticlib_suffix: ".lib".to_string(),
+        no_default_libraries: true,
+        target_family: Some("windows".to_string()),
+        is_like_windows: true,
+        allows_weak_linkage: false,
+        pre_link_args: pre_link_args,
         pre_link_objects_exe: vec![
             "crt2.o".to_string(),    // mingw C runtime initialization for executables
             "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
@@ -73,14 +87,7 @@ pub fn opts() -> TargetOptions {
             "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
             "rsbegin.o".to_string(),
         ],
-        late_link_args: vec![
-            "-lmingwex".to_string(),
-            "-lmingw32".to_string(),
-            "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
-            "-lmsvcrt".to_string(),
-            "-luser32".to_string(),
-            "-lkernel32".to_string(),
-        ],
+        late_link_args: late_link_args,
         post_link_objects: vec![
             "rsend.o".to_string()
         ],
index efa215b419d7044fed385b8b176d2f664a6e3bc1..421f59aea93bf4acba458dd5622be1641f832746 100644 (file)
@@ -8,10 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Msvc,
+                vec!["/NOLOGO".to_string(),
+                     "/NXCOMPAT".to_string()]);
+
     TargetOptions {
         function_sections: true,
         linker: "link.exe".to_string(),
@@ -56,10 +62,7 @@ pub fn opts() -> TargetOptions {
         target_family: Some("windows".to_string()),
         is_like_windows: true,
         is_like_msvc: true,
-        pre_link_args: vec![
-            "/NOLOGO".to_string(),
-            "/NXCOMPAT".to_string(),
-        ],
+        pre_link_args: args,
         exe_allocation_crate: "alloc_system".to_string(),
 
         .. Default::default()
index b3c1561dbcc0bb06f2556b1a68a1f34244388d41..8fd1b80430f44795aa62ff0749cc301988abfed3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -15,7 +16,7 @@ pub fn target() -> TargetResult {
     base.cpu = "core2".to_string();
     base.max_atomic_width = Some(128); // core2 support cmpxchg16b
     base.eliminate_frame_pointer = false;
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
 
     Ok(Target {
         llvm_target: "x86_64-apple-darwin".to_string(),
@@ -26,6 +27,7 @@ pub fn target() -> TargetResult {
         target_os: "macos".to_string(),
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 7a58bb34ce7f6e67eeefb15074917a3ef5ab00c4..bbd81fd86ff578e2e2f9e4cb6576277f21879eb3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
@@ -22,6 +23,7 @@ pub fn target() -> TargetResult {
         target_os: "ios".to_string(),
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             max_atomic_width: Some(64),
             .. base
index 321585cd65eb39020824daeaffc3da90b70164d9..10e88d88ee372c97fdb3b27c2479723cf1fa244c 100644 (file)
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_base::opts();
     base.cpu = "x86-64".to_string();
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
 
     Ok(Target {
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "pc".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index ea8909d213e80b79463cae221a7a634f679b5ca0..b07031c4bf1a3de5b13ba9d196a50b1d17860c8a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
@@ -24,6 +25,7 @@ pub fn target() -> TargetResult {
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
         target_vendor: "pc".to_string(),
+        linker_flavor: LinkerFlavor::Msvc,
         options: base,
     })
 }
index 33137214396961a05e7fff8139bd7e341ad7da37..eea4389cfd64eaee7e5f8bfd79166ca552e470f6 100644 (file)
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
     base.cpu = "x86-64".to_string();
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
     base.ar = "x86_64-rumprun-netbsd-ar".to_string();
     base.max_atomic_width = Some(64);
@@ -34,6 +35,7 @@ pub fn target() -> TargetResult {
         target_os: "netbsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "rumprun".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 8e4fd94e7bce4375afd14a991f5cb1b5cde92271..fe8691f36950dc5aa31807daf3de80a7e6eaaf7b 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::solaris_base::opts();
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
 
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "solaris".to_string(),
         target_env: "".to_string(),
         target_vendor: "sun".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index eda16c29466b54ce5e8a2c2276dfb2ba261d034a..5f87fe177a98c04dfc21c04e5cfff594d06ff175 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::bitrig_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
 
     Ok(Target {
         llvm_target: "x86_64-unknown-bitrig".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "bitrig".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 194efb8fc232254af9523d0ad249a1644bb46aa1..96f608409ffa7610ed9c28a3619f35b2b26e646c 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-dragonfly".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "dragonfly".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index b127bee163b86ed5df3a610a3d00711eff51c024..500629a16808dd3f88125ec53dfd376bfb36c637 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-freebsd".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "freebsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 08fe17a556ecca1f74a5f81d7bc0a700ebd26eb0..6e37896d4148bd1790d10fc41b16f5a713db7b91 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::fuchsia_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-fuchsia".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "fuchsia".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 7cf0599037c1e97efd71fac637aac8fbfad3af4b..7fab9128b2952f538569539b637dafee5daf1d5c 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::haiku_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
 
     Ok(Target {
         llvm_target: "x86_64-unknown-haiku".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "haiku".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index f95bcb556e57f0bf3ac2838e6c36f7acf67de42d..f73055cebaa2e2ff0f94a3cb2ce6eee402501989 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-linux-gnu".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index c3bf9dcca6ee4ff9e24d0e2522b3aae4a59a07e9..38b9c0bace52b1fe73530d66ab0f86549196706f 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-linux-musl".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 87a7c184644d57082215e8cf465c38674529f981..6fe2e3fc08e23e30de5bb716949d8d8d0a70c775 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-netbsd".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "netbsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index e9d645b0d38f259f74f4a29d21aa2c1f3b08ba34..b292b5fc1e4e4720f6a771088509555b33299b4c 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::openbsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-openbsd".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "openbsd".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index cecac06b235275a6b18162e7b532c9168ff983c3..a693e76099bdafa27b8f013d58e56bd438cc50ac 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::redox_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.push("-m64".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
 
     Ok(Target {
         llvm_target: "x86_64-unknown-redox".to_string(),
@@ -25,6 +26,7 @@ pub fn target() -> TargetResult {
         target_os: "redox".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
 }
index 29fbcb70756ba08adeca9c87caff42d202225183..adb22197226023fcb80731626f1ecc97255275f7 100644 (file)
 use std::mem;
 use std::collections::range::RangeArgument;
 use std::collections::Bound::{Excluded, Included, Unbounded};
+use std::mem::ManuallyDrop;
 
 pub unsafe trait Array {
     type Element;
-    type PartialStorage: Default + Unsize<[ManuallyDrop<Self::Element>]>;
+    type PartialStorage: Unsize<[ManuallyDrop<Self::Element>]>;
     const LEN: usize;
 }
 
@@ -66,7 +67,7 @@ impl<A: Array> ArrayVec<A> {
     pub fn new() -> Self {
         ArrayVec {
             count: 0,
-            values: Default::default(),
+            values: unsafe { ::std::mem::uninitialized() },
         }
     }
 
@@ -81,7 +82,7 @@ pub unsafe fn set_len(&mut self, len: usize) {
     /// Panics when the stack vector is full.
     pub fn push(&mut self, el: A::Element) {
         let arr = &mut self.values as &mut [ManuallyDrop<_>];
-        arr[self.count] = ManuallyDrop { value: el };
+        arr[self.count] = ManuallyDrop::new(el);
         self.count += 1;
     }
 
@@ -90,8 +91,8 @@ pub fn pop(&mut self) -> Option<A::Element> {
             let arr = &mut self.values as &mut [ManuallyDrop<_>];
             self.count -= 1;
             unsafe {
-                let value = ptr::read(&arr[self.count]);
-                Some(value.value)
+                let value = ptr::read(&*arr[self.count]);
+                Some(value)
             }
         } else {
             None
@@ -210,7 +211,7 @@ impl<A: Array> Iterator for Iter<A> {
     fn next(&mut self) -> Option<A::Element> {
         let arr = &self.store as &[ManuallyDrop<_>];
         unsafe {
-            self.indices.next().map(|i| ptr::read(&arr[i]).value)
+            self.indices.next().map(|i| ptr::read(&*arr[i]))
         }
     }
 
@@ -233,7 +234,7 @@ impl<'a, A: Array> Iterator for Drain<'a, A> {
 
     #[inline]
     fn next(&mut self) -> Option<A::Element> {
-        self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value })
+        self.iter.next().map(|elt| unsafe { ptr::read(&**elt) })
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
@@ -295,25 +296,3 @@ fn into_iter(self) -> Self::IntoIter {
         self.iter_mut()
     }
 }
-
-// FIXME: This should use repr(transparent) from rust-lang/rfcs#1758.
-#[allow(unions_with_drop_fields)]
-pub union ManuallyDrop<T> {
-    value: T,
-    #[allow(dead_code)]
-    empty: (),
-}
-
-impl<T> ManuallyDrop<T> {
-    fn new() -> ManuallyDrop<T> {
-        ManuallyDrop {
-            empty: ()
-        }
-    }
-}
-
-impl<T> Default for ManuallyDrop<T> {
-    fn default() -> Self {
-        ManuallyDrop::new()
-    }
-}
index c1735b4a4ec9a588156757293152deb775fa1129..72c533a74618b8185eae1cb22807539ef56cdb4f 100644 (file)
@@ -39,6 +39,7 @@
 #![feature(conservative_impl_trait)]
 #![feature(discriminant_value)]
 #![feature(specialization)]
+#![feature(manually_drop)]
 
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
index c90dde3a5f6e0232694ae37dec7e11e70c91b446..1a892b73aa5d771c86f6f2dd1c09796763647997 100644 (file)
@@ -517,6 +517,16 @@ fn build_controller(&mut self,
             control.make_glob_map = resolve::MakeGlobMap::Yes;
         }
 
+        if sess.print_fuel_crate.is_some() {
+            let old_callback = control.compilation_done.callback;
+            control.compilation_done.callback = box move |state| {
+                old_callback(state);
+                let sess = state.session;
+                println!("Fuel used by {}: {}",
+                    sess.print_fuel_crate.as_ref().unwrap(),
+                    sess.print_fuel.get());
+            }
+        }
         control
     }
 }
index 12a1ffa2767255aa325b6f3eff380d6fad49ca44..66380079a8b29038538e18324455f68bce83deb4 100644 (file)
@@ -707,13 +707,16 @@ fn link_natively(sess: &Session,
                  outputs: &OutputFilenames,
                  tmpdir: &Path) {
     info!("preparing {:?} from {:?} to {:?}", crate_type, objects, out_filename);
+    let flavor = sess.linker_flavor();
 
     // The invocations of cc share some flags across platforms
     let (pname, mut cmd, extra) = get_linker(sess);
     cmd.env("PATH", command_path(sess, extra));
 
     let root = sess.target_filesearch(PathKind::Native).get_lib_path();
-    cmd.args(&sess.target.target.options.pre_link_args);
+    if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
+        cmd.args(args);
+    }
 
     let pre_link_objects = if crate_type == config::CrateTypeExecutable {
         &sess.target.target.options.pre_link_objects_exe
@@ -739,11 +742,15 @@ fn link_natively(sess: &Session,
                   objects, out_filename, outputs, trans);
         cmd = linker.finalize();
     }
-    cmd.args(&sess.target.target.options.late_link_args);
+    if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
+        cmd.args(args);
+    }
     for obj in &sess.target.target.options.post_link_objects {
         cmd.arg(root.join(obj));
     }
-    cmd.args(&sess.target.target.options.post_link_args);
+    if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
+        cmd.args(args);
+    }
 
     if sess.opts.debugging_opts.print_link_args {
         println!("{:?}", &cmd);
index a178d17a7c2d371f01e17ce87fc7cd22a41efab7..61c57f00de70d5b00c229933d4ff5148767e963b 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::collections::HashMap;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufWriter};
@@ -22,6 +22,7 @@
 use back::symbol_export::{self, ExportedSymbols};
 use middle::dependency_format::Linkage;
 use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
+use rustc_back::LinkerFlavor;
 use session::Session;
 use session::config::{self, CrateType, OptLevel, DebugInfoLevel};
 use serialize::{json, Encoder};
@@ -45,25 +46,39 @@ pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
     pub fn to_linker(&'a self,
                      cmd: Command,
                      sess: &'a Session) -> Box<Linker+'a> {
-        if sess.target.target.options.is_like_msvc {
-            Box::new(MsvcLinker {
-                cmd: cmd,
-                sess: sess,
-                info: self
-            }) as Box<Linker>
-        } else if sess.target.target.options.is_like_emscripten {
-            Box::new(EmLinker {
-                cmd: cmd,
-                sess: sess,
-                info: self
-            }) as Box<Linker>
-        } else {
-            Box::new(GnuLinker {
-                cmd: cmd,
-                sess: sess,
-                info: self,
-                hinted_static: false,
-            }) as Box<Linker>
+        match sess.linker_flavor() {
+            LinkerFlavor::Msvc => {
+                Box::new(MsvcLinker {
+                    cmd: cmd,
+                    sess: sess,
+                    info: self
+                }) as Box<Linker>
+            }
+            LinkerFlavor::Em =>  {
+                Box::new(EmLinker {
+                    cmd: cmd,
+                    sess: sess,
+                    info: self
+                }) as Box<Linker>
+            }
+            LinkerFlavor::Gcc =>  {
+                Box::new(GccLinker {
+                    cmd: cmd,
+                    sess: sess,
+                    info: self,
+                    hinted_static: false,
+                    is_ld: false,
+                }) as Box<Linker>
+            }
+            LinkerFlavor::Ld => {
+                Box::new(GccLinker {
+                    cmd: cmd,
+                    sess: sess,
+                    info: self,
+                    hinted_static: false,
+                    is_ld: true,
+                }) as Box<Linker>
+            }
         }
     }
 }
@@ -100,14 +115,32 @@ pub trait Linker {
     fn finalize(&mut self) -> Command;
 }
 
-pub struct GnuLinker<'a> {
+pub struct GccLinker<'a> {
     cmd: Command,
     sess: &'a Session,
     info: &'a LinkerInfo,
     hinted_static: bool, // Keeps track of the current hinting mode.
+    // Link as ld
+    is_ld: bool,
 }
 
-impl<'a> GnuLinker<'a> {
+impl<'a> GccLinker<'a> {
+    /// Argument that must be passed *directly* to the linker
+    ///
+    /// These arguments need to be prepended with '-Wl,' when a gcc-style linker is used
+    fn linker_arg<S>(&mut self, arg: S) -> &mut Self
+        where S: AsRef<OsStr>
+    {
+        if !self.is_ld {
+            let mut os = OsString::from("-Wl,");
+            os.push(arg.as_ref());
+            self.cmd.arg(os);
+        } else {
+            self.cmd.arg(arg);
+        }
+        self
+    }
+
     fn takes_hints(&self) -> bool {
         !self.sess.target.target.options.is_like_osx
     }
@@ -119,7 +152,7 @@ fn takes_hints(&self) -> bool {
     fn hint_static(&mut self) {
         if !self.takes_hints() { return }
         if !self.hinted_static {
-            self.cmd.arg("-Wl,-Bstatic");
+            self.linker_arg("-Bstatic");
             self.hinted_static = true;
         }
     }
@@ -127,13 +160,13 @@ fn hint_static(&mut self) {
     fn hint_dynamic(&mut self) {
         if !self.takes_hints() { return }
         if self.hinted_static {
-            self.cmd.arg("-Wl,-Bdynamic");
+            self.linker_arg("-Bdynamic");
             self.hinted_static = false;
         }
     }
 }
 
-impl<'a> Linker for GnuLinker<'a> {
+impl<'a> Linker for GccLinker<'a> {
     fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); }
     fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); }
     fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
@@ -164,27 +197,26 @@ fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
         self.hint_static();
         let target = &self.sess.target.target;
         if !target.options.is_like_osx {
-            self.cmd.arg("-Wl,--whole-archive")
-                    .arg("-l").arg(lib)
-                    .arg("-Wl,--no-whole-archive");
+            self.linker_arg("--whole-archive").cmd.arg("-l").arg(lib);
+            self.linker_arg("--no-whole-archive");
         } else {
             // -force_load is the macOS equivalent of --whole-archive, but it
             // involves passing the full path to the library to link.
-            let mut v = OsString::from("-Wl,-force_load,");
+            let mut v = OsString::from("-force_load,");
             v.push(&archive::find_library(lib, search_path, &self.sess));
-            self.cmd.arg(&v);
+            self.linker_arg(&v);
         }
     }
 
     fn link_whole_rlib(&mut self, lib: &Path) {
         self.hint_static();
         if self.sess.target.target.options.is_like_osx {
-            let mut v = OsString::from("-Wl,-force_load,");
+            let mut v = OsString::from("-force_load,");
             v.push(lib);
-            self.cmd.arg(&v);
+            self.linker_arg(&v);
         } else {
-            self.cmd.arg("-Wl,--whole-archive").arg(lib)
-                    .arg("-Wl,--no-whole-archive");
+            self.linker_arg("--whole-archive").cmd.arg(lib);
+            self.linker_arg("--no-whole-archive");
         }
     }
 
@@ -204,10 +236,10 @@ fn gc_sections(&mut self, keep_metadata: bool) {
         // for partial linking when using multiple codegen units (-r).  So we
         // insert it here.
         if self.sess.target.target.options.is_like_osx {
-            self.cmd.arg("-Wl,-dead_strip");
+            self.linker_arg("-dead_strip");
         } else if self.sess.target.target.options.is_like_solaris {
-            self.cmd.arg("-Wl,-z");
-            self.cmd.arg("-Wl,ignore");
+            self.linker_arg("-z");
+            self.linker_arg("ignore");
 
         // If we're building a dylib, we don't use --gc-sections because LLVM
         // has already done the best it can do, and we also don't want to
@@ -215,7 +247,7 @@ fn gc_sections(&mut self, keep_metadata: bool) {
         // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
         // reduction.
         } else if !keep_metadata {
-            self.cmd.arg("-Wl,--gc-sections");
+            self.linker_arg("--gc-sections");
         }
     }
 
@@ -226,7 +258,7 @@ fn optimize(&mut self) {
         // need a numeric argument, but other linkers do.
         if self.sess.opts.optimize == config::OptLevel::Default ||
            self.sess.opts.optimize == config::OptLevel::Aggressive {
-            self.cmd.arg("-Wl,-O1");
+            self.linker_arg("-O1");
         }
     }
 
@@ -235,13 +267,16 @@ fn debuginfo(&mut self) {
     }
 
     fn no_default_libraries(&mut self) {
-        self.cmd.arg("-nodefaultlibs");
+        if !self.is_ld {
+            self.cmd.arg("-nodefaultlibs");
+        }
     }
 
     fn build_dylib(&mut self, out_filename: &Path) {
         // On mac we need to tell the linker to let this library be rpathed
         if self.sess.target.target.options.is_like_osx {
-            self.cmd.args(&["-dynamiclib", "-Wl,-dylib"]);
+            self.cmd.arg("-dynamiclib");
+            self.linker_arg("-dylib");
 
             // Note that the `osx_rpath_install_name` option here is a hack
             // purely to support rustbuild right now, we should get a more
@@ -249,9 +284,9 @@ fn build_dylib(&mut self, out_filename: &Path) {
             // the right `-Wl,-install_name` with an `@rpath` in it.
             if self.sess.opts.cg.rpath ||
                self.sess.opts.debugging_opts.osx_rpath_install_name {
-                let mut v = OsString::from("-Wl,-install_name,@rpath/");
+                let mut v = OsString::from("-install_name,@rpath/");
                 v.push(out_filename.file_name().unwrap());
-                self.cmd.arg(&v);
+                self.linker_arg(&v);
             }
         } else {
             self.cmd.arg("-shared");
@@ -307,11 +342,20 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
         }
 
         if self.sess.target.target.options.is_like_osx {
-            arg.push("-Wl,-exported_symbols_list,");
+            if !self.is_ld {
+                arg.push("-Wl,")
+            }
+            arg.push("-exported_symbols_list,");
         } else if self.sess.target.target.options.is_like_solaris {
-            arg.push("-Wl,-M,");
+            if !self.is_ld {
+                arg.push("-Wl,")
+            }
+            arg.push("-M,");
         } else {
-            arg.push("-Wl,--version-script=");
+            if !self.is_ld {
+                arg.push("-Wl,")
+            }
+            arg.push("--version-script=");
         }
 
         arg.push(&path);
@@ -319,7 +363,7 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
     }
 
     fn subsystem(&mut self, subsystem: &str) {
-        self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem));
+        self.linker_arg(&format!("--subsystem,{}", subsystem));
     }
 
     fn finalize(&mut self) -> Command {
index 5e7d612d17f82e21eb12904140b5b21cabaa9b36..7077eade61182af2387119e8dd0801d8e3b48062 100644 (file)
@@ -16,7 +16,7 @@
 use llvm::{ValueRef};
 use abi::{Abi, FnType};
 use adt;
-use mir::lvalue::LvalueRef;
+use mir::lvalue::{LvalueRef, Alignment};
 use base::*;
 use common::*;
 use declare;
@@ -36,8 +36,6 @@
 use std::cmp::Ordering;
 use std::iter;
 
-use mir::lvalue::Alignment;
-
 fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
     let llvm_name = match name {
         "sqrtf32" => "llvm.sqrt.f32",
@@ -188,7 +186,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             C_nil(ccx)
         }
         // Effectively no-ops
-        "uninit" | "forget" => {
+        "uninit" => {
             C_nil(ccx)
         }
         "needs_drop" => {
@@ -622,7 +620,10 @@ fn modify_as_needed<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
 
                     for i in 0..elems.len() {
                         let val = bcx.extract_value(val, i);
-                        bcx.store(val, bcx.struct_gep(llresult, i), None);
+                        let lval = LvalueRef::new_sized_ty(llresult, ret_ty,
+                                                           Alignment::AbiAligned);
+                        let (dest, align) = lval.trans_field_ptr(bcx, i);
+                        bcx.store(val, dest, align.to_align());
                     }
                     C_nil(ccx)
                 }
index c8d15d28708f4e3b9a8b926bc272afd174e9c778..f4c9a136ace3c9516e9857fb20651f1976455e3a 100644 (file)
@@ -386,7 +386,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
 
             let lvalue = LvalueRef::alloca(bcx, arg_ty, &format!("arg{}", arg_index));
             for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
-                let dst = bcx.struct_gep(lvalue.llval, i);
+                let (dst, _) = lvalue.trans_field_ptr(bcx, i);
                 let arg = &mircx.fn_ty.args[idx];
                 idx += 1;
                 if common::type_is_fat_ptr(bcx.ccx, tupled_arg_ty) {
index 2861fd288326b001f639e03bbf4fd7bb7f61a140..cd58fcd4806da62d104e61679c7a9527ae71bad6 100644 (file)
@@ -124,7 +124,6 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "rustc_peek" => (1, vec![param(0)], param(0)),
             "init" => (1, Vec::new(), param(0)),
             "uninit" => (1, Vec::new(), param(0)),
-            "forget" => (1, vec![ param(0) ], tcx.mk_nil()),
             "transmute" => (2, vec![ param(0) ], param(1)),
             "move_val_init" => {
                 (1,
index 1e687d63f58755d732d1e71878c4ca45262d90df..c59101cc779968eea9f7f7f3e772f3359ac6e401 100644 (file)
@@ -469,22 +469,28 @@ fn parse(string: &str) -> LangString {
         );
 
         for token in tokens {
-            match token {
+            match token.trim() {
                 "" => {},
-                "should_panic" => { data.should_panic = true; seen_rust_tags = true; },
-                "no_run" => { data.no_run = true; seen_rust_tags = true; },
-                "ignore" => { data.ignore = true; seen_rust_tags = true; },
-                "rust" => { data.rust = true; seen_rust_tags = true; },
-                "test_harness" => { data.test_harness = true; seen_rust_tags = true; },
+                "should_panic" => {
+                    data.should_panic = true;
+                    seen_rust_tags = seen_other_tags == false;
+                }
+                "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
+                "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
+                "rust" => { data.rust = true; seen_rust_tags = true; }
+                "test_harness" => {
+                    data.test_harness = true;
+                    seen_rust_tags = !seen_other_tags || seen_rust_tags;
+                }
                 "compile_fail" if allow_compile_fail => {
                     data.compile_fail = true;
-                    seen_rust_tags = true;
+                    seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     data.no_run = true;
                 }
                 x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => {
                     if let Ok(_) = x[1..].parse::<u32>() {
                         data.error_codes.push(x.to_owned());
-                        seen_rust_tags = true;
+                        seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     } else {
                         seen_other_tags = true;
                     }
@@ -670,9 +676,11 @@ fn t(s: &str,
         t("test_harness",          false,        false,  false,  true,  true,  false, Vec::new());
         t("compile_fail",          false,        true,   false,  true,  false, true,  Vec::new());
         t("{.no_run .example}",    false,        true,   false,  true,  false, false, Vec::new());
-        t("{.sh .should_panic}",   true,         false,  false,  true,  false, false, Vec::new());
+        t("{.sh .should_panic}",   true,         false,  false,  false, false, false, Vec::new());
         t("{.example .rust}",      false,        false,  false,  true,  false, false, Vec::new());
         t("{.test_harness .rust}", false,        false,  false,  true,  true,  false, Vec::new());
+        t("text, no_run",          false,        true,   false,  false, false, false, Vec::new());
+        t("text,no_run",           false,        true,   false,  false, false, false, Vec::new());
     }
 
     #[test]
index b36253862094f4acf1c6aff41f1c89dd23193edb..4e3781ecafab5b008c82c2c3d5562f6fd50bbb89 100644 (file)
@@ -27,7 +27,6 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use fmt;
-use mem;
 use ops::Range;
 use iter::FusedIterator;
 
@@ -599,12 +598,12 @@ fn eq_ignore_ascii_case(&self, other: &str) -> bool {
     }
 
     fn make_ascii_uppercase(&mut self) {
-        let me: &mut [u8] = unsafe { mem::transmute(self) };
+        let me = unsafe { self.as_bytes_mut() };
         me.make_ascii_uppercase()
     }
 
     fn make_ascii_lowercase(&mut self) {
-        let me: &mut [u8] = unsafe { mem::transmute(self) };
+        let me = unsafe { self.as_bytes_mut() };
         me.make_ascii_lowercase()
     }
 
index 064144dcd68183b82bddb06d086d38ee658af447..6299a9070ae03bd22bc9f1e34e50fe6d70887288 100644 (file)
 #![feature(stmt_expr_attributes)]
 #![feature(str_char)]
 #![feature(str_internals)]
+#![feature(str_mut_extras)]
 #![feature(str_utf16)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
index 5b2053e929a10317d645126fcbd16e163dd0cc10..052340a0f253a11cf43e257c5da563b62c7585f8 100644 (file)
@@ -277,7 +277,7 @@ mod prim_pointer { }
 /// Arrays of sizes from 0 to 32 (inclusive) implement the following traits if
 /// the element type allows it:
 ///
-/// - [`Clone`][clone] (only if `T: [Copy][copy]`)
+/// - [`Clone`][clone] (only if `T: `[`Copy`][copy])
 /// - [`Debug`][debug]
 /// - [`IntoIterator`][intoiterator] (implemented for `&[T; N]` and `&mut [T; N]`)
 /// - [`PartialEq`][partialeq], [`PartialOrd`][partialord], [`Eq`][eq], [`Ord`][ord]
index c68e2ae34687b347cc095ca3b6d7787ec3c265db..08762ccf04bde8d0dbaaf6a638402384cbe10262 100644 (file)
@@ -343,6 +343,9 @@ pub fn new() -> Features {
 
     // Used to preserve symbols (see llvm.used)
     (active, used, "1.18.0", Some(40289)),
+
+    // Hack to document `-Z linker-flavor` in The Unstable Book
+    (active, linker_flavor, "1.18.0", Some(41142)),
 );
 
 declare_features! (
index 43d21015a4fb14569ac0f1635ae18b218b1bc550..58be43526fd9d7e6da9ddc0572ec177c63ea482c 100644 (file)
@@ -592,8 +592,10 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
             } else {
                 label_sp
             };
-            err.span_label(sp, &label_exp);
-            if !sp.source_equal(&self.span) {
+            if self.span.contains(sp) {
+                err.span_label(self.span, &label_exp);
+            } else {
+                err.span_label(sp, &label_exp);
                 err.span_label(self.span, &"unexpected token");
             }
             Err(err)
index 9b88b9f7696fb3a35f68c5165d3f5ccc59ce610f..aaafcadc38a1468e8177fdc123a7c726f3483515 100644 (file)
@@ -89,7 +89,7 @@ pub fn end_point(self) -> Span {
     /// Returns a new span representing the next character after the end-point of this span
     pub fn next_point(self) -> Span {
         let lo = cmp::max(self.hi.0, self.lo.0 + 1);
-        Span { lo: BytePos(lo), hi: BytePos(lo + 1), ..self }
+        Span { lo: BytePos(lo), hi: BytePos(lo), ..self }
     }
 
     /// Returns `self` if `self` is not the dummy span, and `other` otherwise.
diff --git a/src/test/compile-fail/feature-gate-linker-flavor.rs b/src/test/compile-fail/feature-gate-linker-flavor.rs
new file mode 100644 (file)
index 0000000..955ec39
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This is a fake compile fail test as there's no way to generate a
+// `#![feature(linker_flavor)]` error. The only reason we have a `linker_flavor`
+// feature gate is to be able to document `-Z linker-flavor` in the unstable
+// book
+
+#[used]
+fn foo() {}
+//~^^ ERROR the `#[used]` attribute is an experimental feature
+
+fn main() {}
index 521f122f8af0b57eec342d14cadd72fee2904610..48c9fda31e8c80707674537252d6a2fe4306d0a9 100644 (file)
 
 #![feature(core_intrinsics)]
 
-use std::intrinsics::{init, forget};
+use std::intrinsics::{init};
 
 // Test that the `forget` and `init` intrinsics are really unsafe
 pub fn main() {
     let stuff = init::<isize>(); //~ ERROR call to unsafe function requires unsafe
-    forget(stuff);             //~ ERROR call to unsafe function requires unsafe
 }
diff --git a/src/test/compile-fail/impl-trait/equality.rs b/src/test/compile-fail/impl-trait/equality.rs
deleted file mode 100644 (file)
index 36df4f0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(conservative_impl_trait, specialization)]
-
-trait Foo: Copy + ToString {}
-
-impl<T: Copy + ToString> Foo for T {}
-
-fn hide<T: Foo>(x: T) -> impl Foo {
-    x
-}
-
-fn two(x: bool) -> impl Foo {
-    if x {
-        return 1_i32;
-    }
-    0_u32
-    //~^ ERROR mismatched types
-    //~| expected i32, found u32
-}
-
-fn sum_to(n: u32) -> impl Foo {
-    if n == 0 {
-        0
-    } else {
-        n + sum_to(n - 1)
-        //~^ ERROR the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
-    }
-}
-
-trait Leak: Sized {
-    type T;
-    fn leak(self) -> Self::T;
-}
-impl<T> Leak for T {
-    default type T = ();
-    default fn leak(self) -> Self::T { panic!() }
-}
-impl Leak for i32 {
-    type T = i32;
-    fn leak(self) -> i32 { self }
-}
-
-fn main() {
-    let _: u32 = hide(0_u32);
-    //~^ ERROR mismatched types
-    //~| expected type `u32`
-    //~| found type `impl Foo`
-    //~| expected u32, found anonymized type
-
-    let _: i32 = Leak::leak(hide(0_i32));
-    //~^ ERROR mismatched types
-    //~| expected type `i32`
-    //~| found type `<impl Foo as Leak>::T`
-    //~| expected i32, found associated type
-
-    let mut x = (hide(0_u32), hide(0_i32));
-    x = (x.1,
-    //~^ ERROR mismatched types
-    //~| expected u32, found i32
-         x.0);
-    //~^ ERROR mismatched types
-    //~| expected i32, found u32
-}
index b7083c2776aeccd3f5575be4e55c25dc7222d0f9..14515ad7f00b91f9c4c140b6e5e15351d25968d2 100644 (file)
@@ -1,5 +1,6 @@
 {
     "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128",
+    "linker-flavor": "gcc",
     "llvm-target": "i686-unknown-linux-gnu",
     "target-endian": "little",
     "target-pointer-width": "32",
index 053f2dd63358a9b9e832e5dbaaf7831e5752b445..74787b28d2233905382e8960af5b8ee003299867 100644 (file)
@@ -1,5 +1,6 @@
 {
     "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
+    "linker-flavor": "gcc",
     "target-endian": "little",
     "target-pointer-width": "32",
     "arch": "x86",
index 688bbe46bfaf0593b6df26e2a1035ee0952ee272..cfe152f9e8728c0a3fb294de11c324d4210b9895 100644 (file)
@@ -1,6 +1,7 @@
 {
     "pre-link-args": ["-m64"],
     "data-layout": "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128",
+    "linker-flavor": "gcc",
     "llvm-target": "x86_64-unknown-linux-gnu",
     "target-endian": "little",
     "target-pointer-width": "64",
diff --git a/src/test/run-pass/optimization-fuel-0.rs b/src/test/run-pass/optimization-fuel-0.rs
new file mode 100644 (file)
index 0000000..3832c04
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="foo"]
+
+use std::mem::size_of;
+
+// compile-flags: -Z fuel=foo=0
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+
+fn main() {
+    assert_eq!(size_of::<S1>(), 6);
+    assert_eq!(size_of::<S2>(), 6);
+}
+
diff --git a/src/test/run-pass/optimization-fuel-1.rs b/src/test/run-pass/optimization-fuel-1.rs
new file mode 100644 (file)
index 0000000..5f294e2
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="foo"]
+
+use std::mem::size_of;
+
+// compile-flags: -Z fuel=foo=1
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+
+fn main() {
+    let optimized = (size_of::<S1>() == 4) as usize
+        +(size_of::<S2>() == 4) as usize;
+    assert_eq!(optimized, 1);
+}
+
+
index bbb01eaaf46b9b43afbdbf4bdbf4c7ebfbf4aa61..2f50e63153ea4bf8722b3bec2458aaa40d6168be 100644 (file)
@@ -31,6 +31,17 @@ enum e3 {
     a([u16; 0], u8), b
 }
 
+struct ReorderedStruct {
+    a: u8,
+    b: u16,
+    c: u8
+}
+
+enum ReorderedEnum {
+    A(u8, u16, u8),
+    B(u8, u16, u8),
+}
+
 pub fn main() {
     assert_eq!(size_of::<u8>(), 1 as usize);
     assert_eq!(size_of::<u32>(), 4 as usize);
@@ -54,4 +65,6 @@ pub fn main() {
     assert_eq!(size_of::<e1>(), 8 as usize);
     assert_eq!(size_of::<e2>(), 8 as usize);
     assert_eq!(size_of::<e3>(), 4 as usize);
+    assert_eq!(size_of::<ReorderedStruct>(), 4);
+    assert_eq!(size_of::<ReorderedEnum>(), 6);
 }
diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs
new file mode 100644 (file)
index 0000000..96db53a
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(conservative_impl_trait, specialization)]
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+    x
+}
+
+fn two(x: bool) -> impl Foo {
+    if x {
+        return 1_i32;
+    }
+    0_u32
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
+
+fn sum_to(n: u32) -> impl Foo {
+    if n == 0 {
+        0
+    } else {
+        n + sum_to(n - 1)
+        //~^ ERROR no implementation for `u32 + impl Foo`
+    }
+}
+
+trait Leak: Sized {
+    type T;
+    fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+    default type T = ();
+    default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+    type T = i32;
+    fn leak(self) -> i32 { self }
+}
+
+fn main() {
+    let _: u32 = hide(0_u32);
+    //~^ ERROR mismatched types
+    //~| expected type `u32`
+    //~| found type `impl Foo`
+    //~| expected u32, found anonymized type
+
+    let _: i32 = Leak::leak(hide(0_i32));
+    //~^ ERROR mismatched types
+    //~| expected type `i32`
+    //~| found type `<impl Foo as Leak>::T`
+    //~| expected i32, found associated type
+
+    let mut x = (hide(0_u32), hide(0_i32));
+    x = (x.1,
+    //~^ ERROR mismatched types
+    //~| expected u32, found i32
+         x.0);
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
new file mode 100644 (file)
index 0000000..bd024d6
--- /dev/null
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+  --> $DIR/equality.rs:25:5
+   |
+25 |     0_u32
+   |     ^^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0277]: the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
+  --> $DIR/equality.rs:34:9
+   |
+34 |         n + sum_to(n - 1)
+   |         ^^^^^^^^^^^^^^^^^ the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
+   |
+   = note: no implementation for `u32 + impl Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/equality.rs:53:18
+   |
+53 |     let _: u32 = hide(0_u32);
+   |                  ^^^^^^^^^^^ expected u32, found anonymized type
+   |
+   = note: expected type `u32`
+              found type `impl Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/equality.rs:59:18
+   |
+59 |     let _: i32 = Leak::leak(hide(0_i32));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found associated type
+   |
+   = note: expected type `i32`
+              found type `<impl Foo as Leak>::T`
+
+error[E0308]: mismatched types
+  --> $DIR/equality.rs:66:10
+   |
+66 |     x = (x.1,
+   |          ^^^ expected u32, found i32
+   |
+   = note: expected type `impl Foo` (u32)
+              found type `impl Foo` (i32)
+
+error[E0308]: mismatched types
+  --> $DIR/equality.rs:69:10
+   |
+69 |          x.0);
+   |          ^^^ expected i32, found u32
+   |
+   = note: expected type `impl Foo` (i32)
+              found type `impl Foo` (u32)
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/mismatched_types/binops.rs b/src/test/ui/mismatched_types/binops.rs
new file mode 100644 (file)
index 0000000..98449e5
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    1 + Some(1);
+    2 as usize - Some(1);
+    3 * ();
+    4 / "";
+    5 < String::new();
+    6 == Ok(1);
+}
diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr
new file mode 100644 (file)
index 0000000..a0f7ff6
--- /dev/null
@@ -0,0 +1,58 @@
+error[E0277]: the trait bound `{integer}: std::ops::Add<std::option::Option<{integer}>>` is not satisfied
+  --> $DIR/binops.rs:12:5
+   |
+12 |     1 + Some(1);
+   |     ^^^^^^^^^^^ the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
+   |
+   = note: no implementation for `{integer} + std::option::Option<{integer}>`
+
+error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` is not satisfied
+  --> $DIR/binops.rs:13:5
+   |
+13 |     2 as usize - Some(1);
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
+   |
+   = note: no implementation for `usize - std::option::Option<{integer}>`
+
+error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied
+  --> $DIR/binops.rs:14:5
+   |
+14 |     3 * ();
+   |     ^^^^^^ the trait `std::ops::Mul<()>` is not implemented for `{integer}`
+   |
+   = note: no implementation for `{integer} * ()`
+
+error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
+  --> $DIR/binops.rs:15:5
+   |
+15 |     4 / "";
+   |     ^^^^^^ the trait `std::ops::Div<&str>` is not implemented for `{integer}`
+   |
+   = note: no implementation for `{integer} / &str`
+
+error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::string::String>` is not satisfied
+  --> $DIR/binops.rs:16:5
+   |
+16 |     5 < String::new();
+   |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
+   |
+   = note: can't compare `{integer}` with `std::string::String`
+
+error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd<std::string::String>` is not satisfied
+  --> $DIR/binops.rs:16:5
+   |
+16 |     5 < String::new();
+   |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
+   |
+   = note: can't compare `{integer}` with `std::string::String`
+
+error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not satisfied
+  --> $DIR/binops.rs:17:5
+   |
+17 |     6 == Ok(1);
+   |     ^^^^^^^^^^ the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
+   |
+   = note: can't compare `{integer}` with `std::result::Result<{integer}, _>`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/print-fuel/print-fuel.rs b/src/test/ui/print-fuel/print-fuel.rs
new file mode 100644 (file)
index 0000000..0d9e243
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="foo"]
+#![allow(dead_code)]
+
+// compile-flags: -Z print-fuel=foo
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+struct S3(u8, u16, u8);
+
+fn main() {
+}
diff --git a/src/test/ui/print-fuel/print-fuel.stdout b/src/test/ui/print-fuel/print-fuel.stdout
new file mode 100644 (file)
index 0000000..cc88cc0
--- /dev/null
@@ -0,0 +1 @@
+Fuel used by foo: 3
index dd999c4a5e4c779d1e30f105926d4a4ef4e07eda..830678f174f88cf38e0d76836bac2cc7c9a9ee96 100644 (file)
@@ -1,25 +1,22 @@
-print-type-size type: `IndirectNonZero<u32>`: 20 bytes, alignment: 4 bytes
-print-type-size     field `.pre`: 1 bytes
-print-type-size     padding: 3 bytes
-print-type-size     field `.nested`: 12 bytes, alignment: 4 bytes
+print-type-size type: `IndirectNonZero<u32>`: 12 bytes, alignment: 4 bytes
+print-type-size     field `.nested`: 8 bytes
 print-type-size     field `.post`: 2 bytes
-print-type-size     end padding: 2 bytes
-print-type-size type: `MyOption<IndirectNonZero<u32>>`: 20 bytes, alignment: 4 bytes
-print-type-size     variant `Some`: 20 bytes
-print-type-size         field `.0`: 20 bytes
-print-type-size type: `EmbeddedDiscr`: 12 bytes, alignment: 4 bytes
-print-type-size     variant `Record`: 10 bytes
-print-type-size         field `.pre`: 1 bytes
-print-type-size         padding: 3 bytes
-print-type-size         field `.val`: 4 bytes, alignment: 4 bytes
-print-type-size         field `.post`: 2 bytes
-print-type-size     end padding: 2 bytes
-print-type-size type: `NestedNonZero<u32>`: 12 bytes, alignment: 4 bytes
 print-type-size     field `.pre`: 1 bytes
-print-type-size     padding: 3 bytes
-print-type-size     field `.val`: 4 bytes, alignment: 4 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
+print-type-size     variant `Some`: 12 bytes
+print-type-size         field `.0`: 12 bytes
+print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
+print-type-size     variant `Record`: 7 bytes
+print-type-size         field `.val`: 4 bytes
+print-type-size         field `.post`: 2 bytes
+print-type-size         field `.pre`: 1 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `NestedNonZero<u32>`: 8 bytes, alignment: 4 bytes
+print-type-size     field `.val`: 4 bytes
 print-type-size     field `.post`: 2 bytes
-print-type-size     end padding: 2 bytes
+print-type-size     field `.pre`: 1 bytes
+print-type-size     end padding: 1 bytes
 print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
index 1278a7d7c92c67836d9e74db7eefd791ef4b3b23..83fd333c9c7fc45dba547de22add55c477521ef9 100644 (file)
@@ -1,13 +1,11 @@
-print-type-size type: `Padded`: 16 bytes, alignment: 4 bytes
+print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.h`: 2 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
-print-type-size     padding: 2 bytes
-print-type-size     field `.g`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.c`: 1 bytes
-print-type-size     padding: 1 bytes
-print-type-size     field `.h`: 2 bytes, alignment: 2 bytes
 print-type-size     field `.d`: 1 bytes
-print-type-size     end padding: 3 bytes
+print-type-size     end padding: 2 bytes
 print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
index bb95f790bd9e471bdd740e5f9817faf8af8d4f54..0eaff7118b35c38a528dab7052d2cd498acb15aa 100644 (file)
@@ -1,10 +1,12 @@
 print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
-print-type-size     discriminant: 4 bytes
-print-type-size     variant `A`: 5 bytes
-print-type-size         field `.0`: 4 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 7 bytes
 print-type-size         field `.1`: 1 bytes
-print-type-size     variant `B`: 8 bytes
-print-type-size         field `.0`: 8 bytes
+print-type-size         padding: 2 bytes
+print-type-size         field `.0`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `B`: 11 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
 print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `A`: 7 bytes
@@ -15,7 +17,7 @@ print-type-size     variant `B`: 11 bytes
 print-type-size         padding: 3 bytes
 print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
 print-type-size type: `S`: 8 bytes, alignment: 4 bytes
+print-type-size     field `.g`: 4 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
-print-type-size     padding: 2 bytes
-print-type-size     field `.g`: 4 bytes, alignment: 4 bytes
+print-type-size     end padding: 2 bytes
index 85c11c05b9f9004c55a54d303433e11de586340b..161b6ca48b282444edf6150f4d847eb7df3903a6 100644 (file)
@@ -9,11 +9,7 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied
 27 | |             y),
    | |______________^ ...ending here: the trait `std::ops::Add<()>` is not implemented for `u32`
    |
-   = help: the following implementations were found:
-             <u32 as std::ops::Add>
-             <&'a u32 as std::ops::Add<u32>>
-             <u32 as std::ops::Add<&'a u32>>
-             <&'b u32 as std::ops::Add<&'a u32>>
+   = note: no implementation for `u32 + ()`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/token/issue-41155.rs b/src/test/ui/token/issue-41155.rs
new file mode 100644 (file)
index 0000000..0f473c9
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+impl S {
+    pub
+}
diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr
new file mode 100644 (file)
index 0000000..0da3abd
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected one of `(`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}`
+  --> $DIR/issue-41155.rs:13:1
+   |
+12 |     pub
+   |        - expected one of 7 possible tokens here
+13 | }
+   | ^ unexpected token
+
+error: aborting due to previous error
+
index adddd7b7e89b047030eeb63a0b32cb2aa18c017d..a7a43e6858ef9dd267695177cafb36a21d8ea1f9 100644 (file)
@@ -11,7 +11,7 @@
 extern crate toml;
 extern crate rustc_serialize;
 
-use std::collections::{BTreeMap, HashMap};
+use std::collections::BTreeMap;
 use std::env;
 use std::fs::File;
 use std::io::{self, Read, Write};
 struct Manifest {
     manifest_version: String,
     date: String,
-    pkg: HashMap<String, Package>,
+    pkg: BTreeMap<String, Package>,
 }
 
 #[derive(RustcEncodable)]
 struct Package {
     version: String,
-    target: HashMap<String, Target>,
+    target: BTreeMap<String, Target>,
 }
 
 #[derive(RustcEncodable)]
@@ -138,7 +138,7 @@ struct Builder {
     input: PathBuf,
     output: PathBuf,
     gpg_passphrase: String,
-    digests: HashMap<String, String>,
+    digests: BTreeMap<String, String>,
     s3_address: String,
     date: String,
     rust_version: String,
@@ -162,7 +162,7 @@ fn main() {
         input: input,
         output: output,
         gpg_passphrase: passphrase,
-        digests: HashMap::new(),
+        digests: BTreeMap::new(),
         s3_address: s3_address,
         date: date,
         rust_version: String::new(),
@@ -214,7 +214,7 @@ fn build_manifest(&mut self) -> Manifest {
         let mut manifest = Manifest {
             manifest_version: "2".to_string(),
             date: self.date.to_string(),
-            pkg: HashMap::new(),
+            pkg: BTreeMap::new(),
         };
 
         self.package("rustc", &mut manifest.pkg, HOSTS);
@@ -230,7 +230,7 @@ fn build_manifest(&mut self) -> Manifest {
 
         let mut pkg = Package {
             version: self.cached_version("rust").to_string(),
-            target: HashMap::new(),
+            target: BTreeMap::new(),
         };
         for host in HOSTS {
             let filename = self.filename("rust", host);
@@ -299,7 +299,7 @@ fn build_manifest(&mut self) -> Manifest {
 
     fn package(&mut self,
                pkgname: &str,
-               dst: &mut HashMap<String, Package>,
+               dst: &mut BTreeMap<String, Package>,
                targets: &[&str]) {
         let targets = targets.iter().map(|name| {
             let filename = self.filename(pkgname, name);