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:
commit
b6ab01a713
@ -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),
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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<()> {
|
||||
|
@ -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<()> {
|
||||
|
@ -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<()> {
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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",
|
||||
}
|
||||
)
|
||||
|
@ -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`.
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user