Auto merge of #64562 - tmandry:rollup-kfk0nuo, r=tmandry
Rollup of 10 pull requests Successful merges: - #61626 (Get rid of special const intrinsic query in favour of `const_eval`) - #64283 (Updated RELEASES.md for 1.38.0) - #64394 (Shrink `SubregionOrigin`.) - #64429 (Fix failure note `to_str` implementation) - #64436 (improve Vec example soundness in mem::transmute docs) - #64502 (avoid duplicate issues for Miri build failures) - #64505 (Fix inconsistent link formatting) - #64529 (Add an example to Pin::as_mut) - #64541 (document Miri error categories) - #64544 (build-manifest: re-add some comments) Failed merges: r? @ghost
This commit is contained in:
commit
528379121c
105
RELEASES.md
105
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<T>`.][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)
|
||||
==========================
|
||||
|
||||
|
@ -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"));
|
||||
|
||||
|
@ -845,21 +845,26 @@ extern "rust-intrinsic" {
|
||||
///
|
||||
/// ```
|
||||
/// let store = [0, 1, 2, 3];
|
||||
/// let mut v_orig = store.iter().collect::<Vec<&i32>>();
|
||||
/// let v_orig = store.iter().collect::<Vec<&i32>>();
|
||||
///
|
||||
/// // 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<&i32>, Vec<Option<&i32>>>(
|
||||
/// v_orig.clone())
|
||||
/// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(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::<Vec<Option<&i32>>>();
|
||||
/// let v_collected = v_clone.into_iter()
|
||||
/// .map(Some)
|
||||
/// .collect::<Vec<Option<&i32>>>();
|
||||
///
|
||||
/// 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`:
|
||||
|
@ -584,6 +584,27 @@ impl<P: DerefMut> Pin<P> {
|
||||
/// the pointee cannot move after `Pin<Pointer<T>>` 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.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// 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> {
|
||||
|
@ -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)
|
||||
|
@ -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 }),
|
||||
}),
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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<TypeTrace<'tcx>>),
|
||||
|
||||
/// 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 {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -213,6 +213,15 @@ fn print_backtrace(backtrace: &mut Backtrace) {
|
||||
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
|
||||
}
|
||||
|
||||
impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
|
||||
fn from(err: ErrorHandled) -> Self {
|
||||
match err {
|
||||
ErrorHandled::Reported => err_inval!(ReferencedConstant),
|
||||
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
||||
fn from(kind: InterpError<'tcx>) -> Self {
|
||||
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
|
||||
@ -313,6 +322,9 @@ impl<O: fmt::Debug> fmt::Debug for PanicInfo<O> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 +354,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 +377,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 +556,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.
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -833,7 +833,7 @@ impl Level {
|
||||
Warning => "warning",
|
||||
Note => "note",
|
||||
Help => "help",
|
||||
FailureNote => "",
|
||||
FailureNote => "failure-note",
|
||||
Cancelled => panic!("Shouldn't call on cancelled error"),
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -2326,10 +2326,10 @@ impl<R: Read> Iterator for Bytes<R> {
|
||||
/// 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<B> {
|
||||
@ -2358,10 +2358,10 @@ impl<B: BufRead> Iterator for Split<B> {
|
||||
|
||||
/// 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<B> {
|
||||
|
@ -14,6 +14,11 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
|
||||
|
|
||||
LL | intrinsics::size_of::<T>()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
|
||||
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
|
||||
|
|
||||
LL | pub fn size_of<T>() -> 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
|
||||
|
@ -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::<Foo>() }],
|
||||
| ^^^^^^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
|
||||
--> $DIR/issue-44415.rs:6:17
|
||||
|
|
||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||
| ^^^^^^
|
||||
note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
|
||||
--> $DIR/issue-44415.rs:6:26
|
||||
|
|
||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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`.
|
@ -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`.
|
||||
"}
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
// <https://github.com/japaric/xargo/pull/204#issuecomment-374888868>
|
||||
// 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");
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user