diff --git a/RELEASES.md b/RELEASES.md index 48bd13105bbea..4185961187b39 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,10 +1,108 @@ +Version 1.35.0 (2019-05-23) +========================== + +Language +-------- +- [`FnOnce`, `FnMut`, and the `Fn` traits are now implemented for `Box`, + `Box`, and `Box` respectively.][59500] +- [You can now coerce closures into unsafe function pointers.][59580] e.g. + ```rust + unsafe fn call_unsafe(func: unsafe fn()) { + func() + } + + pub fn main() { + unsafe { call_unsafe(|| {}); } + } + ``` + + +Compiler +-------- +- [Added the `armv6-unknown-freebsd-gnueabihf` and + `armv7-unknown-freebsd-gnueabihf` targets.][58080] +- [Added the `wasm32-unknown-wasi` target.][59464] + + +Libraries +--------- +- [`Thread` will now show its ID in `Debug` output.][59460] +- [`StdinLock`, `StdoutLock`, and `StderrLock` now implement `AsRawFd`.][59512] +- [`alloc::System` now implements `Default`.][59451] +- [Expanded `Debug` output (`{:#?}`) for structs now has a trailing comma on the + last field.][59076] +- [`char::{ToLowercase, ToUppercase}` now + implement `ExactSizeIterator`.][58778] +- [All `NonZero` numeric types now implement `FromStr`.][58717] +- [Removed the `Read` trait bounds + on the `BufReader::{get_ref, get_mut, into_inner}` methods.][58423] +- [You can now call the `dbg!` macro without any parameters to print the file + and line where it is called.][57847] +- [In place ASCII case conversions are now up to 4× faster.][59283] + e.g. `str::make_ascii_lowercase` +- [`hash_map::{OccupiedEntry, VacantEntry}` now implement `Sync` + and `Send`.][58369] + +Stabilized APIs +--------------- +- [`f32::copysign`] +- [`f64::copysign`] +- [`RefCell::replace_with`] +- [`RefCell::map_split`] +- [`ptr::hash`] +- [`Range::contains`] +- [`RangeFrom::contains`] +- [`RangeTo::contains`] +- [`RangeInclusive::contains`] +- [`RangeToInclusive::contains`] +- [`Option::copied`] + +Cargo +----- +- [You can now set `cargo:rustc-cdylib-link-arg` at build time to pass custom + linker arguments when building a `cdylib`.][cargo/6298] Its usage is highly + platform specific. + +Misc +---- +- [The Rust toolchain is now available natively for musl based distros.][58575] + +[59460]: https://github.com/rust-lang/rust/pull/59460/ +[59464]: https://github.com/rust-lang/rust/pull/59464/ +[59500]: https://github.com/rust-lang/rust/pull/59500/ +[59512]: https://github.com/rust-lang/rust/pull/59512/ +[59580]: https://github.com/rust-lang/rust/pull/59580/ +[59283]: https://github.com/rust-lang/rust/pull/59283/ +[59451]: https://github.com/rust-lang/rust/pull/59451/ +[59076]: https://github.com/rust-lang/rust/pull/59076/ +[58778]: https://github.com/rust-lang/rust/pull/58778/ +[58717]: https://github.com/rust-lang/rust/pull/58717/ +[58369]: https://github.com/rust-lang/rust/pull/58369/ +[58423]: https://github.com/rust-lang/rust/pull/58423/ +[58080]: https://github.com/rust-lang/rust/pull/58080/ +[57847]: https://github.com/rust-lang/rust/pull/57847/ +[58575]: https://github.com/rust-lang/rust/pull/58575 +[cargo/6298]: https://github.com/rust-lang/cargo/pull/6298/ +[`f32::copysign`]: https://doc.rust-lang.org/stable/std/primitive.f32.html#method.copysign +[`f64::copysign`]: https://doc.rust-lang.org/stable/std/primitive.f64.html#method.copysign +[`RefCell::replace_with`]: https://doc.rust-lang.org/stable/std/cell/struct.RefCell.html#method.replace_with +[`RefCell::map_split`]: https://doc.rust-lang.org/stable/std/cell/struct.RefCell.html#method.map_split +[`ptr::hash`]: https://doc.rust-lang.org/stable/std/ptr/fn.hash.html +[`Range::contains`]: https://doc.rust-lang.org/std/ops/struct.Range.html#method.contains +[`RangeFrom::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeFrom.html#method.contains +[`RangeTo::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeTo.html#method.contains +[`RangeInclusive::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html#method.contains +[`RangeToInclusive::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeToInclusive.html#method.contains +[`Option::copied`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.copied + Version 1.34.2 (2019-05-14) =========================== * [Destabilize the `Error::type_id` function due to a security - vulnerability][60785] + vulnerability][60785] ([CVE-2019-12083]) [60785]: https://github.com/rust-lang/rust/pull/60785 +[CVE-2019-12083]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12083 Version 1.34.1 (2019-04-25) =========================== diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md index 61e5b3d0133ff..b165c5a6b3b93 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/the-doc-attribute.md @@ -92,6 +92,21 @@ the tracking issue. #![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] ``` +### `html_root_url` + +The `#[doc(html_root_url = "…")]` attribute value indicates the URL for +generating links to external crates. When rustdoc needs to generate a link to +an item in an external crate, it will first check if the extern crate has been +documented locally on-disk, and if so link directly to it. Failing that, it +will use the URL given by the `--extern-html-root-url` command-line flag if +available. If that is not available, then it will use the `html_root_url` +value in the extern crate if it is available. If that is not available, then +the extern items will not be linked. + +```rust,ignore +#![doc(html_root_url = "https://docs.rs/serde/1.0")] +``` + ### `html_no_source` By default, `rustdoc` will include the source code of your program, with links diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md index 54472e35b1b2c..bbcacb7f3d5d9 100644 --- a/src/doc/rustdoc/src/what-is-rustdoc.md +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -98,21 +98,21 @@ documentation for them as well! `rustdoc` can also generate HTML from standalone Markdown files. Let's give it a try: create a `README.md` file with these contents: -```text - # Docs +````text +# Docs - This is a project to test out `rustdoc`. +This is a project to test out `rustdoc`. - [Here is a link!](https://www.rust-lang.org) +[Here is a link!](https://www.rust-lang.org) - ## Subheading +## Subheading - ```rust - fn foo() -> i32 { - 1 + 1 - } - ``` +```rust +fn foo() -> i32 { + 1 + 1 +} ``` +```` And call `rustdoc` on it: diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 72af027820106..4e214c3c7253e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -3,15 +3,17 @@ use rustc::hir::def::DefKind; use rustc::mir::{ - Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local, + AggregateKind, Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem, SourceScope, SourceScopeLocalData, LocalDecl, Promoted, }; -use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; +use rustc::mir::visit::{ + Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, +}; use rustc::mir::interpret::{InterpError, Scalar, GlobalId, EvalResult}; use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; -use syntax::source_map::DUMMY_SP; +use syntax_pos::{Span, DUMMY_SP}; use rustc::ty::subst::InternalSubsts; use rustc_data_structures::indexed_vec::IndexVec; use rustc::ty::layout::{ @@ -19,7 +21,7 @@ use rustc::ty::layout::{ HasTyCtxt, TargetDataLayout, HasDataLayout, }; -use crate::interpret::{InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind}; +use crate::interpret::{self, InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind}; use crate::const_eval::{ CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx, }; @@ -497,6 +499,53 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { }, } } + + fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>, span: Span) -> Operand<'tcx> { + Operand::Constant(Box::new( + Constant { + span, + ty, + user_ty: None, + literal: self.tcx.mk_const(ty::Const::from_scalar( + scalar, + ty, + )) + } + )) + } + + fn replace_with_const(&self, rval: &mut Rvalue<'tcx>, value: Const<'tcx>, span: Span) { + self.ecx.validate_operand( + value, + vec![], + None, + true, + ).expect("value should already be a valid const"); + + if let interpret::Operand::Immediate(im) = *value { + match im { + interpret::Immediate::Scalar(ScalarMaybeUndef::Scalar(scalar)) => { + *rval = Rvalue::Use(self.operand_from_scalar(scalar, value.layout.ty, span)); + }, + Immediate::ScalarPair( + ScalarMaybeUndef::Scalar(one), + ScalarMaybeUndef::Scalar(two) + ) => { + let ty = &value.layout.ty.sty; + if let ty::Tuple(substs) = ty { + *rval = Rvalue::Aggregate( + Box::new(AggregateKind::Tuple), + vec![ + self.operand_from_scalar(one, substs[0].expect_ty(), span), + self.operand_from_scalar(two, substs[1].expect_ty(), span), + ], + ); + } + }, + _ => { } + } + } + } } fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -560,10 +609,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { } } -impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { +impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { fn visit_constant( &mut self, - constant: &Constant<'tcx>, + constant: &mut Constant<'tcx>, location: Location, ) { trace!("visit_constant: {:?}", constant); @@ -573,11 +622,11 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { fn visit_statement( &mut self, - statement: &Statement<'tcx>, + statement: &mut Statement<'tcx>, location: Location, ) { trace!("visit_statement: {:?}", statement); - if let StatementKind::Assign(ref place, ref rval) = statement.kind { + if let StatementKind::Assign(ref place, ref mut rval) = statement.kind { let place_ty: Ty<'tcx> = place .ty(&self.local_decls, self.tcx) .ty; @@ -589,6 +638,10 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { trace!("storing {:?} to {:?}", value, local); assert!(self.places[local].is_none()); self.places[local] = Some(value); + + if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { + self.replace_with_const(rval, value, statement.source_info.span); + } } } } @@ -599,7 +652,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { fn visit_terminator( &mut self, - terminator: &Terminator<'tcx>, + terminator: &mut Terminator<'tcx>, location: Location, ) { self.super_terminator(terminator, location); diff --git a/src/test/mir-opt/const_prop/array_index.rs b/src/test/mir-opt/const_prop/array_index.rs new file mode 100644 index 0000000000000..4b97af68ff08a --- /dev/null +++ b/src/test/mir-opt/const_prop/array_index.rs @@ -0,0 +1,33 @@ +fn main() { + let x: u32 = [0, 1, 2, 3][2]; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _2 = [const 0u32, const 1u32, const 2u32, const 3u32]; +// ... +// _3 = const 2usize; +// _4 = const 4usize; +// _5 = Lt(_3, _4); +// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; +// } +// bb1: { +// _1 = _2[_3]; +// ... +// return; +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _5 = const true; +// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; +// } +// bb1: { +// _1 = _2[_3]; +// ... +// return; +// } +// END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/const_prop/checked_add.rs b/src/test/mir-opt/const_prop/checked_add.rs new file mode 100644 index 0000000000000..0718316307c5e --- /dev/null +++ b/src/test/mir-opt/const_prop/checked_add.rs @@ -0,0 +1,21 @@ +// compile-flags: -C overflow-checks=on + +fn main() { + let x: u32 = 1 + 1; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _2 = CheckedAdd(const 1u32, const 1u32); +// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1; +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _2 = (const 2u32, const false); +// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1; +// } +// END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs new file mode 100644 index 0000000000000..97d3abdcc6cbf --- /dev/null +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -0,0 +1,34 @@ +#[inline(never)] +fn read(_: usize) { } + +fn main() { + const FOO: &i32 = &1; + let x = FOO as *const i32 as usize; + read(x); +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _3 = _4; +// _2 = move _3 as *const i32 (Misc); +// ... +// _1 = move _2 as usize (Misc); +// ... +// _6 = _1; +// _5 = const read(move _6) -> bb1; +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _3 = _4; +// _2 = move _3 as *const i32 (Misc); +// ... +// _1 = move _2 as usize (Misc); +// ... +// _6 = _1; +// _5 = const read(move _6) -> bb1; +// } +// END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs new file mode 100644 index 0000000000000..3435ca07f4cd8 --- /dev/null +++ b/src/test/mir-opt/const_prop/slice_len.rs @@ -0,0 +1,37 @@ +fn test() -> &'static [u32] { + &[1, 2] +} + +fn main() { + let x = test()[0]; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb1: { +// ... +// _3 = const 0usize; +// _4 = Len((*_2)); +// _5 = Lt(_3, _4); +// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2; +// } +// bb2: { +// _1 = (*_2)[_3]; +// ... +// return; +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _3 = const 0usize; +// _4 = Len((*_2)); +// _5 = Lt(_3, _4); +// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2; +// } +// bb2: { +// _1 = (*_2)[_3]; +// ... +// return; +// } +// END rustc.main.ConstProp.after.mir diff --git a/src/tools/clippy b/src/tools/clippy index ad3269c4b510b..11194e3d050f4 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit ad3269c4b510b94b7c0082f4bb341bee6ed1eca4 +Subproject commit 11194e3d050f45ff002a775f451ff6222fcd5b2c