diff --git a/RELEASES.md b/RELEASES.md index 503ce7ede0..56c70a64b8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -52,6 +52,16 @@ Stabilized APIs --------------- - [`Iterator::step_by`] - [`Path::ancestors`] +- [`SystemTime::UNIX_EPOCH`] +- [`alloc::GlobalAlloc`] +- [`alloc::Layout`] +- [`alloc::LayoutErr`] +- [`alloc::System`] +- [`alloc::alloc`] +- [`alloc::alloc_zeroed`] +- [`alloc::dealloc`] +- [`alloc::realloc`] +- [`alloc::handle_alloc_error`] - [`btree_map::Entry::or_default`] - [`fmt::Alignment`] - [`hash_map::Entry::or_default`] @@ -122,6 +132,16 @@ Compatibility Notes [cargo/5584]: https://github.com/rust-lang/cargo/pull/5584/ [`Iterator::step_by`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.step_by [`Path::ancestors`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.ancestors +[`SystemTime::UNIX_EPOCH`]: https://doc.rust-lang.org/std/time/struct.SystemTime.html#associatedconstant.UNIX_EPOCH +[`alloc::GlobalAlloc`]: https://doc.rust-lang.org/std/alloc/trait.GlobalAlloc.html +[`alloc::Layout`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html +[`alloc::LayoutErr`]: https://doc.rust-lang.org/std/alloc/struct.LayoutErr.html +[`alloc::System`]: https://doc.rust-lang.org/std/alloc/struct.System.html +[`alloc::alloc`]: https://doc.rust-lang.org/std/alloc/fn.alloc.html +[`alloc::alloc_zeroed`]: https://doc.rust-lang.org/std/alloc/fn.alloc_zeroed.html +[`alloc::dealloc`]: https://doc.rust-lang.org/std/alloc/fn.dealloc.html +[`alloc::realloc`]: https://doc.rust-lang.org/std/alloc/fn.realloc.html +[`alloc::handle_alloc_error`]: https://doc.rust-lang.org/std/alloc/fn.handle_alloc_error.html [`btree_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default [`fmt::Alignment`]: https://doc.rust-lang.org/std/fmt/enum.Alignment.html [`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default @@ -3162,7 +3182,7 @@ Stabilized APIs * [`UnixDatagram::shutdown`](http://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.shutdown) * RawFd impls for `UnixDatagram` * `{BTree,Hash}Map::values_mut` -* [`<[_]>::binary_search_by_key`](http://doc.rust-lang.org/beta/std/primitive.slice.html#method.binary_search_by_key) +* [`<[_]>::binary_search_by_key`](http://doc.rust-lang.org/std/primitive.slice.html#method.binary_search_by_key) Libraries --------- @@ -4080,7 +4100,7 @@ Compatibility Notes [1.6bh]: https://github.com/rust-lang/rust/pull/29811 [1.6c]: https://github.com/rust-lang/cargo/pull/2192 [1.6cc]: https://github.com/rust-lang/cargo/pull/2131 -[1.6co]: http://doc.rust-lang.org/beta/core/index.html +[1.6co]: http://doc.rust-lang.org/core/index.html [1.6dv]: https://github.com/rust-lang/rust/pull/30000 [1.6f]: https://github.com/rust-lang/rust/pull/29129 [1.6m]: https://github.com/rust-lang/rust/pull/29828 diff --git a/git-commit-hash b/git-commit-hash index 8e89520a36..7335fd74b2 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -0aaa819fea00a6bf2b1303b9eb47f142f099cf5a \ No newline at end of file +9634041f0e8c0f3191d2867311276f19d0a42564 \ No newline at end of file diff --git a/src/ci/run.sh b/src/ci/run.sh index 44db6b92c9..45ca302ff3 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -46,7 +46,7 @@ fi # # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # either automatically or manually. -export RUST_RELEASE_CHANNEL=beta +export RUST_RELEASE_CHANNEL=stable if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 67fd5da8c9..dbb6cbaf78 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1483,10 +1483,12 @@ fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec(f: F) -> Result> +/// Runs `f` in a suitable thread for running `rustc`; returns a `Result` with either the return +/// value of `f` or -- if a panic occurs -- the panic value. +/// +/// This version applies the given name to the thread. This is used by rustdoc to ensure consistent +/// doctest output across platforms and executions. +pub fn in_named_rustc_thread(name: String, f: F) -> Result> where F: FnOnce() -> R + Send + 'static, R: Send + 'static, { @@ -1530,7 +1532,7 @@ pub fn in_rustc_thread(f: F) -> Result> // The or condition is added from backward compatibility. if spawn_thread || env::var_os("RUST_MIN_STACK").is_some() { - let mut cfg = thread::Builder::new().name("rustc".to_string()); + let mut cfg = thread::Builder::new().name(name); // FIXME: Hacks on hacks. If the env is trying to override the stack size // then *don't* set it explicitly. @@ -1546,6 +1548,16 @@ pub fn in_rustc_thread(f: F) -> Result> } } +/// Runs `f` in a suitable thread for running `rustc`; returns a +/// `Result` with either the return value of `f` or -- if a panic +/// occurs -- the panic value. +pub fn in_rustc_thread(f: F) -> Result> + where F: FnOnce() -> R + Send + 'static, + R: Send + 'static, +{ + in_named_rustc_thread("rustc".to_string(), f) +} + /// Get a list of extra command-line flags provided by the user, as strings. /// /// This function is used during ICEs to show more information useful for diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 2dd22058d7..432d5466e1 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -165,18 +165,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { op, is_assign); - let lhs_needs = match is_assign { - IsAssign::Yes => Needs::MutPlace, - IsAssign::No => Needs::None + let lhs_ty = match is_assign { + IsAssign::No => { + // Find a suitable supertype of the LHS expression's type, by coercing to + // a type variable, to pass as the `Self` to the trait, avoiding invariant + // trait matching creating lifetime constraints that are too strict. + // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result + // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`. + let lhs_ty = self.check_expr_with_needs(lhs_expr, Needs::None); + let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)); + self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No) + } + IsAssign::Yes => { + // rust-lang/rust#52126: We have to use strict + // equivalence on the LHS of an assign-op like `+=`; + // overwritten or mutably-borrowed places cannot be + // coerced to a supertype. + self.check_expr_with_needs(lhs_expr, Needs::MutPlace) + } }; - // Find a suitable supertype of the LHS expression's type, by coercing to - // a type variable, to pass as the `Self` to the trait, avoiding invariant - // trait matching creating lifetime constraints that are too strict. - // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result - // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`. - let lhs_ty = self.check_expr_with_needs(lhs_expr, lhs_needs); - let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)); - let lhs_ty = self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No); let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty); // NB: As we have not yet type-checked the RHS, we don't have the diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e516192769..c40e1df027 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -214,7 +214,7 @@ pub fn run_core(search_paths: SearchPaths, } else { vec![] }, - lint_cap: Some(lint::Forbid), + lint_cap: Some(lint::Allow), cg, externs, target_triple: triple.unwrap_or(host_triple), diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 6086c5a47c..354729ff5e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -232,31 +232,35 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, ..config::basic_options().clone() }; - let (libdir, outdir) = driver::spawn_thread_pool(sessopts, |sessopts| { - // Shuffle around a few input and output handles here. We're going to pass - // an explicit handle into rustc to collect output messages, but we also - // want to catch the error message that rustc prints when it fails. - // - // We take our thread-local stderr (likely set by the test runner) and replace - // it with a sink that is also passed to rustc itself. When this function - // returns the output of the sink is copied onto the output of our own thread. - // - // The basic idea is to not use a default Handler for rustc, and then also - // not print things by default to the actual stderr. - struct Sink(Arc>>); - impl Write for Sink { - fn write(&mut self, data: &[u8]) -> io::Result { - Write::write(&mut *self.0.lock().unwrap(), data) - } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + // Shuffle around a few input and output handles here. We're going to pass + // an explicit handle into rustc to collect output messages, but we also + // want to catch the error message that rustc prints when it fails. + // + // We take our thread-local stderr (likely set by the test runner) and replace + // it with a sink that is also passed to rustc itself. When this function + // returns the output of the sink is copied onto the output of our own thread. + // + // The basic idea is to not use a default Handler for rustc, and then also + // not print things by default to the actual stderr. + struct Sink(Arc>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) } - struct Bomb(Arc>>, Box); - impl Drop for Bomb { - fn drop(&mut self) { - let _ = self.1.write_all(&self.0.lock().unwrap()); - } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + struct Bomb(Arc>>, Box); + impl Drop for Bomb { + fn drop(&mut self) { + let _ = self.1.write_all(&self.0.lock().unwrap()); } - let data = Arc::new(Mutex::new(Vec::new())); + } + let data = Arc::new(Mutex::new(Vec::new())); + + let old = io::set_panic(Some(box Sink(data.clone()))); + let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout())); + + let (libdir, outdir, compile_result) = driver::spawn_thread_pool(sessopts, |sessopts| { let codemap = Lrc::new(CodeMap::new_doctest( sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize )); @@ -264,8 +268,6 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, Some(codemap.clone()), false, false); - let old = io::set_panic(Some(box Sink(data.clone()))); - let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout())); // Compile the code let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter); @@ -310,29 +312,29 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(()) }; - match (compile_result, compile_fail) { - (Ok(()), true) => { - panic!("test compiled while it wasn't supposed to") - } - (Ok(()), false) => {} - (Err(()), true) => { - if error_codes.len() > 0 { - let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); - error_codes.retain(|err| !out.contains(err)); - } - } - (Err(()), false) => { - panic!("couldn't compile the test") - } - } - - if error_codes.len() > 0 { - panic!("Some expected error codes were not found: {:?}", error_codes); - } - - (libdir, outdir) + (libdir, outdir, compile_result) }); + match (compile_result, compile_fail) { + (Ok(()), true) => { + panic!("test compiled while it wasn't supposed to") + } + (Ok(()), false) => {} + (Err(()), true) => { + if error_codes.len() > 0 { + let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); + error_codes.retain(|err| !out.contains(err)); + } + } + (Err(()), false) => { + panic!("couldn't compile the test") + } + } + + if error_codes.len() > 0 { + panic!("Some expected error codes were not found: {:?}", error_codes); + } + if no_run { return } // Run the code! @@ -546,7 +548,7 @@ impl Collector { debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { - name: testing::DynTestName(name), + name: testing::DynTestName(name.clone()), ignore: should_ignore, // compiler failures are test failures should_panic: testing::ShouldPanic::No, @@ -556,7 +558,7 @@ impl Collector { let panic = io::set_panic(None); let print = io::set_print(None); match { - rustc_driver::in_rustc_thread(move || with_globals(move || { + rustc_driver::in_named_rustc_thread(name, move || with_globals(move || { io::set_panic(panic); io::set_print(print); run_test(&test, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a6061e96ae..98ecd4f833 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -331,9 +331,7 @@ // `force_alloc_system` is *only* intended as a workaround for local rebuilds // with a rustc without jemalloc. // FIXME(#44236) shouldn't need MSVC logic -#![cfg_attr(all(not(target_env = "msvc"), - any(all(stage0, not(test)), feature = "force_alloc_system")), - feature(global_allocator))] +#![cfg_attr(all(not(target_env = "msvc"), stage0, not(test)), feature(global_allocator))] #[cfg(all(not(target_env = "msvc"), any(all(stage0, not(test)), feature = "force_alloc_system")))] #[global_allocator] diff --git a/src/stage0.txt b/src/stage0.txt index 10478bd74d..731076312c 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,8 +12,8 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2018-06-21 -rustc: 1.27.0 +date: 2018-07-20 +rustc: 1.27.2 cargo: 0.28.0 # When making a stable release the process currently looks like: diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs index 85d19c8354..1df5a63a27 100644 --- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs +++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-test + #![deny(intra_doc_link_resolution_failure)] /// [v2] //~ ERROR diff --git a/src/test/rustdoc-ui/failed-doctest-output.rs b/src/test/rustdoc-ui/failed-doctest-output.rs new file mode 100644 index 0000000000..62e495288c --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-output.rs @@ -0,0 +1,29 @@ +// Copyright 2013-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #51162: A failed doctest was not printing its stdout/stderr +// FIXME: if/when the output of the test harness can be tested on its own, this test should be +// adapted to use that, and that normalize line can go away + +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// failure-status: 101 + +// doctest fails at runtime +/// ``` +/// panic!("oh no"); +/// ``` +pub struct SomeStruct; + +// doctest fails at compile time +/// ``` +/// no +/// ``` +pub struct OtherStruct; diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout new file mode 100644 index 0000000000..62f5f2566a --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -0,0 +1,32 @@ + +running 2 tests +test $DIR/failed-doctest-output.rs - OtherStruct (line 26) ... FAILED +test $DIR/failed-doctest-output.rs - SomeStruct (line 20) ... FAILED + +failures: + +---- $DIR/failed-doctest-output.rs - OtherStruct (line 26) stdout ---- +error[E0425]: cannot find value `no` in this scope + --> $DIR/failed-doctest-output.rs:27:1 + | +3 | no + | ^^ not found in this scope + +thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:330:13 +note: Run with `RUST_BACKTRACE=1` for a backtrace. + +---- $DIR/failed-doctest-output.rs - SomeStruct (line 20) stdout ---- +thread '$DIR/failed-doctest-output.rs - SomeStruct (line 20)' panicked at 'test executable failed: + +thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1 +note: Run with `RUST_BACKTRACE=1` for a backtrace. + +', librustdoc/test.rs:365:17 + + +failures: + $DIR/failed-doctest-output.rs - OtherStruct (line 26) + $DIR/failed-doctest-output.rs - SomeStruct (line 20) + +test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out + diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs index d6bc275b57..c99746eaf5 100644 --- a/src/test/rustdoc-ui/intra-links-warning.rs +++ b/src/test/rustdoc-ui/intra-links-warning.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-test + // compile-pass //! Test with [Foo::baz], [Bar::foo], ... diff --git a/src/test/ui/issue-52126-assign-op-invariance.nll.stderr b/src/test/ui/issue-52126-assign-op-invariance.nll.stderr new file mode 100644 index 0000000000..dcca491a87 --- /dev/null +++ b/src/test/ui/issue-52126-assign-op-invariance.nll.stderr @@ -0,0 +1,15 @@ +error[E0597]: `line` does not live long enough + --> $DIR/issue-52126-assign-op-invariance.rs:44:28 + | +LL | let v: Vec<&str> = line.split_whitespace().collect(); + | ^^^^ borrowed value does not live long enough +LL | //~^ ERROR `line` does not live long enough +LL | println!("accumulator before add_assign {:?}", acc.map); + | ------- borrow later used here +... +LL | } + | - borrowed value only lives until here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-52126-assign-op-invariance.rs b/src/test/ui/issue-52126-assign-op-invariance.rs new file mode 100644 index 0000000000..b26ad9bc37 --- /dev/null +++ b/src/test/ui/issue-52126-assign-op-invariance.rs @@ -0,0 +1,59 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 52126: With respect to variance, the assign-op's like += were +// accidentally lumped together with other binary op's. In both cases +// we were coercing the LHS of the op to the expected supertype. +// +// The problem is that since the LHS of += is modified, we need the +// parameter to be invariant with respect to the overall type, not +// covariant. + +use std::collections::HashMap; +use std::ops::AddAssign; + +pub fn main() { + panics(); +} + +pub struct Counter<'l> { + map: HashMap<&'l str, usize>, +} + +impl<'l> AddAssign for Counter<'l> +{ + fn add_assign(&mut self, rhs: Counter<'l>) { + rhs.map.into_iter().for_each(|(key, val)| { + let count = self.map.entry(key).or_insert(0); + *count += val; + }); + } +} + +/// often times crashes, if not prints invalid strings +pub fn panics() { + let mut acc = Counter{map: HashMap::new()}; + for line in vec!["123456789".to_string(), "12345678".to_string()] { + let v: Vec<&str> = line.split_whitespace().collect(); + //~^ ERROR `line` does not live long enough + println!("accumulator before add_assign {:?}", acc.map); + let mut map = HashMap::new(); + for str_ref in v { + let e = map.entry(str_ref); + println!("entry: {:?}", e); + let count = e.or_insert(0); + *count += 1; + } + let cnt2 = Counter{map}; + acc += cnt2; + println!("accumulator after add_assign {:?}", acc.map); + // line gets dropped here but references are kept in acc.map + } +} diff --git a/src/test/ui/issue-52126-assign-op-invariance.stderr b/src/test/ui/issue-52126-assign-op-invariance.stderr new file mode 100644 index 0000000000..a4ea8085c1 --- /dev/null +++ b/src/test/ui/issue-52126-assign-op-invariance.stderr @@ -0,0 +1,14 @@ +error[E0597]: `line` does not live long enough + --> $DIR/issue-52126-assign-op-invariance.rs:44:28 + | +LL | let v: Vec<&str> = line.split_whitespace().collect(); + | ^^^^ borrowed value does not live long enough +... +LL | } + | - `line` dropped here while still borrowed +LL | } + | - borrowed value needs to live until here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/constant.rs b/src/test/ui/nll/constant.rs index 10ce0652d4..6e2c0ae7bb 100644 --- a/src/test/ui/nll/constant.rs +++ b/src/test/ui/nll/constant.rs @@ -11,7 +11,7 @@ // Test that MIR borrowck and NLL analysis can handle constants of // arbitrary types without ICEs. -// compile-flags:-Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir // compile-pass const HI: &str = "hi"; diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index f66f5c5b70..ea06e87077 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -15,7 +15,7 @@ use std::io::BufReader; use std::path::{Path, PathBuf}; use common; -use common::Config; +use common::{Config, Mode}; use util; use extract_gdb_version; @@ -396,6 +396,13 @@ impl TestProps { } }); + if self.failure_status == -1 { + self.failure_status = match config.mode { + Mode::RunFail => 101, + _ => 1, + }; + } + for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { if let Ok(val) = env::var(key) { if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() { diff --git a/version b/version index 927e52fbc7..7a525f1deb 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.28.0-beta.14 (0aaa819fe 2018-07-24) \ No newline at end of file +1.28.0 (9634041f0 2018-07-30) \ No newline at end of file