From cfcc5c296ed6fabcc8b9d380eaaea8a7352299fd Mon Sep 17 00:00:00 2001 From: Erin Power Date: Sun, 8 Sep 2019 13:52:29 +0200 Subject: [PATCH 01/11] Updated RELEASES.md for 1.38.0 --- RELEASES.md | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index f26f6e6c888ed..d634feba33ac5 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,108 @@ +Version 1.38.0 (2019-09-26) +========================== + +Language +-------- +- [The `#[global_allocator]` attribute can now be used in submodules.][62735] +- [The `#[deprecated]` attribute can now be used on macros.][62042] + +Compiler +-------- +- [Added pipelined compilation support to `rustc`.][62766] This will + improve compilation times in some cases. For further information please refer + to the [_"Evaluating pipelined rustc compilation"_][pipeline-internals] thread. +- [Added tier 3\* support for the `aarch64-uwp-windows-msvc`, `i686-uwp-windows-gnu`, + `i686-uwp-windows-msvc`, `x86_64-uwp-windows-gnu`, and + `x86_64-uwp-windows-msvc` targets.][60260] +- [Added tier 3 support for the `armv7-unknown-linux-gnueabi` and + `armv7-unknown-linux-musleabi` targets.][63107] +- [Added tier 3 support for the `hexagon-unknown-linux-musl` target.][62814] +- [Added tier 3 support for the `riscv32i-unknown-none-elf` target.][62784] + +\* Refer to Rust's [platform support page][forge-platform-support] for more +information on Rust's tiered platform support. + +Libraries +--------- +- [`ascii::EscapeDefault` now implements `Clone` and `Display`.][63421] +- [Derive macros for prelude traits (e.g. `Clone`, `Debug`, `Hash`) are now + available at the same path as the trait.][63056] (e.g. The `Clone` derive macro + is available at `std::clone::Clone`). This also makes all built-in macros + available in `std`/`core` root. e.g. `std::include_bytes!`. +- [`str::Chars` now implements `Debug`.][63000] +- [`slice::{concat, connect, join}` now accepts `&[T]` in addition to `&T`.][62528] +- [`*const T` and `*mut T` now implement `marker::Unpin`.][62583] +- [`Arc<[T]>` and `Rc<[T]>` now implement `FromIterator`.][61953] +- [Added euclidean remainder and division operations (`div_euclid`, + `rem_euclid`) to all numeric primitives.][61884] Additionally `checked`, + `overflowing`, and `wrapping` versions are available for all + integer primitives. +- [`thread::AccessError` now implements `Clone`, `Copy`, `Eq`, `Error`, and + `PartialEq`.][61491] +- [`iter::{StepBy, Peekable, Take}` now implement `DoubleEndedIterator`.][61457] + +Stabilized APIs +--------------- +- [`<*const T>::cast`] +- [`<*mut T>::cast`] +- [`Duration::as_secs_f32`] +- [`Duration::as_secs_f64`] +- [`Duration::div_duration_f32`] +- [`Duration::div_duration_f64`] +- [`Duration::div_f32`] +- [`Duration::div_f64`] +- [`Duration::from_secs_f32`] +- [`Duration::from_secs_f64`] +- [`Duration::mul_f32`] +- [`Duration::mul_f64`] +- [`any::type_name`] + +Cargo +----- +- [Added pipelined compilation support to `cargo`.][cargo/7143] +- [You can now pass the `--features` option multiple times to enable + multiple features.][cargo/7084] + +Misc +---- +- [`rustc` will now warn about some incorrect uses of + `mem::{uninitialized, zeroed}` that are known to cause undefined behaviour.][63346] + +[60260]: https://github.com/rust-lang/rust/pull/60260/ +[61457]: https://github.com/rust-lang/rust/pull/61457/ +[61491]: https://github.com/rust-lang/rust/pull/61491/ +[61884]: https://github.com/rust-lang/rust/pull/61884/ +[61953]: https://github.com/rust-lang/rust/pull/61953/ +[62042]: https://github.com/rust-lang/rust/pull/62042/ +[62528]: https://github.com/rust-lang/rust/pull/62528/ +[62583]: https://github.com/rust-lang/rust/pull/62583/ +[62735]: https://github.com/rust-lang/rust/pull/62735/ +[62766]: https://github.com/rust-lang/rust/pull/62766/ +[62784]: https://github.com/rust-lang/rust/pull/62784/ +[62814]: https://github.com/rust-lang/rust/pull/62814/ +[63000]: https://github.com/rust-lang/rust/pull/63000/ +[63056]: https://github.com/rust-lang/rust/pull/63056/ +[63107]: https://github.com/rust-lang/rust/pull/63107/ +[63346]: https://github.com/rust-lang/rust/pull/63346/ +[63421]: https://github.com/rust-lang/rust/pull/63421/ +[cargo/7084]: https://github.com/rust-lang/cargo/pull/7084/ +[cargo/7143]: https://github.com/rust-lang/cargo/pull/7143/ +[`<*const T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast +[`<*mut T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast +[`Duration::as_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f32 +[`Duration::as_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f64 +[`Duration::div_duration_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f32 +[`Duration::div_duration_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f64 +[`Duration::div_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f32 +[`Duration::div_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f64 +[`Duration::from_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f32 +[`Duration::from_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f64 +[`Duration::mul_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f32 +[`Duration::mul_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f64 +[`any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html +[forge-platform-support]: https://forge.rust-lang.org/platform-support.html +[pipeline-internals]: https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199 + Version 1.37.0 (2019-08-15) ========================== From 7f0637da5144c7435e88ea3805021882f077d50c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Sep 2019 13:29:32 +1000 Subject: [PATCH 02/11] Shrink `SubregionOrigin`. It's currently 120 bytes on x86-64, due to one oversized variant (`Subtype`). This commit boxes `Subtype`'s contents, reducing the size of `SubregionOrigin` to 32 bytes. The change speeds things up by avoiding lots of `memcpy` calls, mostly relating to `RegionConstraintData::constraints`, which is a `BTreeMap` with `SubregionOrigin` values. --- src/librustc/infer/equate.rs | 2 +- .../nice_region_error/placeholder_error.rs | 14 +++++++------- src/librustc/infer/error_reporting/note.rs | 4 ++-- src/librustc/infer/glb.rs | 2 +- src/librustc/infer/lub.rs | 2 +- src/librustc/infer/mod.rs | 6 +++++- src/librustc/infer/sub.rs | 2 +- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 5dfa0d29daf1b..96d40bc81add2 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -97,7 +97,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { self.tag(), a, b); - let origin = Subtype(self.fields.trace.clone()); + let origin = Subtype(box self.fields.trace.clone()); self.fields.infcx.borrow_region_constraints() .make_eqregion(origin, a, b); Ok(a) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index b4fb018920647..5f3c5fed3a3b2 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -30,7 +30,7 @@ impl NiceRegionError<'me, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -50,7 +50,7 @@ impl NiceRegionError<'me, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -70,7 +70,7 @@ impl NiceRegionError<'me, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -92,7 +92,7 @@ impl NiceRegionError<'me, 'tcx> { _, _, _, - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -108,7 +108,7 @@ impl NiceRegionError<'me, 'tcx> { )), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -125,7 +125,7 @@ impl NiceRegionError<'me, 'tcx> { )), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), @@ -142,7 +142,7 @@ impl NiceRegionError<'me, 'tcx> { )), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(TypeTrace { + SubregionOrigin::Subtype(box TypeTrace { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index caed4288892ef..115ffea97bf1a 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -138,7 +138,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { sup: Region<'tcx>) -> DiagnosticBuilder<'tcx> { match origin { - infer::Subtype(trace) => { + infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let mut err = self.report_and_explain_type_error(trace, &terr); self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "..."); @@ -450,7 +450,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> DiagnosticBuilder<'tcx> { // I can't think how to do better than this right now. -nikomatsakis match placeholder_origin { - infer::Subtype(trace) => { + infer::Subtype(box trace) => { let terr = TypeError::RegionsPlaceholderMismatch; self.report_and_explain_type_error(trace, &terr) } diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index 2cef521176269..10e45321a6d6a 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -57,7 +57,7 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { a, b); - let origin = Subtype(self.fields.trace.clone()); + let origin = Subtype(box self.fields.trace.clone()); Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b)) } diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index e20372f151371..8b64cda7bd26d 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -57,7 +57,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { a, b); - let origin = Subtype(self.fields.trace.clone()); + let origin = Subtype(box self.fields.trace.clone()); Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b)) } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 8638f42976f04..a886c44a4792d 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -254,7 +254,7 @@ pub struct TypeTrace<'tcx> { #[derive(Clone, Debug)] pub enum SubregionOrigin<'tcx> { /// Arose from a subtyping relation - Subtype(TypeTrace<'tcx>), + Subtype(Box>), /// Stack-allocated closures cannot outlive innermost loop /// or function so as to ensure we only require finite stack @@ -340,6 +340,10 @@ pub enum SubregionOrigin<'tcx> { }, } +// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(SubregionOrigin<'_>, 32); + /// Places that type/region parameters can appear. #[derive(Clone, Copy, Debug)] pub enum ParameterOrigin { diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index cd1d206b5fca1..76db55ecfa8ef 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -130,7 +130,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { // FIXME -- we have more fine-grained information available // from the "cause" field, we could perhaps give more tailored // error messages. - let origin = SubregionOrigin::Subtype(self.fields.trace.clone()); + let origin = SubregionOrigin::Subtype(box self.fields.trace.clone()); self.fields.infcx.borrow_region_constraints() .make_subregion(origin, a, b); From 62e86b42b5ed342d30c539e22810c26d312995e2 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 16 Sep 2019 20:02:36 +0800 Subject: [PATCH 03/11] Fix inconsistent link formatting --- src/libstd/io/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 0386dbd490d03..be364a10593da 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -2326,10 +2326,10 @@ impl Iterator for Bytes { /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// -/// This struct is generally created by calling [`split`][split] on a -/// `BufRead`. Please see the documentation of `split()` for more details. +/// This struct is generally created by calling [`split`] on a `BufRead`. +/// Please see the documentation of [`split`] for more details. /// -/// [split]: trait.BufRead.html#method.split +/// [`split`]: trait.BufRead.html#method.split #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Split { @@ -2358,10 +2358,10 @@ impl Iterator for Split { /// An iterator over the lines of an instance of `BufRead`. /// -/// This struct is generally created by calling [`lines`][lines] on a -/// `BufRead`. Please see the documentation of `lines()` for more details. +/// This struct is generally created by calling [`lines`] on a `BufRead`. +/// Please see the documentation of [`lines`] for more details. /// -/// [lines]: trait.BufRead.html#method.lines +/// [`lines`]: trait.BufRead.html#method.lines #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Lines { From 388cd5d88eb6cbb9a2440d0a05fa0ea7d0b24dd3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 16 Sep 2019 11:29:10 +0200 Subject: [PATCH 04/11] avoid duplicate issues for Miri build failures --- src/tools/publish_toolstate.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 4060b90d952bd..7cf3cc7663b47 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -201,7 +201,9 @@ def update_latest( new = s.get(tool, old) status[os] = new maintainers = ' '.join('@'+name for name in MAINTAINERS[tool]) - if new > old: # comparing the strings, but they are ordered appropriately! + # comparing the strings, but they are ordered appropriately: + # "test-pass" > "test-fail" > "build-fail" + if new > old: # things got fixed or at least the status quo improved changed = True message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \ @@ -213,10 +215,17 @@ def update_latest( .format(tool, os, old, new) message += '{} (cc {}, @rust-lang/infra).\n' \ .format(title, maintainers) - # Most tools only create issues for build failures. - # Other failures can be spurious. - if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'): - create_issue_for_status = new + # See if we need to create an issue. + if tool == 'miri': + # Create issue if tests used to pass before. Don't open a *second* + # issue when we regress from "test-fail" to "build-fail". + if old == 'test-pass': + create_issue_for_status = new + else: + # Create issue if things no longer build. + # (No issue for mere test failures to avoid spurious issues.) + if new == 'build-fail': + create_issue_for_status = new if create_issue_for_status is not None: try: From 02c1b892c1dfa6d0f00254f9c058ce7595921d61 Mon Sep 17 00:00:00 2001 From: Afnan Enayet Date: Fri, 13 Sep 2019 06:48:47 -0700 Subject: [PATCH 05/11] Fix failure note `to_str` implementation * Serialize the level to something a little more useful for a failure note struct * Update tests accordingly --- src/librustc_errors/emitter.rs | 15 +++++++++------ src/librustc_errors/lib.rs | 2 +- src/test/ui/json-short.stderr | 2 +- src/test/ui/lint/use_suggestion_json.stderr | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 0ce69eecc6b1e..5214806c6ea98 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1144,15 +1144,18 @@ impl EmitterWriter { buffer.prepend(0, " ", Style::NoStyle); } draw_note_separator(&mut buffer, 0, max_line_num_len + 1); - let level_str = level.to_string(); - if !level_str.is_empty() { - buffer.append(0, &level_str, Style::MainHeaderMsg); - buffer.append(0, ": ", Style::NoStyle); + if *level != Level::FailureNote { + let level_str = level.to_string(); + if !level_str.is_empty() { + buffer.append(0, &level_str, Style::MainHeaderMsg); + buffer.append(0, ": ", Style::NoStyle); + } } self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None); } else { let level_str = level.to_string(); - if !level_str.is_empty() { + // The failure note level itself does not provide any useful diagnostic information + if *level != Level::FailureNote && !level_str.is_empty() { buffer.append(0, &level_str, Style::Level(level.clone())); } // only render error codes, not lint codes @@ -1161,7 +1164,7 @@ impl EmitterWriter { buffer.append(0, &code, Style::Level(level.clone())); buffer.append(0, "]", Style::Level(level.clone())); } - if !level_str.is_empty() { + if *level != Level::FailureNote && !level_str.is_empty() { buffer.append(0, ": ", header_style); } for &(ref text, _) in msg.iter() { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index c1fba416d6433..8b543be6e6497 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -833,7 +833,7 @@ impl Level { Warning => "warning", Note => "note", Help => "help", - FailureNote => "", + FailureNote => "failure-note", Cancelled => panic!("Shouldn't call on cancelled error"), } } diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr index dffbdb7e4802d..549de0d27102e 100644 --- a/src/test/ui/json-short.stderr +++ b/src/test/ui/json-short.stderr @@ -15,5 +15,5 @@ started: https://doc.rust-lang.org/book/ "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error "} -{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`. +{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`. "} diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index c7c53abcf4406..678c88849b561 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -412,7 +412,7 @@ mod foo { { "message": "For more information about this error, try `rustc --explain E0412`.", "code": null, - "level": "", + "level": "failure-note", "spans": [], "children": [], "rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m From daafeb35b731a599fc8b6c4cf37b81f838dae319 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 17 Sep 2019 08:58:51 +0200 Subject: [PATCH 06/11] document Miri error categories --- src/librustc/mir/interpret/error.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 09c822f7508a0..2975944c7fba7 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -313,6 +313,9 @@ impl fmt::Debug for PanicInfo { } } +/// Error information for when the program we executed turned out not to actually be a valid +/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp +/// where we work on generic code or execution does not have all information available. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum InvalidProgramInfo<'tcx> { /// Resolution can fail if we are in a too generic context. @@ -342,6 +345,7 @@ impl fmt::Debug for InvalidProgramInfo<'tcx> { } } +/// Error information for when the program caused Undefined Behavior. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum UndefinedBehaviorInfo { /// Free-form case. Only for errors that are never caught! @@ -364,12 +368,19 @@ impl fmt::Debug for UndefinedBehaviorInfo { } } +/// Error information for when the program did something that might (or might not) be correct +/// to do according to the Rust spec, but due to limitations in the interpreter, the +/// operation could not be carried out. These limitations can differ between CTFE and the +/// Miri engine, e.g., CTFE does not support casting pointers to "real" integers. +/// +/// Currently, we also use this as fall-back error kind for errors that have not been +/// categorized yet. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsupportedOpInfo<'tcx> { /// Free-form case. Only for errors that are never caught! Unsupported(String), - // -- Everything below is not classified yet -- + // -- Everything below is not categorized yet -- FunctionAbiMismatch(Abi, Abi), FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>), @@ -536,6 +547,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { } } +/// Error information for when the program exhausted the resources granted to it +/// by the interpreter. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum ResourceExhaustionInfo { /// The stack grew too big. From 522f4e1f3e69a29ab3772df877f2e2e30f986256 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Tue, 17 Sep 2019 19:41:12 +0900 Subject: [PATCH 07/11] Add an example to Pin::as_mut --- src/libcore/pin.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index be59e830beda3..e8d63b8c3130b 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -584,6 +584,27 @@ impl Pin

{ /// the pointee cannot move after `Pin>` got created. /// "Malicious" implementations of `Pointer::DerefMut` are likewise /// ruled out by the contract of `Pin::new_unchecked`. + /// + /// This method is useful when doing multiple calls to functions that consume the pinned type. + /// + /// # Examples + /// + /// ``` + /// use std::pin::Pin; + /// + /// # struct Type {} + /// impl Type { + /// fn method(self: Pin<&mut Self>) { + /// // do something + /// } + /// + /// fn call_method_twice(mut self: Pin<&mut Self>) { + /// // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`. + /// self.as_mut().method(); + /// self.as_mut().method(); + /// } + /// } + /// ``` #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_mut(&mut self) -> Pin<&mut P::Target> { From a22e9ee8d0801f9738533b76a492e94065767cbc Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Tue, 17 Sep 2019 20:02:48 +0900 Subject: [PATCH 08/11] Update src/libcore/pin.rs Co-Authored-By: Ralf Jung --- src/libcore/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index e8d63b8c3130b..1dc6d54b08a5a 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -587,7 +587,7 @@ impl Pin

{ /// /// This method is useful when doing multiple calls to functions that consume the pinned type. /// - /// # Examples + /// # Example /// /// ``` /// use std::pin::Pin; From 0de9485038a5a068644efbfa397feec6d02e05ea Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 7 Jun 2019 19:22:42 +0200 Subject: [PATCH 09/11] Get rid of special const intrinsic query in favour of `const_eval` --- src/librustc/mir/interpret/error.rs | 9 ++ src/librustc/query/mod.rs | 9 -- src/librustc_codegen_llvm/intrinsic.rs | 36 +++---- src/librustc_codegen_ssa/mir/block.rs | 3 +- src/librustc_codegen_ssa/traits/intrinsic.rs | 4 +- src/librustc_mir/const_eval.rs | 18 ++++ src/librustc_mir/interpret/eval_context.rs | 10 +- src/librustc_mir/interpret/intrinsics.rs | 99 ++++++++++++------- .../interpret/intrinsics/type_name.rs | 21 +--- src/librustc_mir/interpret/mod.rs | 4 +- src/librustc_mir/lib.rs | 1 - .../issues => compile-fail}/issue-44415.rs | 0 src/test/ui/consts/const-size_of-cycle.stderr | 5 + src/test/ui/issues/issue-44415.stderr | 28 ------ 14 files changed, 117 insertions(+), 130 deletions(-) rename src/test/{ui/issues => compile-fail}/issue-44415.rs (100%) delete mode 100644 src/test/ui/issues/issue-44415.stderr diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 09c822f7508a0..67b3ce0e63fb0 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -213,6 +213,15 @@ fn print_backtrace(backtrace: &mut Backtrace) { eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace); } +impl From for InterpErrorInfo<'tcx> { + fn from(err: ErrorHandled) -> Self { + match err { + ErrorHandled::Reported => err_inval!(ReferencedConstant), + ErrorHandled::TooGeneric => err_inval!(TooGeneric), + }.into() + } +} + impl<'tcx> From> for InterpErrorInfo<'tcx> { fn from(kind: InterpError<'tcx>) -> Self { let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 4ebc2e72490d4..c7260945295a6 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -462,15 +462,6 @@ rustc_queries! { no_force desc { "extract field of const" } } - - /// Produces an absolute path representation of the given type. See also the documentation - /// on `std::any::type_name`. - query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - eval_always - no_force - desc { "get absolute path of type" } - } - } TypeChecking { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 5fbfe9138f2a4..3f3c5ac1460a3 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -15,6 +15,7 @@ use rustc_codegen_ssa::glue; use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types}; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; +use rustc::mir::interpret::GlobalId; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use syntax::ast::{self, FloatTy}; @@ -81,13 +82,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn codegen_intrinsic_call( &mut self, - callee_ty: Ty<'tcx>, + instance: ty::Instance<'tcx>, fn_ty: &FnType<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, &'ll Value>], llresult: &'ll Value, span: Span, ) { let tcx = self.tcx; + let callee_ty = instance.ty(tcx); let (def_id, substs) = match callee_ty.sty { ty::FnDef(def_id, substs) => (def_id, substs), @@ -133,10 +135,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let llfn = self.get_intrinsic(&("llvm.debugtrap")); self.call(llfn, &[], None) } - "size_of" => { - let tp_ty = substs.type_at(0); - self.const_usize(self.size_of(tp_ty).bytes()) - } "va_start" => { self.va_start(args[0].immediate()) } @@ -188,10 +186,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.const_usize(self.size_of(tp_ty).bytes()) } } - "min_align_of" => { - let tp_ty = substs.type_at(0); - self.const_usize(self.align_of(tp_ty).bytes()) - } "min_align_of_val" => { let tp_ty = substs.type_at(0); if let OperandValue::Pair(_, meta) = args[0].val { @@ -201,18 +195,19 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.const_usize(self.align_of(tp_ty).bytes()) } } - "pref_align_of" => { - let tp_ty = substs.type_at(0); - self.const_usize(self.layout_of(tp_ty).align.pref.bytes()) - } + "size_of" | + "pref_align_of" | + "min_align_of" | + "needs_drop" | + "type_id" | "type_name" => { - let tp_ty = substs.type_at(0); - let ty_name = self.tcx.type_name(tp_ty); + let gid = GlobalId { + instance, + promoted: None, + }; + let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap(); OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self) } - "type_id" => { - self.const_u64(self.tcx.type_id_hash(substs.type_at(0))) - } "init" => { let ty = substs.type_at(0); if !self.layout_of(ty).is_zst() { @@ -235,11 +230,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { "uninit" | "forget" => { return; } - "needs_drop" => { - let tp_ty = substs.type_at(0); - - self.const_bool(self.type_needs_drop(tp_ty)) - } "offset" => { let ptr = args[0].immediate(); let offset = args[1].immediate(); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 8829a33992ae3..1bb0ea5dae44b 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -667,8 +667,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }).collect(); - let callee_ty = instance.as_ref().unwrap().ty(bx.tcx()); - bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest, + bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest, terminator.source_info.span); if let ReturnDest::IndirectOperand(dst, _) = ret_dest { diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index ede30a0bed756..7c79cd6021031 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -1,6 +1,6 @@ use super::BackendTypes; use crate::mir::operand::OperandRef; -use rustc::ty::Ty; +use rustc::ty::{self, Ty}; use rustc_target::abi::call::FnType; use syntax_pos::Span; @@ -10,7 +10,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { /// add them to librustc_codegen_llvm/context.rs fn codegen_intrinsic_call( &mut self, - callee_ty: Ty<'tcx>, + instance: ty::Instance<'tcx>, fn_ty: &FnType<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Self::Value>], llresult: Self::Value, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 3f53f842f314f..435159827e6c3 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -15,6 +15,7 @@ use rustc::ty::{self, Ty, TyCtxt, subst::Subst}; use rustc::ty::layout::{self, LayoutOf, VariantIdx}; use rustc::traits::Reveal; use rustc_data_structures::fx::FxHashMap; +use crate::interpret::eval_nullary_intrinsic; use syntax::source_map::{Span, DUMMY_SP}; @@ -602,6 +603,23 @@ pub fn const_eval_provider<'tcx>( other => return other, } } + + // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. + // Catch such calls and evaluate them instead of trying to load a constant's MIR. + if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { + let ty = key.value.instance.ty(tcx); + let substs = match ty.sty { + ty::FnDef(_, substs) => substs, + _ => bug!("intrinsic with type {:?}", ty), + }; + return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs) + .map_err(|error| { + let span = tcx.def_span(def_id); + let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span }; + error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic") + }) + } + tcx.const_eval_raw(key).and_then(|val| { validate_and_turn_into_const(tcx, val, key) }) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 054b65f0e1a9e..78996ed6939d8 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -14,7 +14,6 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::query::TyCtxtAt; use rustc_data_structures::indexed_vec::IndexVec; use rustc::mir::interpret::{ - ErrorHandled, GlobalId, Scalar, Pointer, FrameInfo, AllocId, InterpResult, truncate, sign_extend, }; @@ -672,14 +671,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Our result will later be validated anyway, and there seems no good reason // to have to fail early here. This is also more consistent with // `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles. - let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| { - match err { - ErrorHandled::Reported => - err_inval!(ReferencedConstant), - ErrorHandled::TooGeneric => - err_inval!(TooGeneric), - } - })?; + let val = self.tcx.const_eval_raw(param_env.and(gid))?; self.raw_const_to_mplace(val) } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 0f2305e03ff33..ec09e69ec8537 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -5,17 +5,18 @@ use syntax::symbol::Symbol; use rustc::ty; use rustc::ty::layout::{LayoutOf, Primitive, Size}; +use rustc::ty::subst::SubstsRef; +use rustc::hir::def_id::DefId; +use rustc::ty::TyCtxt; use rustc::mir::BinOp; -use rustc::mir::interpret::{InterpResult, Scalar}; +use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue}; use super::{ - Machine, PlaceTy, OpTy, InterpCx, Immediate, + Machine, PlaceTy, OpTy, InterpCx, }; mod type_name; -pub use type_name::*; - fn numeric_intrinsic<'tcx, Tag>( name: &str, bits: u128, @@ -37,6 +38,50 @@ fn numeric_intrinsic<'tcx, Tag>( Ok(Scalar::from_uint(bits_out, size)) } +/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated +/// inside an `InterpCx` and instead have their value computed directly from rustc internal info. +crate fn eval_nullary_intrinsic<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, +) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> { + let tp_ty = substs.type_at(0); + let name = &*tcx.item_name(def_id).as_str(); + Ok(match name { + "type_name" => { + let alloc = type_name::alloc_type_name(tcx, tp_ty); + tcx.mk_const(ty::Const { + val: ConstValue::Slice { + data: alloc, + start: 0, + end: alloc.len(), + }, + ty: tcx.mk_static_str(), + }) + }, + "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)), + "size_of" | + "min_align_of" | + "pref_align_of" => { + let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; + let n = match name { + "pref_align_of" => layout.align.pref.bytes(), + "min_align_of" => layout.align.abi.bytes(), + "size_of" => layout.size.bytes(), + _ => bug!(), + }; + ty::Const::from_usize(tcx, n) + }, + "type_id" => ty::Const::from_bits( + tcx, + tcx.type_id_hash(tp_ty).into(), + param_env.and(tcx.types.u64), + ), + other => bug!("`{}` is not a zero arg intrinsic", other), + }) +} + impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Returns `true` if emulation happened. pub fn emulate_intrinsic( @@ -49,41 +94,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..]; match intrinsic_name { - "min_align_of" => { - let elem_ty = substs.type_at(0); - let elem_align = self.layout_of(elem_ty)?.align.abi.bytes(); - let align_val = Scalar::from_uint(elem_align, dest.layout.size); - self.write_scalar(align_val, dest)?; - } - - "needs_drop" => { - let ty = substs.type_at(0); - let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env); - let val = Scalar::from_bool(ty_needs_drop); - self.write_scalar(val, dest)?; - } - - "size_of" => { - let ty = substs.type_at(0); - let size = self.layout_of(ty)?.size.bytes() as u128; - let size_val = Scalar::from_uint(size, dest.layout.size); - self.write_scalar(size_val, dest)?; - } - - "type_id" => { - let ty = substs.type_at(0); - let type_id = self.tcx.type_id_hash(ty) as u128; - let id_val = Scalar::from_uint(type_id, dest.layout.size); - self.write_scalar(id_val, dest)?; - } - + "min_align_of" | + "pref_align_of" | + "needs_drop" | + "size_of" | + "type_id" | "type_name" => { - let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0)); - let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc); - let id_ptr = self.memory.tag_static_base_pointer(name_id.into()); - let alloc_len = alloc.size.bytes(); - let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self); - self.write_immediate(name_val, dest)?; + let gid = GlobalId { + instance, + promoted: None, + }; + let val = self.tcx.const_eval(self.param_env.and(gid))?; + let val = self.eval_const_to_op(val, None)?; + self.copy_op(val, dest)?; } | "ctpop" diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index 032d16a49db4b..1e765a4ed982c 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -7,7 +7,7 @@ use rustc::ty::{ use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::hir::def_id::CrateNum; use std::fmt::Write; -use rustc::mir::interpret::{Allocation, ConstValue}; +use rustc::mir::interpret::Allocation; struct AbsolutePathPrinter<'tcx> { tcx: TyCtxt<'tcx>, @@ -213,22 +213,11 @@ impl Write for AbsolutePathPrinter<'_> { } } -/// Produces an absolute path representation of the given type. See also the documentation on -/// `std::any::type_name` -pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - let alloc = alloc_type_name(tcx, ty); - tcx.mk_const(ty::Const { - val: ConstValue::Slice { - data: alloc, - start: 0, - end: alloc.len(), - }, - ty: tcx.mk_static_str(), - }) -} - /// Directly returns an `Allocation` containing an absolute path representation of the given type. -pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation { +crate fn alloc_type_name<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx> +) -> &'tcx Allocation { let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path; let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes()); tcx.intern_const_alloc(alloc) diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 45d24347e4efd..0c61be283dfd0 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -34,6 +34,6 @@ pub use self::visitor::{ValueVisitor, MutValueVisitor}; pub use self::validity::RefTracking; -pub(super) use self::intrinsics::type_name; - pub use self::intern::intern_const_alloc_recursive; + +crate use self::intrinsics::eval_nullary_intrinsic; diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index f27db351b74db..034ad5b01d346 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -59,5 +59,4 @@ pub fn provide(providers: &mut Providers<'_>) { let (param_env, (value, field)) = param_env_and_value.into_parts(); const_eval::const_field(tcx, param_env, None, field, value) }; - providers.type_name = interpret::type_name; } diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/compile-fail/issue-44415.rs similarity index 100% rename from src/test/ui/issues/issue-44415.rs rename to src/test/compile-fail/issue-44415.rs diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index fdba359e7464a..1ae39e7563a82 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -14,6 +14,11 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... | LL | intrinsics::size_of::() | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `std::intrinsics::size_of`... + --> $SRC_DIR/libcore/intrinsics.rs:LL:COL + | +LL | pub fn size_of() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr deleted file mode 100644 index 8008e53f65f4d..0000000000000 --- a/src/test/ui/issues/issue-44415.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0` - --> $DIR/issue-44415.rs:6:17 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^ - | -note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... - --> $DIR/issue-44415.rs:6:17 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^ -note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... - --> $DIR/issue-44415.rs:6:26 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing layout of `Foo`... - = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... - = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle -note: cycle used when processing `Foo` - --> $DIR/issue-44415.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0391`. From a4dc33baf6496e58eed16f612031475c88545091 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 17 Sep 2019 10:39:26 +0200 Subject: [PATCH 10/11] build-manifest: add some comments --- src/bootstrap/dist.rs | 14 ++++++++++---- src/tools/build-manifest/src/main.rs | 17 +++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 500d5766a899e..076bcd878df71 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2000,6 +2000,8 @@ impl Step for HashSign { } fn run(self, builder: &Builder<'_>) { + // This gets called by `promote-release` + // (https://github.com/rust-lang/rust-central-station/tree/master/promote-release). let mut cmd = builder.tool_cmd(Tool::BuildManifest); if builder.config.dry_run { return; @@ -2010,10 +2012,14 @@ impl Step for HashSign { let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n") }); - let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { - panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") - }); - let pass = t!(fs::read_to_string(&file)); + let pass = if env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err() { + let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") + }); + t!(fs::read_to_string(&file)) + } else { + String::new() + }; let today = output(Command::new("date").arg("+%Y-%m-%d")); diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 9ffa9391c820b..eab23f3cfffc4 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -1,3 +1,9 @@ +//! Build a dist manifest, hash and sign everything. +//! This gets called by `promote-release` +//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release) +//! via `x.py dist hash-and-sign`; the cmdline arguments are set up +//! by rustbuild (in `src/bootstrap/dist.rs`). + use toml; use serde::Serialize; @@ -270,6 +276,7 @@ fn main() { // Do not ask for a passphrase while manually testing let mut passphrase = String::new(); if should_sign { + // `x.py` passes the passphrase via stdin. t!(io::stdin().read_to_string(&mut passphrase)); } @@ -362,6 +369,7 @@ impl Builder { } } + /// Hash all files, compute their signatures, and collect the hashes in `self.digests`. fn digest_and_sign(&mut self) { for file in t!(self.input.read_dir()).map(|e| t!(e).path()) { let filename = file.file_name().unwrap().to_str().unwrap(); @@ -532,19 +540,20 @@ impl Builder { .as_ref() .cloned() .map(|version| (version, true)) - .unwrap_or_default(); + .unwrap_or_default(); // `is_present` defaults to `false` here. - // miri needs to build std with xargo, which doesn't allow stable/beta: - // + // Miri is nightly-only; never ship it for other trains. if pkgname == "miri-preview" && self.rust_release != "nightly" { - is_present = false; // ignore it + is_present = false; // Pretend the component is entirely missing. } let targets = targets.iter().map(|name| { if is_present { + // The component generally exists, but it might still be missing for this target. let filename = self.filename(pkgname, name); let digest = match self.digests.remove(&filename) { Some(digest) => digest, + // This component does not exist for this target -- skip it. None => return (name.to_string(), Target::unavailable()), }; let xz_filename = filename.replace(".tar.gz", ".tar.xz"); From ab6e108644474ece91711e889cff7d36a0adf7f0 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 13 Sep 2019 18:42:09 +0200 Subject: [PATCH 11/11] improve Vec example soundness in mem::transmute docs --- src/libcore/intrinsics.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index d145f2212f93a..ecff40a75978d 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -845,21 +845,26 @@ extern "rust-intrinsic" { /// /// ``` /// let store = [0, 1, 2, 3]; - /// let mut v_orig = store.iter().collect::>(); + /// let v_orig = store.iter().collect::>(); + /// + /// // clone the vector as we will reuse them later + /// let v_clone = v_orig.clone(); /// /// // Using transmute: this is Undefined Behavior, and a bad idea. /// // However, it is no-copy. /// let v_transmuted = unsafe { - /// std::mem::transmute::, Vec>>( - /// v_orig.clone()) + /// std::mem::transmute::, Vec>>(v_clone) /// }; /// + /// let v_clone = v_orig.clone(); + /// /// // This is the suggested, safe way. /// // It does copy the entire vector, though, into a new array. - /// let v_collected = v_orig.clone() - /// .into_iter() - /// .map(|r| Some(r)) - /// .collect::>>(); + /// let v_collected = v_clone.into_iter() + /// .map(Some) + /// .collect::>>(); + /// + /// let v_clone = v_orig.clone(); /// /// // The no-copy, unsafe way, still using transmute, but not UB. /// // This is equivalent to the original, but safer, and reuses the @@ -869,11 +874,12 @@ extern "rust-intrinsic" { /// // the original inner type (`&i32`) to the converted inner type /// // (`Option<&i32>`), so read the nomicon pages linked above. /// let v_from_raw = unsafe { - /// Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>, - /// v_orig.len(), - /// v_orig.capacity()) + /// // Ensure the original vector is not dropped. + /// let mut v_clone = std::mem::ManuallyDrop::new(v_clone); + /// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>, + /// v_clone.len(), + /// v_clone.capacity()) /// }; - /// std::mem::forget(v_orig); /// ``` /// /// Implementing `split_at_mut`: