Auto merge of #71795 - RalfJung:rollup-yqxfi5a, r=RalfJung
Rollup of 6 pull requests Successful merges: - #71712 (Miri: port error backtraces to std::backtrace) - #71736 (bootstrap: also apply unused-attributes hack without deny_warnings) - #71738 (remove AllocId generalization of Pointer) - #71739 (remove obsolete comment) - #71781 (Uncomment test code for failure to use `Box::pin`) - #71782 (Use a non-existent test path instead of clobbering /dev/null) Failed merges: r? @ghost
This commit is contained in:
commit
7184d137f6
16 changed files with 154 additions and 81 deletions
|
@ -3978,7 +3978,6 @@ name = "rustc_middle"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arena",
|
"arena",
|
||||||
"backtrace",
|
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"log",
|
"log",
|
||||||
|
|
|
@ -1088,13 +1088,13 @@ impl<'a> Builder<'a> {
|
||||||
|
|
||||||
if self.config.deny_warnings {
|
if self.config.deny_warnings {
|
||||||
rustflags.arg("-Dwarnings");
|
rustflags.arg("-Dwarnings");
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(#58633) hide "unused attribute" errors in incremental
|
// FIXME(#58633) hide "unused attribute" errors in incremental
|
||||||
// builds of the standard library, as the underlying checks are
|
// builds of the standard library, as the underlying checks are
|
||||||
// not yet properly integrated with incremental recompilation.
|
// not yet properly integrated with incremental recompilation.
|
||||||
if mode == Mode::Std && compiler.stage == 0 && self.config.incremental {
|
if mode == Mode::Std && compiler.stage == 0 && self.config.incremental {
|
||||||
rustflags.arg("-Aunused-attributes");
|
rustflags.arg("-Aunused-attributes");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ rustc_index = { path = "../librustc_index" }
|
||||||
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
||||||
rustc_ast = { path = "../librustc_ast" }
|
rustc_ast = { path = "../librustc_ast" }
|
||||||
rustc_span = { path = "../librustc_span" }
|
rustc_span = { path = "../librustc_span" }
|
||||||
backtrace = "0.3.40"
|
|
||||||
byteorder = { version = "1.3" }
|
byteorder = { version = "1.3" }
|
||||||
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
|
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
|
||||||
measureme = "0.7.1"
|
measureme = "0.7.1"
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
//! This API is completely unstable and subject to change.
|
//! This API is completely unstable and subject to change.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||||
|
#![feature(backtrace)]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
|
|
@ -6,7 +6,6 @@ use crate::ty::query::TyCtxtAt;
|
||||||
use crate::ty::tls;
|
use crate::ty::tls;
|
||||||
use crate::ty::{self, layout, Ty};
|
use crate::ty::{self, layout, Ty};
|
||||||
|
|
||||||
use backtrace::Backtrace;
|
|
||||||
use rustc_data_structures::sync::Lock;
|
use rustc_data_structures::sync::Lock;
|
||||||
use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
|
use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -15,7 +14,7 @@ use rustc_macros::HashStable;
|
||||||
use rustc_session::CtfeBacktrace;
|
use rustc_session::CtfeBacktrace;
|
||||||
use rustc_span::{def_id::DefId, Pos, Span};
|
use rustc_span::{def_id::DefId, Pos, Span};
|
||||||
use rustc_target::abi::{Align, Size};
|
use rustc_target::abi::{Align, Size};
|
||||||
use std::{any::Any, fmt, mem};
|
use std::{any::Any, backtrace::Backtrace, fmt, mem};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
|
||||||
pub enum ErrorHandled {
|
pub enum ErrorHandled {
|
||||||
|
@ -219,16 +218,15 @@ impl fmt::Display for InterpErrorInfo<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InterpErrorInfo<'_> {
|
impl InterpErrorInfo<'_> {
|
||||||
pub fn print_backtrace(&mut self) {
|
pub fn print_backtrace(&self) {
|
||||||
if let Some(ref mut backtrace) = self.backtrace {
|
if let Some(backtrace) = self.backtrace.as_ref() {
|
||||||
print_backtrace(&mut *backtrace);
|
print_backtrace(backtrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_backtrace(backtrace: &mut Backtrace) {
|
fn print_backtrace(backtrace: &Backtrace) {
|
||||||
backtrace.resolve();
|
eprintln!("\n\nAn error occurred in miri:\n{}", backtrace);
|
||||||
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ErrorHandled> for InterpErrorInfo<'_> {
|
impl From<ErrorHandled> for InterpErrorInfo<'_> {
|
||||||
|
@ -255,11 +253,11 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
||||||
|
|
||||||
let backtrace = match capture_backtrace {
|
let backtrace = match capture_backtrace {
|
||||||
CtfeBacktrace::Disabled => None,
|
CtfeBacktrace::Disabled => None,
|
||||||
CtfeBacktrace::Capture => Some(Box::new(Backtrace::new_unresolved())),
|
CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
|
||||||
CtfeBacktrace::Immediate => {
|
CtfeBacktrace::Immediate => {
|
||||||
// Print it now.
|
// Print it now.
|
||||||
let mut backtrace = Backtrace::new_unresolved();
|
let backtrace = Backtrace::force_capture();
|
||||||
print_backtrace(&mut backtrace);
|
print_backtrace(&backtrace);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -75,18 +75,14 @@ pub trait PointerArithmetic: HasDataLayout {
|
||||||
|
|
||||||
impl<T: HasDataLayout> PointerArithmetic for T {}
|
impl<T: HasDataLayout> PointerArithmetic for T {}
|
||||||
|
|
||||||
/// `Pointer` is generic over the type that represents a reference to `Allocation`s,
|
/// Represents a pointer in the Miri engine.
|
||||||
/// thus making it possible for the most convenient representation to be used in
|
|
||||||
/// each context.
|
|
||||||
///
|
///
|
||||||
/// Defaults to the index based and loosely coupled `AllocId`.
|
/// `Pointer` is generic over the `Tag` associated with each pointer,
|
||||||
///
|
|
||||||
/// `Pointer` is also generic over the `Tag` associated with each pointer,
|
|
||||||
/// which is used to do provenance tracking during execution.
|
/// which is used to do provenance tracking during execution.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
|
||||||
#[derive(HashStable)]
|
#[derive(HashStable)]
|
||||||
pub struct Pointer<Tag = (), Id = AllocId> {
|
pub struct Pointer<Tag = ()> {
|
||||||
pub alloc_id: Id,
|
pub alloc_id: AllocId,
|
||||||
pub offset: Size,
|
pub offset: Size,
|
||||||
pub tag: Tag,
|
pub tag: Tag,
|
||||||
}
|
}
|
||||||
|
@ -97,7 +93,7 @@ static_assert_size!(Pointer, 16);
|
||||||
// all the Miri types.
|
// all the Miri types.
|
||||||
// We have to use `Debug` output for the tag, because `()` does not implement
|
// We have to use `Debug` output for the tag, because `()` does not implement
|
||||||
// `Display` so we cannot specialize that.
|
// `Display` so we cannot specialize that.
|
||||||
impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Pointer<Tag, Id> {
|
impl<Tag: fmt::Debug> fmt::Debug for Pointer<Tag> {
|
||||||
default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
write!(f, "{:#?}+0x{:x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag)
|
write!(f, "{:#?}+0x{:x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag)
|
||||||
|
@ -107,7 +103,7 @@ impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Pointer<Tag, Id> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Specialization for no tag
|
// Specialization for no tag
|
||||||
impl<Id: fmt::Debug> fmt::Debug for Pointer<(), Id> {
|
impl fmt::Debug for Pointer<()> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
write!(f, "{:#?}+0x{:x}", self.alloc_id, self.offset.bytes())
|
write!(f, "{:#?}+0x{:x}", self.alloc_id, self.offset.bytes())
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl<'tcx> ConstValue<'tcx> {
|
||||||
/// of a simple value or a pointer into another `Allocation`
|
/// of a simple value or a pointer into another `Allocation`
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
|
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
|
||||||
#[derive(HashStable)]
|
#[derive(HashStable)]
|
||||||
pub enum Scalar<Tag = (), Id = AllocId> {
|
pub enum Scalar<Tag = ()> {
|
||||||
/// The raw bytes of a simple value.
|
/// The raw bytes of a simple value.
|
||||||
Raw {
|
Raw {
|
||||||
/// The first `size` bytes of `data` are the value.
|
/// The first `size` bytes of `data` are the value.
|
||||||
|
@ -101,7 +101,7 @@ pub enum Scalar<Tag = (), Id = AllocId> {
|
||||||
/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
|
/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
|
||||||
/// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
|
/// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
|
||||||
/// relocation and its associated offset together as a `Pointer` here.
|
/// relocation and its associated offset together as a `Pointer` here.
|
||||||
Ptr(Pointer<Tag, Id>),
|
Ptr(Pointer<Tag>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
@ -109,7 +109,7 @@ static_assert_size!(Scalar, 24);
|
||||||
|
|
||||||
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
|
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
|
||||||
// all the Miri types.
|
// all the Miri types.
|
||||||
impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Scalar<Tag, Id> {
|
impl<Tag: fmt::Debug> fmt::Debug for Scalar<Tag> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Scalar::Ptr(ptr) => write!(f, "{:?}", ptr),
|
Scalar::Ptr(ptr) => write!(f, "{:?}", ptr),
|
||||||
|
@ -542,8 +542,8 @@ impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable, Hash)]
|
#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable, Hash)]
|
||||||
pub enum ScalarMaybeUndef<Tag = (), Id = AllocId> {
|
pub enum ScalarMaybeUndef<Tag = ()> {
|
||||||
Scalar(Scalar<Tag, Id>),
|
Scalar(Scalar<Tag>),
|
||||||
Undef,
|
Undef,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,7 +563,7 @@ impl<Tag> From<Pointer<Tag>> for ScalarMaybeUndef<Tag> {
|
||||||
|
|
||||||
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
|
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
|
||||||
// all the Miri types.
|
// all the Miri types.
|
||||||
impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for ScalarMaybeUndef<Tag, Id> {
|
impl<Tag: fmt::Debug> fmt::Debug for ScalarMaybeUndef<Tag> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ScalarMaybeUndef::Undef => write!(f, "<uninitialized>"),
|
ScalarMaybeUndef::Undef => write!(f, "<uninitialized>"),
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl Error for ConstEvalErrKind {}
|
||||||
/// Should be called only if the error is actually going to to be reported!
|
/// Should be called only if the error is actually going to to be reported!
|
||||||
pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
|
pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
|
||||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||||
mut error: InterpErrorInfo<'tcx>,
|
error: InterpErrorInfo<'tcx>,
|
||||||
) -> ConstEvalErr<'tcx> {
|
) -> ConstEvalErr<'tcx> {
|
||||||
error.print_backtrace();
|
error.print_backtrace();
|
||||||
let stacktrace = ecx.generate_stacktrace();
|
let stacktrace = ecx.generate_stacktrace();
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_macros::HashStable;
|
||||||
use rustc_middle::ich::StableHashingContext;
|
use rustc_middle::ich::StableHashingContext;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
sign_extend, truncate, AllocId, FrameInfo, GlobalId, InterpResult, Pointer, Scalar,
|
sign_extend, truncate, FrameInfo, GlobalId, InterpResult, Pointer, Scalar,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::layout::{self, TyAndLayout};
|
use rustc_middle::ty::layout::{self, TyAndLayout};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
|
@ -103,8 +103,8 @@ pub enum StackPopCleanup {
|
||||||
|
|
||||||
/// State of a local variable including a memoized layout
|
/// State of a local variable including a memoized layout
|
||||||
#[derive(Clone, PartialEq, Eq, HashStable)]
|
#[derive(Clone, PartialEq, Eq, HashStable)]
|
||||||
pub struct LocalState<'tcx, Tag = (), Id = AllocId> {
|
pub struct LocalState<'tcx, Tag = ()> {
|
||||||
pub value: LocalValue<Tag, Id>,
|
pub value: LocalValue<Tag>,
|
||||||
/// Don't modify if `Some`, this is only used to prevent computing the layout twice
|
/// Don't modify if `Some`, this is only used to prevent computing the layout twice
|
||||||
#[stable_hasher(ignore)]
|
#[stable_hasher(ignore)]
|
||||||
pub layout: Cell<Option<TyAndLayout<'tcx>>>,
|
pub layout: Cell<Option<TyAndLayout<'tcx>>>,
|
||||||
|
@ -112,7 +112,7 @@ pub struct LocalState<'tcx, Tag = (), Id = AllocId> {
|
||||||
|
|
||||||
/// Current value of a local variable
|
/// Current value of a local variable
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable)] // Miri debug-prints these
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable)] // Miri debug-prints these
|
||||||
pub enum LocalValue<Tag = (), Id = AllocId> {
|
pub enum LocalValue<Tag = ()> {
|
||||||
/// This local is not currently alive, and cannot be used at all.
|
/// This local is not currently alive, and cannot be used at all.
|
||||||
Dead,
|
Dead,
|
||||||
/// This local is alive but not yet initialized. It can be written to
|
/// This local is alive but not yet initialized. It can be written to
|
||||||
|
@ -125,7 +125,7 @@ pub enum LocalValue<Tag = (), Id = AllocId> {
|
||||||
/// This is an optimization over just always having a pointer here;
|
/// This is an optimization over just always having a pointer here;
|
||||||
/// we can thus avoid doing an allocation when the local just stores
|
/// we can thus avoid doing an allocation when the local just stores
|
||||||
/// immediate values *and* never has its address taken.
|
/// immediate values *and* never has its address taken.
|
||||||
Live(Operand<Tag, Id>),
|
Live(Operand<Tag>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
|
impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
|
||||||
|
|
|
@ -15,8 +15,8 @@ use rustc_target::abi::{Abi, DiscriminantKind, HasDataLayout, Integer, LayoutOf,
|
||||||
use rustc_target::abi::{VariantIdx, Variants};
|
use rustc_target::abi::{VariantIdx, Variants};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
from_known_layout, sign_extend, truncate, AllocId, ConstValue, GlobalId, InterpCx,
|
from_known_layout, sign_extend, truncate, ConstValue, GlobalId, InterpCx, InterpResult,
|
||||||
InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Scalar, ScalarMaybeUndef,
|
MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Scalar, ScalarMaybeUndef,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An `Immediate` represents a single immediate self-contained Rust value.
|
/// An `Immediate` represents a single immediate self-contained Rust value.
|
||||||
|
@ -27,9 +27,9 @@ use super::{
|
||||||
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
|
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
|
||||||
/// defined on `Immediate`, and do not have to work with a `Place`.
|
/// defined on `Immediate`, and do not have to work with a `Place`.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
|
||||||
pub enum Immediate<Tag = (), Id = AllocId> {
|
pub enum Immediate<Tag = ()> {
|
||||||
Scalar(ScalarMaybeUndef<Tag, Id>),
|
Scalar(ScalarMaybeUndef<Tag>),
|
||||||
ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
|
ScalarPair(ScalarMaybeUndef<Tag>, ScalarMaybeUndef<Tag>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Tag> From<ScalarMaybeUndef<Tag>> for Immediate<Tag> {
|
impl<Tag> From<ScalarMaybeUndef<Tag>> for Immediate<Tag> {
|
||||||
|
@ -145,9 +145,9 @@ impl<'tcx, Tag> ::std::ops::Deref for ImmTy<'tcx, Tag> {
|
||||||
/// or still in memory. The latter is an optimization, to delay reading that chunk of
|
/// or still in memory. The latter is an optimization, to delay reading that chunk of
|
||||||
/// memory and to avoid having to store arbitrary-sized data here.
|
/// memory and to avoid having to store arbitrary-sized data here.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
|
||||||
pub enum Operand<Tag = (), Id = AllocId> {
|
pub enum Operand<Tag = ()> {
|
||||||
Immediate(Immediate<Tag, Id>),
|
Immediate(Immediate<Tag>),
|
||||||
Indirect(MemPlace<Tag, Id>),
|
Indirect(MemPlace<Tag>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -20,9 +20,9 @@ use super::{
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||||
/// Information required for the sound usage of a `MemPlace`.
|
/// Information required for the sound usage of a `MemPlace`.
|
||||||
pub enum MemPlaceMeta<Tag = (), Id = AllocId> {
|
pub enum MemPlaceMeta<Tag = ()> {
|
||||||
/// The unsized payload (e.g. length for slices or vtable pointer for trait objects).
|
/// The unsized payload (e.g. length for slices or vtable pointer for trait objects).
|
||||||
Meta(Scalar<Tag, Id>),
|
Meta(Scalar<Tag>),
|
||||||
/// `Sized` types or unsized `extern type`
|
/// `Sized` types or unsized `extern type`
|
||||||
None,
|
None,
|
||||||
/// The address of this place may not be taken. This protects the `MemPlace` from coming from
|
/// The address of this place may not be taken. This protects the `MemPlace` from coming from
|
||||||
|
@ -32,8 +32,8 @@ pub enum MemPlaceMeta<Tag = (), Id = AllocId> {
|
||||||
Poison,
|
Poison,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Tag, Id> MemPlaceMeta<Tag, Id> {
|
impl<Tag> MemPlaceMeta<Tag> {
|
||||||
pub fn unwrap_meta(self) -> Scalar<Tag, Id> {
|
pub fn unwrap_meta(self) -> Scalar<Tag> {
|
||||||
match self {
|
match self {
|
||||||
Self::Meta(s) => s,
|
Self::Meta(s) => s,
|
||||||
Self::None | Self::Poison => {
|
Self::None | Self::Poison => {
|
||||||
|
@ -47,9 +47,7 @@ impl<Tag, Id> MemPlaceMeta<Tag, Id> {
|
||||||
Self::None | Self::Poison => false,
|
Self::None | Self::Poison => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<Tag> MemPlaceMeta<Tag> {
|
|
||||||
pub fn erase_tag(self) -> MemPlaceMeta<()> {
|
pub fn erase_tag(self) -> MemPlaceMeta<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::Meta(s) => MemPlaceMeta::Meta(s.erase_tag()),
|
Self::Meta(s) => MemPlaceMeta::Meta(s.erase_tag()),
|
||||||
|
@ -60,22 +58,22 @@ impl<Tag> MemPlaceMeta<Tag> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||||
pub struct MemPlace<Tag = (), Id = AllocId> {
|
pub struct MemPlace<Tag = ()> {
|
||||||
/// A place may have an integral pointer for ZSTs, and since it might
|
/// A place may have an integral pointer for ZSTs, and since it might
|
||||||
/// be turned back into a reference before ever being dereferenced.
|
/// be turned back into a reference before ever being dereferenced.
|
||||||
/// However, it may never be undef.
|
/// However, it may never be undef.
|
||||||
pub ptr: Scalar<Tag, Id>,
|
pub ptr: Scalar<Tag>,
|
||||||
pub align: Align,
|
pub align: Align,
|
||||||
/// Metadata for unsized places. Interpretation is up to the type.
|
/// Metadata for unsized places. Interpretation is up to the type.
|
||||||
/// Must not be present for sized types, but can be missing for unsized types
|
/// Must not be present for sized types, but can be missing for unsized types
|
||||||
/// (e.g., `extern type`).
|
/// (e.g., `extern type`).
|
||||||
pub meta: MemPlaceMeta<Tag, Id>,
|
pub meta: MemPlaceMeta<Tag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||||
pub enum Place<Tag = (), Id = AllocId> {
|
pub enum Place<Tag = ()> {
|
||||||
/// A place referring to a value allocated in the `Memory` system.
|
/// A place referring to a value allocated in the `Memory` system.
|
||||||
Ptr(MemPlace<Tag, Id>),
|
Ptr(MemPlace<Tag>),
|
||||||
|
|
||||||
/// To support alloc-free locals, we are able to write directly to a local.
|
/// To support alloc-free locals, we are able to write directly to a local.
|
||||||
/// (Without that optimization, we'd just always be a `MemPlace`.)
|
/// (Without that optimization, we'd just always be a `MemPlace`.)
|
||||||
|
|
|
@ -217,7 +217,6 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
|
||||||
(impl_trait_ref, impl_obligations)
|
(impl_trait_ref, impl_obligations)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`super::obligations_for_generics`].
|
|
||||||
pub fn predicates_for_generics<'tcx>(
|
pub fn predicates_for_generics<'tcx>(
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
|
|
|
@ -4,8 +4,12 @@
|
||||||
//
|
//
|
||||||
// An attempt to `-o` into a directory we cannot write into should indeed
|
// An attempt to `-o` into a directory we cannot write into should indeed
|
||||||
// be an error; but not an ICE.
|
// be an error; but not an ICE.
|
||||||
|
//
|
||||||
|
// However, some folks run tests as root, which can write `/dev/` and end
|
||||||
|
// up clobbering `/dev/null`. Instead we'll use a non-existent path, which
|
||||||
|
// also used to ICE, but even root can't magically write there.
|
||||||
|
|
||||||
// compile-flags: -o /dev/null
|
// compile-flags: -o /does-not-exist/output
|
||||||
|
|
||||||
// The error-pattern check occurs *before* normalization, and the error patterns
|
// The error-pattern check occurs *before* normalization, and the error patterns
|
||||||
// are wildly different between build environments. So this is a cop-out (and we
|
// are wildly different between build environments. So this is a cop-out (and we
|
||||||
|
@ -15,10 +19,10 @@
|
||||||
// error-pattern: error
|
// error-pattern: error
|
||||||
|
|
||||||
// On Mac OS X, we get an error like the below
|
// On Mac OS X, we get an error like the below
|
||||||
// normalize-stderr-test "failed to write bytecode to /dev/null.non_ice_error_on_worker_io_fail.*" -> "io error modifying /dev/"
|
// normalize-stderr-test "failed to write bytecode to /does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying /does-not-exist/"
|
||||||
|
|
||||||
// On Linux, we get an error like the below
|
// On Linux, we get an error like the below
|
||||||
// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /dev/"
|
// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /does-not-exist/"
|
||||||
|
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
// ignore-windows - this is a unix-specific test
|
// ignore-windows - this is a unix-specific test
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
warning: ignoring --out-dir flag due to -o flag
|
warning: ignoring --out-dir flag due to -o flag
|
||||||
|
|
||||||
error: io error modifying /dev/
|
error: io error modifying /does-not-exist/
|
||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -11,19 +11,26 @@ fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32>
|
||||||
x //~ ERROR mismatched types
|
x //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: uncomment these once this commit is in Beta and we can rely on `rustc_on_unimplemented`
|
// This case is still subpar:
|
||||||
// having filtering for `Self` being a trait.
|
// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)`
|
||||||
//
|
// Should suggest changing the code from `Pin::new` to `Box::pin`.
|
||||||
// fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||||
// Box::new(x)
|
Box::new(x) //~ ERROR mismatched types
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||||
// Pin::new(x)
|
Pin::new(x) //~ ERROR mismatched types
|
||||||
// }
|
//~^ ERROR E0277
|
||||||
//
|
}
|
||||||
// fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
|
||||||
// Pin::new(Box::new(x))
|
fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||||
// }
|
Pin::new(Box::new(x)) //~ ERROR E0277
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zap() -> BoxFuture<'static, i32> {
|
||||||
|
async { //~ ERROR mismatched types
|
||||||
|
42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -15,6 +15,78 @@ LL | x
|
||||||
= help: type parameters must be constrained to match other types
|
= help: type parameters must be constrained to match other types
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/expected-boxed-future-isnt-pinned.rs:18:5
|
||||||
|
|
|
||||||
|
LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||||
|
| ----------------------- expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>` because of return type
|
||||||
|
LL | Box::new(x)
|
||||||
|
| ^^^^^^^^^^^ expected struct `std::pin::Pin`, found struct `std::boxed::Box`
|
||||||
|
|
|
||||||
|
= note: expected struct `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>`
|
||||||
|
found struct `std::boxed::Box<F>`
|
||||||
|
= help: use `Box::pin`
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/expected-boxed-future-isnt-pinned.rs:22:14
|
||||||
|
|
|
||||||
|
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||||
|
| - this type parameter
|
||||||
|
LL | Pin::new(x)
|
||||||
|
| ^
|
||||||
|
| |
|
||||||
|
| expected struct `std::boxed::Box`, found type parameter `F`
|
||||||
|
| help: store this in the heap by calling `Box::new`: `Box::new(x)`
|
||||||
|
|
|
||||||
|
= note: expected struct `std::boxed::Box<dyn std::future::Future<Output = i32> + std::marker::Send>`
|
||||||
|
found type parameter `F`
|
||||||
|
= help: type parameters must be constrained to match other types
|
||||||
|
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||||
|
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
|
||||||
|
|
||||||
|
error[E0277]: `dyn std::future::Future<Output = i32> + std::marker::Send` cannot be unpinned
|
||||||
|
--> $DIR/expected-boxed-future-isnt-pinned.rs:22:5
|
||||||
|
|
|
||||||
|
LL | Pin::new(x)
|
||||||
|
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::future::Future<Output = i32> + std::marker::Send`
|
||||||
|
|
|
||||||
|
= note: consider using `Box::pin`
|
||||||
|
= note: required by `std::pin::Pin::<P>::new`
|
||||||
|
|
||||||
|
error[E0277]: `dyn std::future::Future<Output = i32> + std::marker::Send` cannot be unpinned
|
||||||
|
--> $DIR/expected-boxed-future-isnt-pinned.rs:27:5
|
||||||
|
|
|
||||||
|
LL | Pin::new(Box::new(x))
|
||||||
|
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::future::Future<Output = i32> + std::marker::Send`
|
||||||
|
|
|
||||||
|
= note: consider using `Box::pin`
|
||||||
|
= note: required by `std::pin::Pin::<P>::new`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/expected-boxed-future-isnt-pinned.rs:31:5
|
||||||
|
|
|
||||||
|
LL | fn zap() -> BoxFuture<'static, i32> {
|
||||||
|
| ----------------------- expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>` because of return type
|
||||||
|
LL | / async {
|
||||||
|
LL | | 42
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected struct `std::pin::Pin`, found opaque type
|
||||||
|
|
|
||||||
|
::: $SRC_DIR/libcore/future/mod.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
|
||||||
|
| ------------------------------- the found opaque type
|
||||||
|
|
|
||||||
|
= note: expected struct `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>`
|
||||||
|
found opaque type `impl std::future::Future`
|
||||||
|
help: you need to pin and box this expression
|
||||||
|
|
|
||||||
|
LL | Box::pin(async {
|
||||||
|
LL | 42
|
||||||
|
LL | })
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0308.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Reference in a new issue