Auto merge of #115018 - matthiaskrgr:rollup-pxj0qdb, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #114834 (Avoid side-effects from `try_coerce` when suggesting borrowing LHS of cast)
 - #114968 (Fix UB in `std::sys::os::getenv()`)
 - #114976 (Ignore unexpected incr-comp session dirs)
 - #114999 (Migrate GUI colors test to original CSS color format)
 - #115000 (custom_mir: change Call() terminator syntax to something more readable)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-08-20 08:11:08 +00:00
commit b6ab01a713
35 changed files with 270 additions and 431 deletions

View File

@ -389,34 +389,26 @@ impl<'a, 'tcx> CastCheck<'tcx> {
if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind()
&& fcx
.try_coerce(
self.expr,
.can_coerce(
Ty::new_ref(fcx.tcx,
fcx.tcx.lifetimes.re_erased,
TypeAndMut { ty: expr_ty, mutbl },
),
self.cast_ty,
AllowTwoPhase::No,
None,
)
.is_ok()
{
sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind()
&& expr_mutbl == Mutability::Not
&& mutbl == Mutability::Mut
&& fcx
.try_coerce(
self.expr,
.can_coerce(
Ty::new_ref(fcx.tcx,
expr_reg,
TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
),
self.cast_ty,
AllowTwoPhase::No,
None,
)
.is_ok()
{
sugg_mutref = true;
}
@ -424,30 +416,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
if !sugg_mutref
&& sugg == None
&& fcx
.try_coerce(
self.expr,
.can_coerce(
Ty::new_ref(fcx.tcx,reg, TypeAndMut { ty: self.expr_ty, mutbl }),
self.cast_ty,
AllowTwoPhase::No,
None,
)
.is_ok()
{
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind()
&& fcx
.try_coerce(
self.expr,
.can_coerce(
Ty::new_ref(fcx.tcx,
fcx.tcx.lifetimes.re_erased,
TypeAndMut { ty: self.expr_ty, mutbl },
),
self.cast_ty,
AllowTwoPhase::No,
None,
)
.is_ok()
{
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
@ -760,7 +744,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
ty::FnDef(..) => {
// Attempt a coercion to a fn pointer type.
let f = fcx.normalize(self.expr_span, self.expr_ty.fn_sig(fcx.tcx));
let res = fcx.try_coerce(
let res = fcx.coerce(
self.expr,
self.expr_ty,
Ty::new_fn_ptr(fcx.tcx, f),
@ -860,7 +844,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
(_, DynStar) => {
if fcx.tcx.features().dyn_star {
bug!("should be handled by `try_coerce`")
bug!("should be handled by `coerce`")
} else {
Err(CastError::IllegalCast)
}
@ -956,7 +940,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
// Coerce to a raw pointer so that we generate AddressOf in MIR.
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr);
fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
.unwrap_or_else(|_| {
bug!(
"could not cast from reference to array to pointer to array ({:?} to {:?})",
@ -992,7 +976,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
}
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'tcx>> {
match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
match fcx.coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
Ok(_) => Ok(()),
Err(err) => Err(err),
}

View File

@ -1005,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// adjusted type of the expression, if successful.
/// Adjustments are only recorded if the coercion succeeded.
/// The expressions *must not* have any preexisting adjustments.
pub fn try_coerce(
pub fn coerce(
&self,
expr: &hir::Expr<'_>,
expr_ty: Ty<'tcx>,
@ -1036,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
}
/// Same as `try_coerce()`, but without side-effects.
/// Same as `coerce()`, but without side-effects.
///
/// Returns false if the coercion creates any obligations that result in
/// errors.
@ -1494,7 +1494,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// Special-case the first expression we are coercing.
// To be honest, I'm not entirely sure why we do this.
// We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
fcx.try_coerce(
fcx.coerce(
expression,
expression_ty,
self.expected_ty,

View File

@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) {
let expected = self.resolve_vars_with_obligations(expected);
let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
Ok(ty) => return (ty, None),
Err(e) => e,
};
@ -475,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else { continue; };
let arg_ty = arg_ty.fold_with(&mut fudger);
let _ = self.try_coerce(
let _ = self.coerce(
arg_expr,
arg_ty,
*expected_arg_ty,

View File

@ -260,9 +260,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// fulfillment error to be more accurate.
let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
let coerce_error = self
.try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
.err();
let coerce_error =
self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
if coerce_error.is_some() {
return Compatibility::Incompatible(coerce_error);

View File

@ -538,9 +538,13 @@ where
continue;
}
let timestamp = extract_timestamp_from_session_dir(&directory_name).unwrap_or_else(|_| {
bug!("unexpected incr-comp session dir: {}", session_dir.display())
});
let timestamp = match extract_timestamp_from_session_dir(&directory_name) {
Ok(timestamp) => timestamp,
Err(e) => {
debug!("unexpected incr-comp session dir: {}: {}", session_dir.display(), e);
continue;
}
};
if timestamp > best_candidate.0 {
best_candidate = (timestamp, Some(session_dir.clone()));
@ -562,14 +566,14 @@ fn is_session_directory_lock_file(file_name: &str) -> bool {
file_name.starts_with("s-") && file_name.ends_with(LOCK_FILE_EXT)
}
fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime, ()> {
fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime, &'static str> {
if !is_session_directory(directory_name) {
return Err(());
return Err("not a directory");
}
let dash_indices: Vec<_> = directory_name.match_indices('-').map(|(idx, _)| idx).collect();
if dash_indices.len() != 3 {
return Err(());
return Err("not three dashes in name");
}
string_to_timestamp(&directory_name[dash_indices[0] + 1..dash_indices[1]])
@ -581,11 +585,11 @@ fn timestamp_to_string(timestamp: SystemTime) -> String {
base_n::encode(micros as u128, INT_ENCODE_BASE)
}
fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
let micros_since_unix_epoch = u64::from_str_radix(s, INT_ENCODE_BASE as u32);
if micros_since_unix_epoch.is_err() {
return Err(());
return Err("timestamp not an int");
}
let micros_since_unix_epoch = micros_since_unix_epoch.unwrap();

View File

@ -61,9 +61,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
})
},
@call("mir_call", args) => {
let destination = self.parse_place(args[0])?;
let target = self.parse_block(args[1])?;
self.parse_call(args[2], destination, target)
self.parse_call(args)
},
ExprKind::Match { scrutinee, arms, .. } => {
let discr = self.parse_operand(*scrutinee)?;
@ -109,13 +107,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise))
}
fn parse_call(
&self,
expr_id: ExprId,
destination: Place<'tcx>,
target: BasicBlock,
) -> PResult<TerminatorKind<'tcx>> {
parse_by_kind!(self, expr_id, _, "function call",
fn parse_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> {
let (destination, call) = parse_by_kind!(self, args[0], _, "function call",
ExprKind::Assign { lhs, rhs } => (*lhs, *rhs),
);
let destination = self.parse_place(destination)?;
let target = self.parse_block(args[1])?;
parse_by_kind!(self, call, _, "function call",
ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
let fun = self.parse_operand(*fun)?;
let args = args

View File

@ -104,17 +104,18 @@
//! }
//!
//! #[custom_mir(dialect = "runtime", phase = "optimized")]
#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set
//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
//! mir!(
//! let unused;
//! let _unused;
//! let popped;
//!
//! {
//! Call(unused, pop, Vec::push(v, value))
//! Call(_unused = Vec::push(v, value), pop)
//! }
//!
//! pop = {
//! Call(popped, drop, Vec::pop(v))
//! Call(popped = Vec::pop(v), drop)
//! }
//!
//! drop = {
@ -275,7 +276,7 @@ define!("mir_return", fn Return() -> BasicBlock);
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
define!("mir_unreachable", fn Unreachable() -> BasicBlock);
define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
define!("mir_call", fn Call(call: (), goto: BasicBlock));
define!("mir_storage_live", fn StorageLive<T>(local: T));
define!("mir_storage_dead", fn StorageDead<T>(local: T));
define!("mir_deinit", fn Deinit<T>(place: T));

View File

@ -81,6 +81,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
static ENV_LOCK: RwLock<()> = RwLock::new(());
pub fn env_read_lock() -> impl Drop {
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
}
pub struct Env {
iter: vec::IntoIter<(OsString, OsString)>,
}
@ -134,7 +138,7 @@ pub fn env() -> Env {
}
unsafe {
let _guard = ENV_LOCK.read();
let _guard = env_read_lock();
let mut result = Vec::new();
if !environ.is_null() {
while !(*environ).is_null() {
@ -168,17 +172,21 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> {
// environment variables with a nul byte can't be set, so their value is
// always None as well
let s = run_with_cstr(k.as_bytes(), |k| {
let _guard = ENV_LOCK.read();
Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
})
.ok()?;
run_with_cstr(k.as_bytes(), |k| {
let _guard = env_read_lock();
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
if s.is_null() {
None
} else {
Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
}
if v.is_null() {
Ok(None)
} else {
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
Ok(Some(OsStringExt::from_vec(bytes)))
}
})
.ok()
.flatten()
}
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {

View File

@ -594,16 +594,21 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> {
// environment variables with a nul byte can't be set, so their value is
// always None as well
let s = run_with_cstr(k.as_bytes(), |k| {
run_with_cstr(k.as_bytes(), |k| {
let _guard = env_read_lock();
Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
if v.is_null() {
Ok(None)
} else {
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
Ok(Some(OsStringExt::from_vec(bytes)))
}
})
.ok()?;
if s.is_null() {
None
} else {
Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
}
.ok()
.flatten()
}
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {

View File

@ -225,16 +225,23 @@ pub fn env() -> Env {
}
pub fn getenv(k: &OsStr) -> Option<OsString> {
let s = run_with_cstr(k.as_bytes(), |k| unsafe {
// environment variables with a nul byte can't be set, so their value is
// always None as well
run_with_cstr(k.as_bytes(), |k| {
let _guard = env_read_lock();
Ok(libc::getenv(k.as_ptr()) as *const libc::c_char)
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
if v.is_null() {
Ok(None)
} else {
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
Ok(Some(OsStringExt::from_vec(bytes)))
}
})
.ok()?;
if s.is_null() {
None
} else {
Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
}
.ok()
.flatten()
}
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {

View File

@ -8,13 +8,13 @@ pub struct S(i32);
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn main() {
mir! {
let unit: ();
let _unit: ();
{
let non_copy = S(42);
let ptr = std::ptr::addr_of_mut!(non_copy);
// Inside `callee`, the first argument and `*ptr` are basically
// aliasing places!
Call(unit, after_call, callee(Move(*ptr), ptr))
Call(_unit = callee(Move(*ptr), ptr), after_call)
}
after_call = {
Return()

View File

@ -10,7 +10,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
LL | / mir! {
LL | | let unit: ();
LL | | let _unit: ();
LL | | {
LL | | let non_copy = S(42);
... |
@ -27,8 +27,8 @@ LL | unsafe { ptr.write(S(0)) };
note: inside `main`
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
LL | Call(unit, after_call, callee(Move(*ptr), ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = callee(Move(*ptr), ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
LL | / mir! {
LL | | let unit: ();
LL | | let _unit: ();
LL | | {
LL | | let non_copy = S(42);
... |
@ -29,8 +29,8 @@ LL | unsafe { ptr.write(S(0)) };
note: inside `main`
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
LL | Call(unit, after_call, callee(Move(*ptr), ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = callee(Move(*ptr), ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -6,12 +6,12 @@ pub struct S(i32);
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn main() {
mir! {
let unit: ();
let _unit: ();
let _observe: i32;
{
let non_copy = S(42);
// This could change `non_copy` in-place
Call(unit, after_call, change_arg(Move(non_copy)))
Call(_unit = change_arg(Move(non_copy)), after_call)
}
after_call = {
// So now we must not be allowed to observe non-copy again.

View File

@ -11,8 +11,8 @@ LL | unsafe { ptr.read() };
note: inside `main`
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
LL | Call(unit, after_call, change_arg(Move(*ptr), ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -9,12 +9,12 @@ pub struct S(i32);
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn main() {
mir! {
let unit: ();
let _unit: ();
{
let non_copy = S(42);
let ptr = std::ptr::addr_of_mut!(non_copy);
// This could change `non_copy` in-place
Call(unit, after_call, change_arg(Move(*ptr), ptr))
Call(_unit = change_arg(Move(*ptr), ptr), after_call)
}
after_call = {
Return()

View File

@ -10,7 +10,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
LL | / mir! {
LL | | let unit: ();
LL | | let _unit: ();
LL | | {
LL | | let non_copy = S(42);
... |
@ -27,8 +27,8 @@ LL | x.0 = 0;
note: inside `main`
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
LL | Call(unit, after_call, change_arg(Move(*ptr), ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
LL | / mir! {
LL | | let unit: ();
LL | | let _unit: ();
LL | | {
LL | | let non_copy = S(42);
... |
@ -29,8 +29,8 @@ LL | x.0 = 0;
note: inside `main`
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
LL | Call(unit, after_call, change_arg(Move(*ptr), ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -11,8 +11,8 @@ LL | unsafe { ptr.read() };
note: inside `main`
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
LL | Call(*ptr, after_call, myfun(ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(*ptr = myfun(ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -15,7 +15,7 @@ pub fn main() {
let ptr = &raw mut x;
// We arrange for `myfun` to have a pointer that aliases
// its return place. Even just reading from that pointer is UB.
Call(*ptr, after_call, myfun(ptr))
Call(*ptr = myfun(ptr), after_call)
}
after_call = {

View File

@ -27,8 +27,8 @@ LL | unsafe { ptr.read() };
note: inside `main`
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
LL | Call(*ptr, after_call, myfun(ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(*ptr = myfun(ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -29,8 +29,8 @@ LL | unsafe { ptr.read() };
note: inside `main`
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
LL | Call(*ptr, after_call, myfun(ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(*ptr = myfun(ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -9,11 +9,11 @@ use std::intrinsics::mir::*;
pub fn main() {
mir! {
{
let x = 0;
let ptr = &raw mut x;
let _x = 0;
let ptr = &raw mut _x;
// We arrange for `myfun` to have a pointer that aliases
// its return place. Even just reading from that pointer is UB.
Call(x, after_call, myfun(ptr))
Call(_x = myfun(ptr), after_call)
}
after_call = {

View File

@ -13,8 +13,8 @@ help: the accessed tag <TAG> was created here
|
LL | / mir! {
LL | | {
LL | | let x = 0;
LL | | let ptr = &raw mut x;
LL | | let _x = 0;
LL | | let ptr = &raw mut _x;
... |
LL | | }
LL | | }
@ -29,8 +29,8 @@ LL | unsafe { ptr.write(0) };
note: inside `main`
--> $DIR/return_pointer_aliasing2.rs:LL:CC
|
LL | Call(x, after_call, myfun(ptr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_x = myfun(ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -11,7 +11,7 @@ pub fn main() {
{
let x = 0;
let ptr = &raw mut x;
Call(*ptr, after_call, myfun())
Call(*ptr = myfun(), after_call)
}
after_call = {

View File

@ -12,7 +12,7 @@ fn ident<T>(t: T) -> T {
fn direct_call(x: i32) -> i32 {
mir!(
{
Call(RET, retblock, ident(x))
Call(RET = ident(x), retblock)
}
retblock = {
@ -26,7 +26,7 @@ fn direct_call(x: i32) -> i32 {
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
mir!(
{
Call(RET, retblock, f(x))
Call(RET = f(x), retblock)
}
retblock = {

View File

@ -21,11 +21,11 @@ fn f() -> bool {
let b = a;
// We cannot propagate the place `a`.
let r2 = &b;
Call(RET, next, cmp_ref(r1, r2))
Call(RET = cmp_ref(r1, r2), next)
}
next = {
// But we can propagate the value `a`.
Call(RET, ret, opaque(b))
Call(RET = opaque(b), ret)
}
ret = {
Return()

View File

@ -13,11 +13,11 @@ struct NotCopy(bool);
fn f(_1: NotCopy) {
mir!({
let _2 = _1;
Call(RET, bb1, opaque(Move(_1)))
Call(RET = opaque(Move(_1)), bb1)
}
bb1 = {
let _3 = Move(_2);
Call(RET, bb2, opaque(_3))
Call(RET = opaque(_3), bb2)
}
bb2 = {
Return()

View File

@ -17,10 +17,10 @@ fn f(a: Foo) -> bool {
let b = a;
// This is a move out of a copy, so must become a copy of `a.0`.
let c = Move(b.0);
Call(RET, bb1, opaque(Move(a)))
Call(RET = opaque(Move(a)), bb1)
}
bb1 = {
Call(RET, ret, opaque(Move(c)))
Call(RET = opaque(Move(c)), ret)
}
ret = {
Return()

View File

@ -426,7 +426,7 @@ fn multiple_storage() {
// As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s
// pointer address is the address of `x`, so do nothing.
let y = *z;
Call(RET, retblock, opaque(y))
Call(RET = opaque(y), retblock)
}
retblock = {
@ -452,7 +452,7 @@ fn dominate_storage() {
}
bb1 = {
let c = *r;
Call(RET, bb2, opaque(c))
Call(RET = opaque(c), bb2)
}
bb2 = {
StorageDead(x);
@ -486,18 +486,18 @@ fn maybe_dead(m: bool) {
bb1 = {
StorageDead(x);
StorageDead(y);
Call(RET, bb2, opaque(u))
Call(RET = opaque(u), bb2)
}
bb2 = {
// As `x` may be `StorageDead`, `a` may be dangling, so we do nothing.
let z = *a;
Call(RET, bb3, opaque(z))
Call(RET = opaque(z), bb3)
}
bb3 = {
// As `y` may be `StorageDead`, `b` may be dangling, so we do nothing.
// This implies that we also do not substitute `b` in `bb0`.
let t = *b;
Call(RET, retblock, opaque(t))
Call(RET = opaque(t), retblock)
}
retblock = {
Return()

View File

@ -2,262 +2,138 @@
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
show-text: true
// Ayu theme
set-local-storage: {
"rustdoc-theme": "ayu",
"rustdoc-use-system-theme": "false",
}
reload:
assert-css: (
".search-input",
{
"border-color": "rgb(92, 103, 115)",
"background-color": "rgb(20, 25, 32)",
"color": "rgb(255, 255, 255)",
},
)
focus: ".search-input"
// Nothing should change.
assert-css: (
".search-input",
{
"border-color": "rgb(92, 103, 115)",
"background-color": "rgb(20, 25, 32)",
"color": "rgb(255, 255, 255)",
define-function: (
"check-search-colors",
(
theme, border, background, search_input_color, search_input_border_focus,
menu_button_border, menu_button_a_color, menu_button_a_border_hover, menu_a_color,
),
block {
set-local-storage: {
"rustdoc-theme": |theme|,
"rustdoc-use-system-theme": "false",
}
reload:
assert-css: (
".search-input",
{
"border-color": |border|,
"background-color": |background|,
"color": |search_input_color|,
},
)
// Focus on search input.
focus: ".search-input"
assert-css: (
".search-input",
{
"border-color": |search_input_border_focus|,
"background-color": |background|,
"color": |search_input_color|,
},
)
assert-css: (
"#help-button",
{"border-color": |menu_button_border|},
)
assert-css: (
"#help-button > a",
{
"color": |menu_button_a_color|,
"border-color": |border|,
"background-color": |background|,
},
)
// Hover help button.
move-cursor-to: "#help-button"
assert-css: (
"#help-button:hover",
{"border-color": |menu_button_border|},
)
assert-css: (
"#help-button > a",
{
"color": |menu_button_a_color|,
"border-color": |menu_button_a_border_hover|,
"background-color": |background|,
},
)
// Link color inside
click: "#help-button"
assert-css: (
"#help a",
{
"color": |menu_a_color|,
},
)
assert-css: (
"#settings-menu",
{"border-color": |menu_button_border|},
)
assert-css: (
"#settings-menu > a",
{
"color": |menu_button_a_color|,
"border-color": |border|,
"background-color": |background|,
},
)
// Hover settings menu.
move-cursor-to: "#settings-menu"
assert-css: (
"#settings-menu:hover",
{"border-color": |menu_button_border|},
)
assert-css: (
"#settings-menu:hover > a",
{
"color": |menu_button_a_color|,
"border-color": |menu_button_a_border_hover|,
"background-color": |background|,
},
)
},
)
assert-css: (
"#help-button",
{"border-color": "rgb(197, 197, 197)"},
)
assert-css: (
"#help-button > a",
call-function: (
"check-search-colors",
{
"color": "rgb(255, 255, 255)",
"border-color": "rgb(92, 103, 115)",
"background-color": "rgb(20, 25, 32)",
},
"theme": "ayu",
"border": "#5c6773",
"background": "#141920",
"search_input_color": "#fff",
"search_input_border_focus": "#5c6773",
"menu_button_border": "#c5c5c5",
"menu_button_a_color": "#fff",
"menu_button_a_border_hover": "#e0e0e0",
"menu_a_color": "#39afd7",
}
)
move-cursor-to: "#help-button"
assert-css: (
"#help-button:hover",
{"border-color": "rgb(197, 197, 197)"},
)
// Only "border-color" should change.
assert-css: (
"#help-button:hover > a",
call-function: (
"check-search-colors",
{
"color": "rgb(255, 255, 255)",
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(20, 25, 32)",
},
"theme": "dark",
"border": "#e0e0e0",
"background": "#f0f0f0",
"search_input_color": "#111",
"search_input_border_focus": "#008dfd",
"menu_button_border": "#ddd",
"menu_button_a_color": "#000",
"menu_button_a_border_hover": "#ffb900",
"menu_a_color": "#d2991d",
}
)
// Link color inside
click: "#help-button"
assert-css: (
"#help a",
call-function: (
"check-search-colors",
{
"color": "rgb(57, 175, 215)",
},
)
assert-css: (
"#settings-menu",
{"border-color": "rgb(197, 197, 197)"},
)
assert-css: (
"#settings-menu > a",
{
"border-color": "rgb(92, 103, 115)",
"background-color": "rgb(20, 25, 32)",
},
)
move-cursor-to: "#settings-menu"
assert-css: (
"#settings-menu:hover",
{"border-color": "rgb(197, 197, 197)"},
)
// Only "border-color" should change.
assert-css: (
"#settings-menu:hover > a",
{
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(20, 25, 32)",
},
)
// Dark theme
set-local-storage: {
"rustdoc-theme": "dark",
"rustdoc-use-system-theme": "false",
}
reload:
assert-css: (
".search-input",
{
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(240, 240, 240)",
"color": "rgb(17, 17, 17)",
},
)
focus: ".search-input"
// Only "border-color" should change.
assert-css: (
".search-input",
{
"border-color": "rgb(0, 141, 253)",
"background-color": "rgb(240, 240, 240)",
"color": "rgb(17, 17, 17)",
},
)
assert-css: (
"#help-button",
{"border-color": "rgb(221, 221, 221)"},
)
assert-css: (
"#help-button > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(240, 240, 240)",
},
)
move-cursor-to: "#help-button"
assert-css: (
"#help-button:hover",
{"border-color": "rgb(221, 221, 221)"},
)
// Only "border-color" should change.
assert-css: (
"#help-button:hover > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(255, 185, 0)",
"background-color": "rgb(240, 240, 240)",
},
)
// Link color inside
click: "#help-button"
assert-css: (
"#help a",
{
"color": "rgb(210, 153, 29)",
},
)
assert-css: (
"#settings-menu",
{"border-color": "rgb(221, 221, 221)"},
)
assert-css: (
"#settings-menu > a",
{
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(240, 240, 240)",
},
)
move-cursor-to: "#settings-menu"
assert-css: (
"#settings-menu:hover",
{"border-color": "rgb(221, 221, 221)"},
)
// Only "border-color" should change.
assert-css: (
"#settings-menu:hover > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(255, 185, 0)",
"background-color": "rgb(240, 240, 240)",
},
)
// Light theme
set-local-storage: {
"rustdoc-theme": "light",
"rustdoc-use-system-theme": "false",
}
reload:
assert-css: (
".search-input",
{
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(255, 255, 255)",
"color": "rgb(0, 0, 0)",
},
)
focus: ".search-input"
// Nothing should change.
assert-css: (
".search-input",
{
"border-color": "rgb(102, 175, 233)",
"background-color": "rgb(255, 255, 255)",
"color": "rgb(0, 0, 0)",
},
)
assert-css: (
"#help-button",
{"border-color": "rgb(0, 0, 0)"},
)
assert-css: (
"#help-button > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(255, 255, 255)",
},
)
move-cursor-to: "#help-button"
assert-css: (
"#help-button:hover",
{"border-color": "rgb(0, 0, 0)"},
)
// Only "border-color" should change.
assert-css: (
"#help-button:hover > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(113, 113, 113)",
"background-color": "rgb(255, 255, 255)",
},
)
// Link color inside
click: "#help-button"
assert-css: (
"#help a",
{
"color": "rgb(56, 115, 173)",
},
)
assert-css: (
"#settings-menu",
{"border-color": "rgb(0, 0, 0)"},
)
assert-css: (
"#settings-menu > a",
{
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(255, 255, 255)",
},
)
move-cursor-to: "#settings-menu"
assert-css: (
"#settings-menu:hover",
{"border-color": "rgb(0, 0, 0)"},
)
// Only "border-color" should change.
assert-css: (
"#settings-menu:hover > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(113, 113, 113)",
"background-color": "rgb(255, 255, 255)",
},
"theme": "light",
"border": "#e0e0e0",
"background": "#fff",
"search_input_color": "#000",
"search_input_border_focus": "#66afe9",
"menu_button_border": "#000",
"menu_button_a_color": "#000",
"menu_button_a_border_hover": "#717171",
"menu_a_color": "#3873ad",
}
)

View File

@ -2,22 +2,8 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
--> $DIR/type-checking-test-1.rs:19:13
|
LL | let _ = x as &dyn Bar<_>; // Ambiguous
| ^^^^^^^^^^^^^^^^ invalid cast
|
help: consider borrowing the value
|
LL | let _ = &x as &dyn Bar<_>; // Ambiguous
| +
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
--> $DIR/type-checking-test-1.rs:19:13
|
LL | let _ = x as &dyn Bar<_>; // Ambiguous
| ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
|
= note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>`
error: aborting due to previous error
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0277, E0605.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0605`.

View File

@ -18,7 +18,6 @@ fn test_specific(x: &dyn Foo) {
fn test_unknown_version(x: &dyn Foo) {
let _ = x as &dyn Bar<_>; // Ambiguous
//~^ ERROR non-primitive cast
//[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
}
fn test_infer_version(x: &dyn Foo) {

View File

@ -18,13 +18,11 @@ fn test_specific2(x: &dyn Foo<u32>) {
fn test_specific3(x: &dyn Foo<i32>) {
let _ = x as &dyn Bar<u32>; // Error
//~^ ERROR non-primitive cast
//~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
}
fn test_infer_arg(x: &dyn Foo<u32>) {
let a = x as &dyn Bar<_>; // Ambiguous
//~^ ERROR non-primitive cast
//~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
let _ = a.bar();
}

View File

@ -2,41 +2,14 @@ error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
--> $DIR/type-checking-test-2.rs:19:13
|
LL | let _ = x as &dyn Bar<u32>; // Error
| ^^^^^^^^^^^^^^^^^^ invalid cast
|
help: consider borrowing the value
|
LL | let _ = &x as &dyn Bar<u32>; // Error
| +
error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
--> $DIR/type-checking-test-2.rs:19:13
|
LL | let _ = x as &dyn Bar<u32>; // Error
| ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
|
= note: required for the cast from `&&dyn Foo<i32>` to `&dyn Bar<u32>`
| ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
--> $DIR/type-checking-test-2.rs:25:13
--> $DIR/type-checking-test-2.rs:24:13
|
LL | let a = x as &dyn Bar<_>; // Ambiguous
| ^^^^^^^^^^^^^^^^ invalid cast
|
help: consider borrowing the value
|
LL | let a = &x as &dyn Bar<_>; // Ambiguous
| +
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
--> $DIR/type-checking-test-2.rs:25:13
|
LL | let a = x as &dyn Bar<_>; // Ambiguous
| ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
|
= note: required for the cast from `&&dyn Foo<u32>` to `&dyn Bar<_>`
error: aborting due to 2 previous errors
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0605.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0605`.