mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #119578 - matthiaskrgr:rollup-42yizmx, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #117636 (add test for #117626) - #118704 (Promote `riscv32{im|imafc}` targets to tier 2) - #119184 (Switch from using `//~ERROR` annotations with `--error-format` to `error-pattern`) - #119325 (custom mir: make it clear what the return block is) - #119391 (Use Result::flatten in catch_with_exit_code) - #119431 (Support reg_addr register class in s390x inline assembly) - #119475 (Remove libtest's dylib) - #119532 (Make offset_of field parsing use metavariable which handles any spacing) - #119553 (stop feed vis when cant access for trait item) - #119574 (Miri subtree update) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4c5ce1f0d5
@ -634,6 +634,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
|
||||
}
|
||||
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::Err => unreachable!(),
|
||||
}
|
||||
@ -704,7 +705,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
|
||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||
bug!("LLVM backend does not support SPIR-V")
|
||||
},
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::S390x(
|
||||
S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr
|
||||
) => cx.type_i32(),
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
|
||||
InlineAsmRegClass::Err => unreachable!(),
|
||||
}
|
||||
|
@ -690,6 +690,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
|
||||
@ -867,7 +868,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(),
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(),
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(),
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::S390x(
|
||||
S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr,
|
||||
) => cx.type_i32(),
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
|
||||
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
|
@ -12,6 +12,7 @@
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(panic_update_hook)]
|
||||
#![feature(result_flattening)]
|
||||
#![recursion_limit = "256"]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
@ -1249,8 +1250,7 @@ pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuarantee
|
||||
/// Variant of `catch_fatal_errors` for the `interface::Result` return type
|
||||
/// that also computes the exit code.
|
||||
pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
|
||||
let result = catch_fatal_errors(f).and_then(|result| result);
|
||||
match result {
|
||||
match catch_fatal_errors(f).flatten() {
|
||||
Ok(()) => EXIT_SUCCESS,
|
||||
Err(_) => EXIT_FAILURE,
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
@call(mir_drop, args) => {
|
||||
Ok(TerminatorKind::Drop {
|
||||
place: self.parse_place(args[0])?,
|
||||
target: self.parse_block(args[1])?,
|
||||
target: self.parse_return_to(args[1])?,
|
||||
unwind: self.parse_unwind_action(args[2])?,
|
||||
replace: false,
|
||||
})
|
||||
@ -104,6 +104,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_return_to(&self, expr_id: ExprId) -> PResult<BasicBlock> {
|
||||
parse_by_kind!(self, expr_id, _, "return block",
|
||||
@call(mir_return_to, args) => {
|
||||
self.parse_block(args[0])
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
|
||||
let Some((otherwise, rest)) = arms.split_last() else {
|
||||
return Err(ParseError {
|
||||
@ -146,7 +154,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
ExprKind::Assign { lhs, rhs } => (*lhs, *rhs),
|
||||
);
|
||||
let destination = self.parse_place(destination)?;
|
||||
let target = self.parse_block(args[1])?;
|
||||
let target = self.parse_return_to(args[1])?;
|
||||
let unwind = self.parse_unwind_action(args[2])?;
|
||||
|
||||
parse_by_kind!(self, call, _, "function call",
|
||||
|
@ -10,6 +10,8 @@ parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretat
|
||||
parse_array_brackets_instead_of_braces = this is a block expression, not an array
|
||||
.suggestion = to make an array, use square brackets instead of curly braces
|
||||
|
||||
parse_array_index_offset_of = array indexing not supported in offset_of
|
||||
|
||||
parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
|
||||
|
||||
parse_assoc_lifetime = associated lifetimes are not supported
|
||||
@ -405,6 +407,8 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
|
||||
|
||||
parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
|
||||
|
||||
parse_invalid_offset_of = offset_of expects dot-separated field and variant names
|
||||
|
||||
parse_invalid_unicode_escape = invalid unicode character escape
|
||||
.label = invalid escape
|
||||
.help = unicode escape must {$surrogate ->
|
||||
|
@ -2887,3 +2887,11 @@ pub(crate) struct TransposeDynOrImplSugg<'a> {
|
||||
pub insertion_span: Span,
|
||||
pub kw: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_array_index_offset_of)]
|
||||
pub(crate) struct ArrayIndexInOffsetOf(#[primary_span] pub Span);
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_invalid_offset_of)]
|
||||
pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span);
|
||||
|
@ -1023,7 +1023,7 @@ impl<'a> Parser<'a> {
|
||||
// we should break everything including floats into more basic proc-macro style
|
||||
// tokens in the lexer (probably preferable).
|
||||
// See also `TokenKind::break_two_token_op` which does similar splitting of `>>` into `>`.
|
||||
fn break_up_float(&mut self, float: Symbol) -> DestructuredFloat {
|
||||
fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
|
||||
#[derive(Debug)]
|
||||
enum FloatComponent {
|
||||
IdentLike(String),
|
||||
@ -1053,7 +1053,6 @@ impl<'a> Parser<'a> {
|
||||
// With proc macros the span can refer to anything, the source may be too short,
|
||||
// or too long, or non-ASCII. It only makes sense to break our span into components
|
||||
// if its underlying text is identical to our float literal.
|
||||
let span = self.token.span;
|
||||
let can_take_span_apart =
|
||||
|| self.span_to_snippet(span).as_deref() == Ok(float_str).as_deref();
|
||||
|
||||
@ -1115,7 +1114,7 @@ impl<'a> Parser<'a> {
|
||||
float: Symbol,
|
||||
suffix: Option<Symbol>,
|
||||
) -> P<Expr> {
|
||||
match self.break_up_float(float) {
|
||||
match self.break_up_float(float, self.token.span) {
|
||||
// 1e2
|
||||
DestructuredFloat::Single(sym, _sp) => {
|
||||
self.parse_expr_tuple_field_access(lo, base, sym, suffix, None)
|
||||
@ -1143,40 +1142,105 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_field_name_maybe_tuple(&mut self) -> PResult<'a, ThinVec<Ident>> {
|
||||
let token::Literal(token::Lit { kind: token::Float, symbol, suffix }) = self.token.kind
|
||||
else {
|
||||
return Ok(thin_vec![self.parse_field_name()?]);
|
||||
};
|
||||
Ok(match self.break_up_float(symbol) {
|
||||
// 1e2
|
||||
DestructuredFloat::Single(sym, sp) => {
|
||||
self.bump();
|
||||
thin_vec![Ident::new(sym, sp)]
|
||||
/// Parse the field access used in offset_of, matched by `$(e:expr)+`.
|
||||
/// Currently returns a list of idents. However, it should be possible in
|
||||
/// future to also do array indices, which might be arbitrary expressions.
|
||||
fn parse_floating_field_access(&mut self) -> PResult<'a, P<[Ident]>> {
|
||||
let mut fields = Vec::new();
|
||||
let mut trailing_dot = None;
|
||||
|
||||
loop {
|
||||
// This is expected to use a metavariable $(args:expr)+, but the builtin syntax
|
||||
// could be called directly. Calling `parse_expr` allows this function to only
|
||||
// consider `Expr`s.
|
||||
let expr = self.parse_expr()?;
|
||||
let mut current = &expr;
|
||||
let start_idx = fields.len();
|
||||
loop {
|
||||
match current.kind {
|
||||
ExprKind::Field(ref left, right) => {
|
||||
// Field access is read right-to-left.
|
||||
fields.insert(start_idx, right);
|
||||
trailing_dot = None;
|
||||
current = left;
|
||||
}
|
||||
// Parse this both to give helpful error messages and to
|
||||
// verify it can be done with this parser setup.
|
||||
ExprKind::Index(ref left, ref _right, span) => {
|
||||
self.dcx().emit_err(errors::ArrayIndexInOffsetOf(span));
|
||||
current = left;
|
||||
}
|
||||
ExprKind::Lit(token::Lit {
|
||||
kind: token::Float | token::Integer,
|
||||
symbol,
|
||||
suffix,
|
||||
}) => {
|
||||
if let Some(suffix) = suffix {
|
||||
self.expect_no_tuple_index_suffix(current.span, suffix);
|
||||
}
|
||||
match self.break_up_float(symbol, current.span) {
|
||||
// 1e2
|
||||
DestructuredFloat::Single(sym, sp) => {
|
||||
trailing_dot = None;
|
||||
fields.insert(start_idx, Ident::new(sym, sp));
|
||||
}
|
||||
// 1.
|
||||
DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => {
|
||||
assert!(suffix.is_none());
|
||||
trailing_dot = Some(dot_span);
|
||||
fields.insert(start_idx, Ident::new(sym, sym_span));
|
||||
}
|
||||
// 1.2 | 1.2e3
|
||||
DestructuredFloat::MiddleDot(
|
||||
symbol1,
|
||||
span1,
|
||||
_dot_span,
|
||||
symbol2,
|
||||
span2,
|
||||
) => {
|
||||
trailing_dot = None;
|
||||
fields.insert(start_idx, Ident::new(symbol2, span2));
|
||||
fields.insert(start_idx, Ident::new(symbol1, span1));
|
||||
}
|
||||
DestructuredFloat::Error => {
|
||||
trailing_dot = None;
|
||||
fields.insert(start_idx, Ident::new(symbol, self.prev_token.span));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
ExprKind::Path(None, Path { ref segments, .. }) => {
|
||||
match &segments[..] {
|
||||
[PathSegment { ident, args: None, .. }] => {
|
||||
trailing_dot = None;
|
||||
fields.insert(start_idx, *ident)
|
||||
}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 1.
|
||||
DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => {
|
||||
assert!(suffix.is_none());
|
||||
// Analogous to `Self::break_and_eat`
|
||||
self.break_last_token = true;
|
||||
// This might work, in cases like `1. 2`, and might not,
|
||||
// in cases like `offset_of!(Ty, 1.)`. It depends on what comes
|
||||
// after the float-like token, and therefore we have to make
|
||||
// the other parts of the parser think that there is a dot literal.
|
||||
self.token = Token::new(token::Ident(sym, false), sym_span);
|
||||
self.bump_with((Token::new(token::Dot, dot_span), self.token_spacing));
|
||||
thin_vec![Ident::new(sym, sym_span)]
|
||||
|
||||
if matches!(self.token.kind, token::CloseDelim(..) | token::Comma) {
|
||||
break;
|
||||
} else if trailing_dot.is_none() {
|
||||
// This loop should only repeat if there is a trailing dot.
|
||||
self.dcx().emit_err(errors::InvalidOffsetOf(self.token.span));
|
||||
break;
|
||||
}
|
||||
// 1.2 | 1.2e3
|
||||
DestructuredFloat::MiddleDot(symbol1, ident1_span, _dot_span, symbol2, ident2_span) => {
|
||||
self.bump();
|
||||
thin_vec![Ident::new(symbol1, ident1_span), Ident::new(symbol2, ident2_span)]
|
||||
}
|
||||
DestructuredFloat::Error => {
|
||||
self.bump();
|
||||
thin_vec![Ident::new(symbol, self.prev_token.span)]
|
||||
}
|
||||
})
|
||||
}
|
||||
if let Some(dot) = trailing_dot {
|
||||
self.dcx().emit_err(errors::InvalidOffsetOf(dot));
|
||||
}
|
||||
Ok(fields.into_iter().collect())
|
||||
}
|
||||
|
||||
fn parse_expr_tuple_field_access(
|
||||
@ -1907,15 +1971,29 @@ impl<'a> Parser<'a> {
|
||||
let container = self.parse_ty()?;
|
||||
self.expect(&TokenKind::Comma)?;
|
||||
|
||||
let seq_sep = SeqSep { sep: Some(token::Dot), trailing_sep_allowed: false };
|
||||
let (fields, _trailing, _recovered) = self.parse_seq_to_before_end(
|
||||
&TokenKind::CloseDelim(Delimiter::Parenthesis),
|
||||
seq_sep,
|
||||
Parser::parse_field_name_maybe_tuple,
|
||||
)?;
|
||||
let fields = fields.into_iter().flatten().collect::<Vec<_>>();
|
||||
let fields = self.parse_floating_field_access()?;
|
||||
let trailing_comma = self.eat_noexpect(&TokenKind::Comma);
|
||||
|
||||
if let Err(mut e) =
|
||||
self.expect_one_of(&[], &[TokenKind::CloseDelim(Delimiter::Parenthesis)])
|
||||
{
|
||||
if trailing_comma {
|
||||
e.note("unexpected third argument to offset_of");
|
||||
} else {
|
||||
e.note("offset_of expects dot-separated field and variant names");
|
||||
}
|
||||
e.emit();
|
||||
}
|
||||
|
||||
// Eat tokens until the macro call ends.
|
||||
if self.may_recover() {
|
||||
while !matches!(self.token.kind, token::CloseDelim(..) | token::Eof) {
|
||||
self.bump();
|
||||
}
|
||||
}
|
||||
|
||||
let span = lo.to(self.token.span);
|
||||
Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.into())))
|
||||
Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields)))
|
||||
}
|
||||
|
||||
/// Returns a string literal if the next token is a string literal.
|
||||
|
@ -3076,7 +3076,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||
}
|
||||
|
||||
let feed_visibility = |this: &mut Self, def_id| {
|
||||
let vis = this.r.tcx.visibility(def_id).expect_local();
|
||||
let vis = this.r.tcx.visibility(def_id);
|
||||
let vis = if vis.is_visible_locally() {
|
||||
vis.expect_local()
|
||||
} else {
|
||||
this.r.dcx().span_delayed_bug(
|
||||
span,
|
||||
"error should be emitted when an unexpected trait item is used",
|
||||
);
|
||||
rustc_middle::ty::Visibility::Public
|
||||
};
|
||||
this.r.feed_visibility(this.r.local_def_id(id), vis);
|
||||
};
|
||||
|
||||
|
@ -1041,6 +1041,7 @@ symbols! {
|
||||
mir_offset,
|
||||
mir_retag,
|
||||
mir_return,
|
||||
mir_return_to,
|
||||
mir_set_discriminant,
|
||||
mir_static,
|
||||
mir_static_mut,
|
||||
|
@ -6,6 +6,7 @@ use std::fmt;
|
||||
def_reg_class! {
|
||||
S390x S390xInlineAsmRegClass {
|
||||
reg,
|
||||
reg_addr,
|
||||
freg,
|
||||
}
|
||||
}
|
||||
@ -36,7 +37,7 @@ impl S390xInlineAsmRegClass {
|
||||
arch: InlineAsmArch,
|
||||
) -> &'static [(InlineAsmType, Option<Symbol>)] {
|
||||
match (self, arch) {
|
||||
(Self::reg, _) => types! { _: I8, I16, I32, I64; },
|
||||
(Self::reg | Self::reg_addr, _) => types! { _: I8, I16, I32, I64; },
|
||||
(Self::freg, _) => types! { _: F32, F64; },
|
||||
}
|
||||
}
|
||||
@ -45,19 +46,19 @@ impl S390xInlineAsmRegClass {
|
||||
def_regs! {
|
||||
S390x S390xInlineAsmReg S390xInlineAsmRegClass {
|
||||
r0: reg = ["r0"],
|
||||
r1: reg = ["r1"],
|
||||
r2: reg = ["r2"],
|
||||
r3: reg = ["r3"],
|
||||
r4: reg = ["r4"],
|
||||
r5: reg = ["r5"],
|
||||
r6: reg = ["r6"],
|
||||
r7: reg = ["r7"],
|
||||
r8: reg = ["r8"],
|
||||
r9: reg = ["r9"],
|
||||
r10: reg = ["r10"],
|
||||
r12: reg = ["r12"],
|
||||
r13: reg = ["r13"],
|
||||
r14: reg = ["r14"],
|
||||
r1: reg, reg_addr = ["r1"],
|
||||
r2: reg, reg_addr = ["r2"],
|
||||
r3: reg, reg_addr = ["r3"],
|
||||
r4: reg, reg_addr = ["r4"],
|
||||
r5: reg, reg_addr = ["r5"],
|
||||
r6: reg, reg_addr = ["r6"],
|
||||
r7: reg, reg_addr = ["r7"],
|
||||
r8: reg, reg_addr = ["r8"],
|
||||
r9: reg, reg_addr = ["r9"],
|
||||
r10: reg, reg_addr = ["r10"],
|
||||
r12: reg, reg_addr = ["r12"],
|
||||
r13: reg, reg_addr = ["r13"],
|
||||
r14: reg, reg_addr = ["r14"],
|
||||
f0: freg = ["f0"],
|
||||
f1: freg = ["f1"],
|
||||
f2: freg = ["f2"],
|
||||
|
@ -104,21 +104,22 @@
|
||||
//! }
|
||||
//!
|
||||
//! #[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 popped;
|
||||
//!
|
||||
//! {
|
||||
//! Call(_unused = Vec::push(v, value), pop, UnwindContinue())
|
||||
//! Call(_unused = Vec::push(v, value), ReturnTo(pop), UnwindContinue())
|
||||
//! }
|
||||
//!
|
||||
//! pop = {
|
||||
//! Call(popped = Vec::pop(v), drop, UnwindContinue())
|
||||
//! Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue())
|
||||
//! }
|
||||
//!
|
||||
//! drop = {
|
||||
//! Drop(popped, ret, UnwindContinue())
|
||||
//! Drop(popped, ReturnTo(ret), UnwindContinue())
|
||||
//! }
|
||||
//!
|
||||
//! ret = {
|
||||
@ -242,9 +243,8 @@
|
||||
//! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
|
||||
//! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
|
||||
//! otherwise branch.
|
||||
//! - [`Call`] has an associated function as well. The third argument of this function is a normal
|
||||
//! function call expression, for example `my_other_function(a, 5)`.
|
||||
//!
|
||||
//! - [`Call`] has an associated function as well, with special syntax:
|
||||
//! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
|
||||
|
||||
#![unstable(
|
||||
feature = "custom_mir",
|
||||
@ -287,35 +287,68 @@ macro_rules! define {
|
||||
}
|
||||
|
||||
// Unwind actions
|
||||
pub struct UnwindActionArg;
|
||||
define!(
|
||||
"mir_unwind_continue",
|
||||
/// An unwind action that continues unwinding.
|
||||
fn UnwindContinue()
|
||||
fn UnwindContinue() -> UnwindActionArg
|
||||
);
|
||||
define!(
|
||||
"mir_unwind_unreachable",
|
||||
/// An unwind action that triggers undefined behaviour.
|
||||
fn UnwindUnreachable() -> BasicBlock
|
||||
fn UnwindUnreachable() -> UnwindActionArg
|
||||
);
|
||||
define!(
|
||||
"mir_unwind_terminate",
|
||||
/// An unwind action that terminates the execution.
|
||||
///
|
||||
/// `UnwindTerminate` can also be used as a terminator.
|
||||
fn UnwindTerminate(reason: UnwindTerminateReason)
|
||||
fn UnwindTerminate(reason: UnwindTerminateReason) -> UnwindActionArg
|
||||
);
|
||||
define!(
|
||||
"mir_unwind_cleanup",
|
||||
/// An unwind action that continues execution in a given basic blok.
|
||||
fn UnwindCleanup(goto: BasicBlock)
|
||||
fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg
|
||||
);
|
||||
|
||||
// Return destination for `Call`
|
||||
pub struct ReturnToArg;
|
||||
define!("mir_return_to", fn ReturnTo(goto: BasicBlock) -> ReturnToArg);
|
||||
|
||||
// Terminators
|
||||
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, U>(place: T, goto: BasicBlock, unwind_action: U));
|
||||
define!("mir_call", fn Call<U>(call: (), goto: BasicBlock, unwind_action: U));
|
||||
define!("mir_drop",
|
||||
/// Drop the contents of a place.
|
||||
///
|
||||
/// The first argument must be a place.
|
||||
///
|
||||
/// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
|
||||
/// will be jumped to after the destructor returns.
|
||||
///
|
||||
/// The third argument describes what happens on unwind. It can be one of:
|
||||
/// - [`UnwindContinue`]
|
||||
/// - [`UnwindUnreachable`]
|
||||
/// - [`UnwindTerminate`]
|
||||
/// - [`UnwindCleanup`]
|
||||
fn Drop<T>(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg)
|
||||
);
|
||||
define!("mir_call",
|
||||
/// Call a function.
|
||||
///
|
||||
/// The first argument must be of the form `ret_val = fun(arg1, arg2, ...)`.
|
||||
///
|
||||
/// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
|
||||
/// will be jumped to after the function returns.
|
||||
///
|
||||
/// The third argument describes what happens on unwind. It can be one of:
|
||||
/// - [`UnwindContinue`]
|
||||
/// - [`UnwindUnreachable`]
|
||||
/// - [`UnwindTerminate`]
|
||||
/// - [`UnwindCleanup`]
|
||||
fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg)
|
||||
);
|
||||
define!("mir_unwind_resume",
|
||||
/// A terminator that resumes the unwinding.
|
||||
fn UnwindResume()
|
||||
|
@ -1395,8 +1395,18 @@ impl<T> SizedTypeProperties for T {}
|
||||
///
|
||||
/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
|
||||
/// ```
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "offset_of", issue = "106655")]
|
||||
#[allow_internal_unstable(builtin_syntax, hint_must_use)]
|
||||
pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) {
|
||||
// The `{}` is for better error messages
|
||||
crate::hint::must_use({builtin # offset_of($Container, $($fields)+)})
|
||||
}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[unstable(feature = "offset_of", issue = "106655")]
|
||||
#[allow_internal_unstable(builtin_syntax, hint_must_use)]
|
||||
#[allow(missing_docs)]
|
||||
pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) {
|
||||
// The `{}` is for better error messages
|
||||
crate::hint::must_use({builtin # offset_of($Container, $($fields).+)})
|
||||
|
@ -3,9 +3,6 @@ name = "test"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["dylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
|
||||
std = { path = "../std" }
|
||||
|
@ -161,7 +161,9 @@ target | std | notes
|
||||
[`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
|
||||
[`riscv32imac-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA)
|
||||
[`riscv32i-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32I ISA)
|
||||
[`riscv32im-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | | Bare RISC-V (RV32IM ISA)
|
||||
[`riscv32imc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA)
|
||||
[`riscv32imafc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
|
||||
`riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
|
||||
`riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
|
||||
`sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)
|
||||
@ -318,8 +320,6 @@ target | std | host | notes
|
||||
[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer)
|
||||
`riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33)
|
||||
`riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
|
||||
[`riscv32imafc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
|
||||
[`riscv32im-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | | Bare RISC-V (RV32IM ISA)
|
||||
[`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA)
|
||||
[`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
|
||||
[`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
|
||||
|
@ -1,6 +1,6 @@
|
||||
# `riscv32{i,im,imc,imac,imafc}-unknown-none-elf`
|
||||
|
||||
**Tier: 2/3**
|
||||
**Tier: 2**
|
||||
|
||||
Bare-metal target for RISC-V CPUs with the RV32I, RV32IM, RV32IMC, RV32IMAFC and RV32IMAC ISAs.
|
||||
|
||||
@ -24,11 +24,11 @@ This target is included in Rust and can be installed via `rustup`.
|
||||
|
||||
## Testing
|
||||
|
||||
This is a cross-compiled no-std target, which must be run either in a simulator
|
||||
This is a cross-compiled `no-std` target, which must be run either in a simulator
|
||||
or by programming them onto suitable hardware. It is not possible to run the
|
||||
Rust testsuite on this target.
|
||||
Rust test-suite on this target.
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
|
||||
This target supports C code. If interlinking with C or C++, you may need to use
|
||||
riscv64-unknown-elf-gcc as a linker instead of rust-lld.
|
||||
`riscv64-unknown-elf-gcc` as a linker instead of `rust-lld`.
|
||||
|
@ -84,7 +84,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
||||
| M68k | `reg_data` | None | `i8`, `i16`, `i32` |
|
||||
| CSKY | `reg` | None | `i8`, `i16`, `i32` |
|
||||
| CSKY | `freg` | None | `f32`, |
|
||||
| s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` |
|
||||
| s390x | `reg`, `reg_addr` | None | `i8`, `i16`, `i32`, `i64` |
|
||||
| s390x | `freg` | None | `f32`, `f64` |
|
||||
|
||||
## Register aliases
|
||||
@ -158,9 +158,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
||||
| NVPTX | `reg64` | None | `rd0` | None |
|
||||
| Hexagon | `reg` | None | `r0` | None |
|
||||
| PowerPC | `reg` | None | `0` | None |
|
||||
| PowerPC | `reg_nonzero` | None | `3` | `b` |
|
||||
| PowerPC | `reg_nonzero` | None | `3` | None |
|
||||
| PowerPC | `freg` | None | `0` | None |
|
||||
| s390x | `reg` | None | `%r0` | None |
|
||||
| s390x | `reg_addr` | None | `%r1` | None |
|
||||
| s390x | `freg` | None | `%f0` | None |
|
||||
| CSKY | `reg` | None | `r0` | None |
|
||||
| CSKY | `freg` | None | `f0` | None |
|
||||
|
@ -11,7 +11,7 @@ use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use tracing::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ErrorKind {
|
||||
Help,
|
||||
Error,
|
||||
|
@ -3977,23 +3977,29 @@ impl<'test> TestCx<'test> {
|
||||
proc_res.status,
|
||||
self.props.error_patterns
|
||||
);
|
||||
|
||||
let check_patterns = should_run == WillExecute::No
|
||||
&& (!self.props.error_patterns.is_empty()
|
||||
|| !self.props.regex_error_patterns.is_empty());
|
||||
if !explicit && self.config.compare_mode.is_none() {
|
||||
let check_patterns = should_run == WillExecute::No
|
||||
&& (!self.props.error_patterns.is_empty()
|
||||
|| !self.props.regex_error_patterns.is_empty());
|
||||
|
||||
let check_annotations = !check_patterns || !expected_errors.is_empty();
|
||||
|
||||
if check_patterns {
|
||||
// "// error-pattern" comments
|
||||
let output_to_check = self.get_output(&proc_res);
|
||||
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
|
||||
}
|
||||
|
||||
if check_annotations {
|
||||
// "//~ERROR comments"
|
||||
self.check_expected_errors(expected_errors, &proc_res);
|
||||
}
|
||||
} else if explicit && !expected_errors.is_empty() {
|
||||
let msg = format!(
|
||||
"line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead",
|
||||
expected_errors[0].line_num,
|
||||
expected_errors[0].kind.unwrap_or(ErrorKind::Error),
|
||||
);
|
||||
self.fatal(&msg);
|
||||
}
|
||||
if check_patterns {
|
||||
// "// error-pattern" comments
|
||||
let output_to_check = self.get_output(&proc_res);
|
||||
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
|
||||
}
|
||||
|
||||
if self.props.run_rustfix && self.config.compare_mode.is_none() {
|
||||
|
@ -6,6 +6,7 @@ use std::time::Duration;
|
||||
use log::trace;
|
||||
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_hir::def::{DefKind, Namespace};
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use rustc_index::IndexVec;
|
||||
@ -117,6 +118,50 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a softfloat type to its corresponding hostfloat type.
|
||||
pub trait ToHost {
|
||||
type HostFloat;
|
||||
fn to_host(self) -> Self::HostFloat;
|
||||
}
|
||||
|
||||
/// Convert a hostfloat type to its corresponding softfloat type.
|
||||
pub trait ToSoft {
|
||||
type SoftFloat;
|
||||
fn to_soft(self) -> Self::SoftFloat;
|
||||
}
|
||||
|
||||
impl ToHost for rustc_apfloat::ieee::Double {
|
||||
type HostFloat = f64;
|
||||
|
||||
fn to_host(self) -> Self::HostFloat {
|
||||
f64::from_bits(self.to_bits().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSoft for f64 {
|
||||
type SoftFloat = rustc_apfloat::ieee::Double;
|
||||
|
||||
fn to_soft(self) -> Self::SoftFloat {
|
||||
Float::from_bits(self.to_bits().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToHost for rustc_apfloat::ieee::Single {
|
||||
type HostFloat = f32;
|
||||
|
||||
fn to_host(self) -> Self::HostFloat {
|
||||
f32::from_bits(self.to_bits().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSoft for f32 {
|
||||
type SoftFloat = rustc_apfloat::ieee::Single;
|
||||
|
||||
fn to_soft(self) -> Self::SoftFloat {
|
||||
Float::from_bits(self.to_bits().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
/// Checks if the given crate/module exists.
|
||||
@ -1188,11 +1233,3 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<
|
||||
_ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"),
|
||||
})
|
||||
}
|
||||
|
||||
// This looks like something that would be nice to have in the standard library...
|
||||
pub(crate) fn round_to_next_multiple_of(x: u64, divisor: u64) -> u64 {
|
||||
assert_ne!(divisor, 0);
|
||||
// divisor is nonzero; multiplication cannot overflow since we just divided
|
||||
#[allow(clippy::arithmetic_side_effects)]
|
||||
return (x.checked_add(divisor - 1).unwrap() / divisor) * divisor;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#![feature(round_ties_even)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(lint_reasons)]
|
||||
#![feature(int_roundings)]
|
||||
// Configure clippy and other lints
|
||||
#![allow(
|
||||
clippy::collapsible_else_if,
|
||||
|
@ -118,4 +118,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
nan
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_nan<F1: Float + FloatConvert<F2>, F2: Float>(&self, f: F2, inputs: &[F1]) -> F2 {
|
||||
if f.is_nan() { self.generate_nan(inputs) } else { f }
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ use rustc_target::{
|
||||
|
||||
use super::backtrace::EvalContextExt as _;
|
||||
use crate::*;
|
||||
use helpers::{ToHost, ToSoft};
|
||||
|
||||
/// Type of dynamic symbols (for `dlsym` et al)
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@ -886,23 +887,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
| "tgammaf"
|
||||
=> {
|
||||
let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
|
||||
let f_host = f.to_host();
|
||||
let res = match link_name.as_str() {
|
||||
"cbrtf" => f.cbrt(),
|
||||
"coshf" => f.cosh(),
|
||||
"sinhf" => f.sinh(),
|
||||
"tanf" => f.tan(),
|
||||
"tanhf" => f.tanh(),
|
||||
"acosf" => f.acos(),
|
||||
"asinf" => f.asin(),
|
||||
"atanf" => f.atan(),
|
||||
"log1pf" => f.ln_1p(),
|
||||
"expm1f" => f.exp_m1(),
|
||||
"tgammaf" => f.gamma(),
|
||||
"cbrtf" => f_host.cbrt(),
|
||||
"coshf" => f_host.cosh(),
|
||||
"sinhf" => f_host.sinh(),
|
||||
"tanf" => f_host.tan(),
|
||||
"tanhf" => f_host.tanh(),
|
||||
"acosf" => f_host.acos(),
|
||||
"asinf" => f_host.asin(),
|
||||
"atanf" => f_host.atan(),
|
||||
"log1pf" => f_host.ln_1p(),
|
||||
"expm1f" => f_host.exp_m1(),
|
||||
"tgammaf" => f_host.gamma(),
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
|
||||
let res = res.to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
#[rustfmt::skip]
|
||||
| "_hypotf"
|
||||
@ -911,19 +915,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
| "fdimf"
|
||||
=> {
|
||||
let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f32()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f32()?;
|
||||
// underscore case for windows, here and below
|
||||
// (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
|
||||
// FIXME: Using host floats.
|
||||
let f1 = f32::from_bits(this.read_scalar(f1)?.to_u32()?);
|
||||
let f2 = f32::from_bits(this.read_scalar(f2)?.to_u32()?);
|
||||
let res = match link_name.as_str() {
|
||||
"_hypotf" | "hypotf" => f1.hypot(f2),
|
||||
"atan2f" => f1.atan2(f2),
|
||||
"_hypotf" | "hypotf" => f1.to_host().hypot(f2.to_host()).to_soft(),
|
||||
"atan2f" => f1.to_host().atan2(f2.to_host()).to_soft(),
|
||||
#[allow(deprecated)]
|
||||
"fdimf" => f1.abs_sub(f2),
|
||||
"fdimf" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
#[rustfmt::skip]
|
||||
| "cbrt"
|
||||
@ -939,23 +944,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
| "tgamma"
|
||||
=> {
|
||||
let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
|
||||
let f_host = f.to_host();
|
||||
let res = match link_name.as_str() {
|
||||
"cbrt" => f.cbrt(),
|
||||
"cosh" => f.cosh(),
|
||||
"sinh" => f.sinh(),
|
||||
"tan" => f.tan(),
|
||||
"tanh" => f.tanh(),
|
||||
"acos" => f.acos(),
|
||||
"asin" => f.asin(),
|
||||
"atan" => f.atan(),
|
||||
"log1p" => f.ln_1p(),
|
||||
"expm1" => f.exp_m1(),
|
||||
"tgamma" => f.gamma(),
|
||||
"cbrt" => f_host.cbrt(),
|
||||
"cosh" => f_host.cosh(),
|
||||
"sinh" => f_host.sinh(),
|
||||
"tan" => f_host.tan(),
|
||||
"tanh" => f_host.tanh(),
|
||||
"acos" => f_host.acos(),
|
||||
"asin" => f_host.asin(),
|
||||
"atan" => f_host.atan(),
|
||||
"log1p" => f_host.ln_1p(),
|
||||
"expm1" => f_host.exp_m1(),
|
||||
"tgamma" => f_host.gamma(),
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
|
||||
let res = res.to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
#[rustfmt::skip]
|
||||
| "_hypot"
|
||||
@ -964,17 +972,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
| "fdim"
|
||||
=> {
|
||||
let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f64()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f64()?;
|
||||
// underscore case for windows, here and below
|
||||
// (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
|
||||
// FIXME: Using host floats.
|
||||
let f1 = f64::from_bits(this.read_scalar(f1)?.to_u64()?);
|
||||
let f2 = f64::from_bits(this.read_scalar(f2)?.to_u64()?);
|
||||
let res = match link_name.as_str() {
|
||||
"_hypot" | "hypot" => f1.hypot(f2),
|
||||
"atan2" => f1.atan2(f2),
|
||||
"_hypot" | "hypot" => f1.to_host().hypot(f2.to_host()).to_soft(),
|
||||
"atan2" => f1.to_host().atan2(f2.to_host()).to_soft(),
|
||||
#[allow(deprecated)]
|
||||
"fdim" => f1.abs_sub(f2),
|
||||
"fdim" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
#[rustfmt::skip]
|
||||
| "_ldexp"
|
||||
@ -987,27 +998,30 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let exp = this.read_scalar(exp)?.to_i32()?;
|
||||
|
||||
let res = x.scalbn(exp);
|
||||
this.write_scalar(Scalar::from_f64(res), dest)?;
|
||||
let res = this.adjust_nan(res, &[x]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"lgammaf_r" => {
|
||||
let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
// FIXME: Using host floats.
|
||||
let x = f32::from_bits(this.read_scalar(x)?.to_u32()?);
|
||||
let x = this.read_scalar(x)?.to_f32()?;
|
||||
let signp = this.deref_pointer(signp)?;
|
||||
|
||||
let (res, sign) = x.ln_gamma();
|
||||
// FIXME: Using host floats.
|
||||
let (res, sign) = x.to_host().ln_gamma();
|
||||
this.write_int(sign, &signp)?;
|
||||
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
|
||||
let res = this.adjust_nan(res.to_soft(), &[x]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"lgamma_r" => {
|
||||
let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
// FIXME: Using host floats.
|
||||
let x = f64::from_bits(this.read_scalar(x)?.to_u64()?);
|
||||
let x = this.read_scalar(x)?.to_f64()?;
|
||||
let signp = this.deref_pointer(signp)?;
|
||||
|
||||
let (res, sign) = x.ln_gamma();
|
||||
// FIXME: Using host floats.
|
||||
let (res, sign) = x.to_host().ln_gamma();
|
||||
this.write_int(sign, &signp)?;
|
||||
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
|
||||
let res = this.adjust_nan(res.to_soft(), &[x]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
// LLVM intrinsics
|
||||
|
@ -15,7 +15,7 @@ use rustc_target::abi::Size;
|
||||
|
||||
use crate::*;
|
||||
use atomic::EvalContextExt as _;
|
||||
use helpers::check_arg_count;
|
||||
use helpers::{check_arg_count, ToHost, ToSoft};
|
||||
use simd::EvalContextExt as _;
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
@ -146,12 +146,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let [f] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
// Can be implemented in soft-floats.
|
||||
// This is a "bitwise" operation, so there's no NaN non-determinism.
|
||||
this.write_scalar(Scalar::from_f32(f.abs()), dest)?;
|
||||
}
|
||||
"fabsf64" => {
|
||||
let [f] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
// Can be implemented in soft-floats.
|
||||
// This is a "bitwise" operation, so there's no NaN non-determinism.
|
||||
this.write_scalar(Scalar::from_f64(f.abs()), dest)?;
|
||||
}
|
||||
#[rustfmt::skip]
|
||||
@ -170,25 +172,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
| "rintf32"
|
||||
=> {
|
||||
let [f] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
|
||||
let f = match intrinsic_name {
|
||||
"sinf32" => f.sin(),
|
||||
"cosf32" => f.cos(),
|
||||
"sqrtf32" => f.sqrt(),
|
||||
"expf32" => f.exp(),
|
||||
"exp2f32" => f.exp2(),
|
||||
"logf32" => f.ln(),
|
||||
"log10f32" => f.log10(),
|
||||
"log2f32" => f.log2(),
|
||||
"floorf32" => f.floor(),
|
||||
"ceilf32" => f.ceil(),
|
||||
"truncf32" => f.trunc(),
|
||||
"roundf32" => f.round(),
|
||||
"rintf32" => f.round_ties_even(),
|
||||
let f_host = f.to_host();
|
||||
let res = match intrinsic_name {
|
||||
"sinf32" => f_host.sin(),
|
||||
"cosf32" => f_host.cos(),
|
||||
"sqrtf32" => f_host.sqrt(),
|
||||
"expf32" => f_host.exp(),
|
||||
"exp2f32" => f_host.exp2(),
|
||||
"logf32" => f_host.ln(),
|
||||
"log10f32" => f_host.log10(),
|
||||
"log2f32" => f_host.log2(),
|
||||
"floorf32" => f_host.floor(),
|
||||
"ceilf32" => f_host.ceil(),
|
||||
"truncf32" => f_host.trunc(),
|
||||
"roundf32" => f_host.round(),
|
||||
"rintf32" => f_host.round_ties_even(),
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_u32(f.to_bits()), dest)?;
|
||||
let res = res.to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
@ -207,25 +212,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
| "rintf64"
|
||||
=> {
|
||||
let [f] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
|
||||
let f = match intrinsic_name {
|
||||
"sinf64" => f.sin(),
|
||||
"cosf64" => f.cos(),
|
||||
"sqrtf64" => f.sqrt(),
|
||||
"expf64" => f.exp(),
|
||||
"exp2f64" => f.exp2(),
|
||||
"logf64" => f.ln(),
|
||||
"log10f64" => f.log10(),
|
||||
"log2f64" => f.log2(),
|
||||
"floorf64" => f.floor(),
|
||||
"ceilf64" => f.ceil(),
|
||||
"truncf64" => f.trunc(),
|
||||
"roundf64" => f.round(),
|
||||
"rintf64" => f.round_ties_even(),
|
||||
let f_host = f.to_host();
|
||||
let res = match intrinsic_name {
|
||||
"sinf64" => f_host.sin(),
|
||||
"cosf64" => f_host.cos(),
|
||||
"sqrtf64" => f_host.sqrt(),
|
||||
"expf64" => f_host.exp(),
|
||||
"exp2f64" => f_host.exp2(),
|
||||
"logf64" => f_host.ln(),
|
||||
"log10f64" => f_host.log10(),
|
||||
"log2f64" => f_host.log2(),
|
||||
"floorf64" => f_host.floor(),
|
||||
"ceilf64" => f_host.ceil(),
|
||||
"truncf64" => f_host.trunc(),
|
||||
"roundf64" => f_host.round(),
|
||||
"rintf64" => f_host.round_ties_even(),
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?;
|
||||
let res = res.to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
@ -268,7 +276,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
this.binop_ignore_overflow(op, &a, &b, dest)?;
|
||||
let res = this.wrapping_binary_op(op, &a, &b)?;
|
||||
if !float_finite(&res)? {
|
||||
throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result");
|
||||
}
|
||||
// This cannot be a NaN so we also don't have to apply any non-determinism.
|
||||
// (Also, `wrapping_binary_op` already called `generate_nan` if needed.)
|
||||
this.write_immediate(*res, dest)?;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
@ -280,9 +294,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let a = this.read_scalar(a)?.to_f32()?;
|
||||
let b = this.read_scalar(b)?.to_f32()?;
|
||||
let res = match intrinsic_name {
|
||||
"minnumf32" => a.min(b),
|
||||
"maxnumf32" => a.max(b),
|
||||
"copysignf32" => a.copy_sign(b),
|
||||
"minnumf32" => this.adjust_nan(a.min(b), &[a, b]),
|
||||
"maxnumf32" => this.adjust_nan(a.max(b), &[a, b]),
|
||||
"copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_f32(res), dest)?;
|
||||
@ -297,68 +311,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let a = this.read_scalar(a)?.to_f64()?;
|
||||
let b = this.read_scalar(b)?.to_f64()?;
|
||||
let res = match intrinsic_name {
|
||||
"minnumf64" => a.min(b),
|
||||
"maxnumf64" => a.max(b),
|
||||
"copysignf64" => a.copy_sign(b),
|
||||
"minnumf64" => this.adjust_nan(a.min(b), &[a, b]),
|
||||
"maxnumf64" => this.adjust_nan(a.max(b), &[a, b]),
|
||||
"copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_f64(res), dest)?;
|
||||
}
|
||||
|
||||
"powf32" => {
|
||||
let [f, f2] = check_arg_count(args)?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
|
||||
let f2 = f32::from_bits(this.read_scalar(f2)?.to_u32()?);
|
||||
let res = f.powf(f2);
|
||||
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
|
||||
}
|
||||
|
||||
"powf64" => {
|
||||
let [f, f2] = check_arg_count(args)?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
|
||||
let f2 = f64::from_bits(this.read_scalar(f2)?.to_u64()?);
|
||||
let res = f.powf(f2);
|
||||
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
|
||||
}
|
||||
|
||||
"fmaf32" => {
|
||||
let [a, b, c] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f32()?;
|
||||
let b = this.read_scalar(b)?.to_f32()?;
|
||||
let c = this.read_scalar(c)?.to_f32()?;
|
||||
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
|
||||
let a = f32::from_bits(this.read_scalar(a)?.to_u32()?);
|
||||
let b = f32::from_bits(this.read_scalar(b)?.to_u32()?);
|
||||
let c = f32::from_bits(this.read_scalar(c)?.to_u32()?);
|
||||
let res = a.mul_add(b, c);
|
||||
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"fmaf64" => {
|
||||
let [a, b, c] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f64()?;
|
||||
let b = this.read_scalar(b)?.to_f64()?;
|
||||
let c = this.read_scalar(c)?.to_f64()?;
|
||||
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
|
||||
let a = f64::from_bits(this.read_scalar(a)?.to_u64()?);
|
||||
let b = f64::from_bits(this.read_scalar(b)?.to_u64()?);
|
||||
let c = f64::from_bits(this.read_scalar(c)?.to_u64()?);
|
||||
let res = a.mul_add(b, c);
|
||||
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powf32" => {
|
||||
let [f1, f2] = check_arg_count(args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f32()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f32()?;
|
||||
// FIXME: Using host floats.
|
||||
let res = f1.to_host().powf(f2.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powf64" => {
|
||||
let [f1, f2] = check_arg_count(args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f64()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f64()?;
|
||||
// FIXME: Using host floats.
|
||||
let res = f1.to_host().powf(f2.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powif32" => {
|
||||
let [f, i] = check_arg_count(args)?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
let i = this.read_scalar(i)?.to_i32()?;
|
||||
let res = f.powi(i);
|
||||
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
|
||||
// FIXME: Using host floats.
|
||||
let res = f.to_host().powi(i).to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powif64" => {
|
||||
let [f, i] = check_arg_count(args)?;
|
||||
// FIXME: Using host floats.
|
||||
let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
let i = this.read_scalar(i)?.to_i32()?;
|
||||
let res = f.powi(i);
|
||||
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
|
||||
// FIXME: Using host floats.
|
||||
let res = f.to_host().powi(i).to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"float_to_int_unchecked" => {
|
||||
|
@ -4,11 +4,15 @@ use rustc_middle::{mir, ty, ty::FloatTy};
|
||||
use rustc_span::{sym, Symbol};
|
||||
use rustc_target::abi::{Endian, HasDataLayout};
|
||||
|
||||
use crate::helpers::{
|
||||
bool_to_simd_element, check_arg_count, round_to_next_multiple_of, simd_element_to_bool,
|
||||
};
|
||||
use crate::helpers::{bool_to_simd_element, check_arg_count, simd_element_to_bool, ToHost, ToSoft};
|
||||
use crate::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) enum MinMax {
|
||||
Min,
|
||||
Max,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
/// Calls the simd intrinsic `intrinsic`; the `simd_` prefix has already been removed.
|
||||
@ -67,13 +71,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let op = this.read_immediate(&this.project_index(&op, i)?)?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
let val = match which {
|
||||
Op::MirOp(mir_op) => this.wrapping_unary_op(mir_op, &op)?.to_scalar(),
|
||||
Op::MirOp(mir_op) => {
|
||||
// This already does NaN adjustments
|
||||
this.wrapping_unary_op(mir_op, &op)?.to_scalar()
|
||||
}
|
||||
Op::Abs => {
|
||||
// Works for f32 and f64.
|
||||
let ty::Float(float_ty) = op.layout.ty.kind() else {
|
||||
span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
|
||||
};
|
||||
let op = op.to_scalar();
|
||||
// "Bitwise" operation, no NaN adjustments
|
||||
match float_ty {
|
||||
FloatTy::F32 => Scalar::from_f32(op.to_f32()?.abs()),
|
||||
FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()),
|
||||
@ -86,14 +94,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
// FIXME using host floats
|
||||
match float_ty {
|
||||
FloatTy::F32 => {
|
||||
let f = f32::from_bits(op.to_scalar().to_u32()?);
|
||||
let res = f.sqrt();
|
||||
Scalar::from_u32(res.to_bits())
|
||||
let f = op.to_scalar().to_f32()?;
|
||||
let res = f.to_host().sqrt().to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
let f = f64::from_bits(op.to_scalar().to_u64()?);
|
||||
let res = f.sqrt();
|
||||
Scalar::from_u64(res.to_bits())
|
||||
let f = op.to_scalar().to_f64()?;
|
||||
let res = f.to_host().sqrt().to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,11 +115,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
FloatTy::F32 => {
|
||||
let f = op.to_scalar().to_f32()?;
|
||||
let res = f.round_to_integral(rounding).value;
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from_f32(res)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
let f = op.to_scalar().to_f64()?;
|
||||
let res = f.round_to_integral(rounding).value;
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from_f64(res)
|
||||
}
|
||||
}
|
||||
@ -157,8 +169,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
enum Op {
|
||||
MirOp(BinOp),
|
||||
SaturatingOp(BinOp),
|
||||
FMax,
|
||||
FMin,
|
||||
FMinMax(MinMax),
|
||||
WrappingOffset,
|
||||
}
|
||||
let which = match intrinsic_name {
|
||||
@ -178,8 +189,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
"le" => Op::MirOp(BinOp::Le),
|
||||
"gt" => Op::MirOp(BinOp::Gt),
|
||||
"ge" => Op::MirOp(BinOp::Ge),
|
||||
"fmax" => Op::FMax,
|
||||
"fmin" => Op::FMin,
|
||||
"fmax" => Op::FMinMax(MinMax::Max),
|
||||
"fmin" => Op::FMinMax(MinMax::Min),
|
||||
"saturating_add" => Op::SaturatingOp(BinOp::Add),
|
||||
"saturating_sub" => Op::SaturatingOp(BinOp::Sub),
|
||||
"arith_offset" => Op::WrappingOffset,
|
||||
@ -192,6 +203,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
let val = match which {
|
||||
Op::MirOp(mir_op) => {
|
||||
// This does NaN adjustments.
|
||||
let (val, overflowed) = this.overflowing_binary_op(mir_op, &left, &right)?;
|
||||
if matches!(mir_op, BinOp::Shl | BinOp::Shr) {
|
||||
// Shifts have extra UB as SIMD operations that the MIR binop does not have.
|
||||
@ -225,11 +237,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let offset_ptr = ptr.wrapping_signed_offset(offset_bytes, this);
|
||||
Scalar::from_maybe_pointer(offset_ptr, this)
|
||||
}
|
||||
Op::FMax => {
|
||||
fmax_op(&left, &right)?
|
||||
}
|
||||
Op::FMin => {
|
||||
fmin_op(&left, &right)?
|
||||
Op::FMinMax(op) => {
|
||||
this.fminmax_op(op, &left, &right)?
|
||||
}
|
||||
};
|
||||
this.write_scalar(val, &dest)?;
|
||||
@ -259,18 +268,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
};
|
||||
let val = match float_ty {
|
||||
FloatTy::F32 => {
|
||||
let a = f32::from_bits(a.to_u32()?);
|
||||
let b = f32::from_bits(b.to_u32()?);
|
||||
let c = f32::from_bits(c.to_u32()?);
|
||||
let res = a.mul_add(b, c);
|
||||
Scalar::from_u32(res.to_bits())
|
||||
let a = a.to_f32()?;
|
||||
let b = b.to_f32()?;
|
||||
let c = c.to_f32()?;
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
let a = f64::from_bits(a.to_u64()?);
|
||||
let b = f64::from_bits(b.to_u64()?);
|
||||
let c = f64::from_bits(c.to_u64()?);
|
||||
let res = a.mul_add(b, c);
|
||||
Scalar::from_u64(res.to_bits())
|
||||
let a = a.to_f64()?;
|
||||
let b = b.to_f64()?;
|
||||
let c = c.to_f64()?;
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
};
|
||||
this.write_scalar(val, &dest)?;
|
||||
@ -295,8 +306,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
enum Op {
|
||||
MirOp(BinOp),
|
||||
MirOpBool(BinOp),
|
||||
Max,
|
||||
Min,
|
||||
MinMax(MinMax),
|
||||
}
|
||||
let which = match intrinsic_name {
|
||||
"reduce_and" => Op::MirOp(BinOp::BitAnd),
|
||||
@ -304,8 +314,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
"reduce_xor" => Op::MirOp(BinOp::BitXor),
|
||||
"reduce_any" => Op::MirOpBool(BinOp::BitOr),
|
||||
"reduce_all" => Op::MirOpBool(BinOp::BitAnd),
|
||||
"reduce_max" => Op::Max,
|
||||
"reduce_min" => Op::Min,
|
||||
"reduce_max" => Op::MinMax(MinMax::Max),
|
||||
"reduce_min" => Op::MinMax(MinMax::Min),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@ -325,24 +335,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let op = imm_from_bool(simd_element_to_bool(op)?);
|
||||
this.wrapping_binary_op(mir_op, &res, &op)?
|
||||
}
|
||||
Op::Max => {
|
||||
Op::MinMax(mmop) => {
|
||||
if matches!(res.layout.ty.kind(), ty::Float(_)) {
|
||||
ImmTy::from_scalar(fmax_op(&res, &op)?, res.layout)
|
||||
ImmTy::from_scalar(this.fminmax_op(mmop, &res, &op)?, res.layout)
|
||||
} else {
|
||||
// Just boring integers, so NaNs to worry about
|
||||
if this.wrapping_binary_op(BinOp::Ge, &res, &op)?.to_scalar().to_bool()? {
|
||||
res
|
||||
} else {
|
||||
op
|
||||
}
|
||||
}
|
||||
}
|
||||
Op::Min => {
|
||||
if matches!(res.layout.ty.kind(), ty::Float(_)) {
|
||||
ImmTy::from_scalar(fmin_op(&res, &op)?, res.layout)
|
||||
} else {
|
||||
// Just boring integers, so NaNs to worry about
|
||||
if this.wrapping_binary_op(BinOp::Le, &res, &op)?.to_scalar().to_bool()? {
|
||||
let mirop = match mmop {
|
||||
MinMax::Min => BinOp::Le,
|
||||
MinMax::Max => BinOp::Ge,
|
||||
};
|
||||
if this.wrapping_binary_op(mirop, &res, &op)?.to_scalar().to_bool()? {
|
||||
res
|
||||
} else {
|
||||
op
|
||||
@ -402,7 +404,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let (yes, yes_len) = this.operand_to_simd(yes)?;
|
||||
let (no, no_len) = this.operand_to_simd(no)?;
|
||||
let (dest, dest_len) = this.place_to_simd(dest)?;
|
||||
let bitmask_len = round_to_next_multiple_of(dest_len, 8);
|
||||
let bitmask_len = dest_len.next_multiple_of(8);
|
||||
|
||||
// The mask must be an integer or an array.
|
||||
assert!(
|
||||
@ -448,7 +450,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
"bitmask" => {
|
||||
let [op] = check_arg_count(args)?;
|
||||
let (op, op_len) = this.operand_to_simd(op)?;
|
||||
let bitmask_len = round_to_next_multiple_of(op_len, 8);
|
||||
let bitmask_len = op_len.next_multiple_of(8);
|
||||
|
||||
// Returns either an unsigned integer or array of `u8`.
|
||||
assert!(
|
||||
@ -709,6 +711,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fminmax_op(
|
||||
&self,
|
||||
op: MinMax,
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
assert_eq!(left.layout.ty, right.layout.ty);
|
||||
let ty::Float(float_ty) = left.layout.ty.kind() else {
|
||||
bug!("fmax operand is not a float")
|
||||
};
|
||||
let left = left.to_scalar();
|
||||
let right = right.to_scalar();
|
||||
Ok(match float_ty {
|
||||
FloatTy::F32 => {
|
||||
let left = left.to_f32()?;
|
||||
let right = right.to_f32()?;
|
||||
let res = match op {
|
||||
MinMax::Min => left.min(right),
|
||||
MinMax::Max => left.max(right),
|
||||
};
|
||||
let res = this.adjust_nan(res, &[left, right]);
|
||||
Scalar::from_f32(res)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
let left = left.to_f64()?;
|
||||
let right = right.to_f64()?;
|
||||
let res = match op {
|
||||
MinMax::Min => left.min(right),
|
||||
MinMax::Max => left.max(right),
|
||||
};
|
||||
let res = this.adjust_nan(res, &[left, right]);
|
||||
Scalar::from_f64(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 {
|
||||
@ -719,31 +758,3 @@ fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 {
|
||||
Endian::Big => vec_len - 1 - idx, // reverse order of bits
|
||||
}
|
||||
}
|
||||
|
||||
fn fmax_op<'tcx>(
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
assert_eq!(left.layout.ty, right.layout.ty);
|
||||
let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmax operand is not a float") };
|
||||
let left = left.to_scalar();
|
||||
let right = right.to_scalar();
|
||||
Ok(match float_ty {
|
||||
FloatTy::F32 => Scalar::from_f32(left.to_f32()?.max(right.to_f32()?)),
|
||||
FloatTy::F64 => Scalar::from_f64(left.to_f64()?.max(right.to_f64()?)),
|
||||
})
|
||||
}
|
||||
|
||||
fn fmin_op<'tcx>(
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
assert_eq!(left.layout.ty, right.layout.ty);
|
||||
let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmin operand is not a float") };
|
||||
let left = left.to_scalar();
|
||||
let right = right.to_scalar();
|
||||
Ok(match float_ty {
|
||||
FloatTy::F32 => Scalar::from_f32(left.to_f32()?.min(right.to_f32()?)),
|
||||
FloatTy::F64 => Scalar::from_f64(left.to_f64()?.min(right.to_f64()?)),
|
||||
})
|
||||
}
|
||||
|
@ -559,8 +559,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
);
|
||||
};
|
||||
|
||||
if mode != 0o666 {
|
||||
throw_unsup_format!("non-default mode 0o{:o} is not supported", mode);
|
||||
#[cfg(unix)]
|
||||
{
|
||||
// Support all modes on UNIX host
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
options.mode(mode);
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
// Only support default mode for non-UNIX (i.e. Windows) host
|
||||
if mode != 0o666 {
|
||||
throw_unsup_format!(
|
||||
"non-default mode 0o{:o} is not supported on non-Unix hosts",
|
||||
mode
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mirror |= o_creat;
|
||||
|
@ -14,7 +14,7 @@
|
||||
//! munmap shim which would partily unmap a region of address space previously mapped by mmap will
|
||||
//! report UB.
|
||||
|
||||
use crate::{helpers::round_to_next_multiple_of, *};
|
||||
use crate::*;
|
||||
use rustc_target::abi::Size;
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
@ -96,7 +96,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
let align = this.machine.page_align();
|
||||
let map_length = round_to_next_multiple_of(length, this.machine.page_size);
|
||||
let Some(map_length) = length.checked_next_multiple_of(this.machine.page_size) else {
|
||||
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
|
||||
return Ok(this.eval_libc("MAP_FAILED"));
|
||||
};
|
||||
if map_length > this.target_usize_max() {
|
||||
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
|
||||
return Ok(this.eval_libc("MAP_FAILED"));
|
||||
}
|
||||
|
||||
let ptr =
|
||||
this.allocate_ptr(Size::from_bytes(map_length), align, MiriMemoryKind::Mmap.into())?;
|
||||
@ -129,7 +136,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
return Ok(Scalar::from_i32(-1));
|
||||
}
|
||||
|
||||
let length = Size::from_bytes(round_to_next_multiple_of(length, this.machine.page_size));
|
||||
let Some(length) = length.checked_next_multiple_of(this.machine.page_size) else {
|
||||
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
|
||||
return Ok(Scalar::from_i32(-1));
|
||||
};
|
||||
if length > this.target_usize_max() {
|
||||
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
|
||||
return Ok(this.eval_libc("MAP_FAILED"));
|
||||
}
|
||||
|
||||
let length = Size::from_bytes(length);
|
||||
this.deallocate_ptr(
|
||||
addr,
|
||||
Some((length, this.machine.page_align())),
|
||||
|
@ -44,6 +44,12 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
@ -71,6 +77,22 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
@ -122,6 +144,12 @@ version = "0.2.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.10"
|
||||
@ -161,7 +189,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -174,7 +202,9 @@ dependencies = [
|
||||
"num_cpus",
|
||||
"page_size",
|
||||
"rand",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -230,9 +260,9 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.3.5",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -301,7 +331,16 @@ version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -310,6 +349,19 @@ version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@ -338,7 +390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -352,6 +404,19 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall 0.4.1",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.32.0"
|
||||
@ -368,7 +433,7 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -482,7 +547,16 @@ version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -491,13 +565,28 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -506,38 +595,80 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
@ -11,6 +11,7 @@ edition = "2021"
|
||||
# all dependencies (and their transitive ones) listed here can be used in `tests/`.
|
||||
libc = "0.2"
|
||||
num_cpus = "1.10.1"
|
||||
tempfile = "3"
|
||||
|
||||
getrandom_01 = { package = "getrandom", version = "0.1" }
|
||||
getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] }
|
||||
@ -20,4 +21,7 @@ rand = { version = "0.8", features = ["small_rng"] }
|
||||
page_size = "0.6"
|
||||
tokio = { version = "1.24", features = ["full"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { version = "0.52", features = [ "Win32_Foundation", "Win32_System_Threading" ] }
|
||||
|
||||
[workspace]
|
||||
|
@ -111,6 +111,8 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
|
||||
"run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
|
||||
]);
|
||||
config.dependency_builder.args = builder_args.into_iter().map(Into::into).collect();
|
||||
// Reset `RUSTFLAGS` to work around <https://github.com/rust-lang/rust/pull/119574#issuecomment-1876878344>.
|
||||
config.dependency_builder.envs.push(("RUSTFLAGS".into(), None));
|
||||
}
|
||||
config
|
||||
}
|
||||
|
@ -3,18 +3,16 @@
|
||||
|
||||
// Joining a detached thread is undefined behavior.
|
||||
|
||||
use std::os::windows::io::{AsRawHandle, RawHandle};
|
||||
use std::os::windows::io::AsRawHandle;
|
||||
use std::thread;
|
||||
|
||||
extern "system" {
|
||||
fn CloseHandle(handle: RawHandle) -> u32;
|
||||
}
|
||||
use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
|
||||
|
||||
fn main() {
|
||||
let thread = thread::spawn(|| ());
|
||||
|
||||
unsafe {
|
||||
assert_ne!(CloseHandle(thread.as_raw_handle()), 0);
|
||||
assert_ne!(CloseHandle(thread.as_raw_handle() as HANDLE), 0);
|
||||
}
|
||||
|
||||
thread.join().unwrap();
|
@ -6,21 +6,18 @@
|
||||
|
||||
use std::thread;
|
||||
|
||||
extern "system" {
|
||||
fn WaitForSingleObject(handle: isize, timeout: u32) -> u32;
|
||||
}
|
||||
|
||||
const INFINITE: u32 = u32::MAX;
|
||||
use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0};
|
||||
use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE};
|
||||
|
||||
// XXX HACK: This is how miri represents the handle for thread 0.
|
||||
// This value can be "legitimately" obtained by using `GetCurrentThread` with `DuplicateHandle`
|
||||
// but miri does not implement `DuplicateHandle` yet.
|
||||
const MAIN_THREAD: isize = (2i32 << 30) as isize;
|
||||
const MAIN_THREAD: HANDLE = (2i32 << 30) as HANDLE;
|
||||
|
||||
fn main() {
|
||||
thread::spawn(|| {
|
||||
unsafe {
|
||||
assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), 0); //~ ERROR: deadlock: the evaluated program deadlocked
|
||||
assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0); //~ ERROR: deadlock: the evaluated program deadlocked
|
||||
}
|
||||
})
|
||||
.join()
|
@ -1,8 +1,8 @@
|
||||
error: deadlock: the evaluated program deadlocked
|
||||
--> $DIR/windows_join_main.rs:LL:CC
|
||||
|
|
||||
LL | assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), 0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked
|
||||
LL | assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked
|
||||
|
|
||||
= note: inside closure at RUSTLIB/core/src/macros/mod.rs:LL:CC
|
||||
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
@ -6,18 +6,14 @@
|
||||
|
||||
use std::thread;
|
||||
|
||||
extern "system" {
|
||||
fn GetCurrentThread() -> usize;
|
||||
fn WaitForSingleObject(handle: usize, timeout: u32) -> u32;
|
||||
}
|
||||
|
||||
const INFINITE: u32 = u32::MAX;
|
||||
use windows_sys::Win32::Foundation::WAIT_OBJECT_0;
|
||||
use windows_sys::Win32::System::Threading::{GetCurrentThread, WaitForSingleObject, INFINITE};
|
||||
|
||||
fn main() {
|
||||
thread::spawn(|| {
|
||||
unsafe {
|
||||
let native = GetCurrentThread();
|
||||
assert_eq!(WaitForSingleObject(native, INFINITE), 0); //~ ERROR: deadlock: the evaluated program deadlocked
|
||||
assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0); //~ ERROR: deadlock: the evaluated program deadlocked
|
||||
}
|
||||
})
|
||||
.join()
|
@ -1,7 +1,7 @@
|
||||
error: deadlock: the evaluated program deadlocked
|
||||
--> $DIR/windows_join_self.rs:LL:CC
|
||||
|
|
||||
LL | assert_eq!(WaitForSingleObject(native, INFINITE), 0);
|
||||
LL | assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0);
|
||||
| ^ the evaluated program deadlocked
|
||||
|
|
||||
= note: inside closure at $DIR/windows_join_self.rs:LL:CC
|
@ -14,7 +14,7 @@ fn main() {
|
||||
let ptr = std::ptr::addr_of_mut!(non_copy);
|
||||
// Inside `callee`, the first argument and `*ptr` are basically
|
||||
// aliasing places!
|
||||
Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue())
|
||||
Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
after_call = {
|
||||
Return()
|
||||
|
@ -27,8 +27,8 @@ LL | unsafe { ptr.write(S(0)) };
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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
|
||||
|
@ -35,8 +35,8 @@ LL | unsafe { ptr.write(S(0)) };
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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 @@ fn main() {
|
||||
{
|
||||
let non_copy = S(42);
|
||||
// This could change `non_copy` in-place
|
||||
Call(_unit = change_arg(Move(non_copy)), after_call, UnwindContinue())
|
||||
Call(_unit = change_arg(Move(non_copy)), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
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 = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
|
@ -14,7 +14,7 @@ fn main() {
|
||||
let non_copy = S(42);
|
||||
let ptr = std::ptr::addr_of_mut!(non_copy);
|
||||
// This could change `non_copy` in-place
|
||||
Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
|
||||
Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
after_call = {
|
||||
Return()
|
||||
|
@ -27,8 +27,8 @@ LL | x.0 = 0;
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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
|
||||
|
@ -35,8 +35,8 @@ LL | x.0 = 0;
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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 = myfun(ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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 = myfun(ptr), after_call, UnwindContinue())
|
||||
Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
|
||||
after_call = {
|
||||
|
@ -27,8 +27,8 @@ LL | unsafe { ptr.read() };
|
||||
note: inside `main`
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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
|
||||
|
@ -35,8 +35,8 @@ LL | unsafe { ptr.read() };
|
||||
note: inside `main`
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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
|
||||
|
@ -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(_x = myfun(ptr), after_call, UnwindContinue())
|
||||
Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
|
||||
after_call = {
|
||||
|
@ -30,8 +30,8 @@ LL | unsafe { ptr.write(0) };
|
||||
note: inside `main`
|
||||
--> $DIR/return_pointer_aliasing2.rs:LL:CC
|
||||
|
|
||||
LL | Call(_x = myfun(ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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
|
||||
|
@ -35,8 +35,8 @@ LL | unsafe { ptr.write(0) };
|
||||
note: inside `main`
|
||||
--> $DIR/return_pointer_aliasing2.rs:LL:CC
|
||||
|
|
||||
LL | Call(_x = myfun(ptr), after_call, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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
|
||||
|
@ -14,7 +14,7 @@ struct S(i32, [u8; 128]);
|
||||
fn docall(out: &mut S) {
|
||||
mir! {
|
||||
{
|
||||
Call(*out = callee(), after_call, UnwindContinue())
|
||||
Call(*out = callee(), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
|
||||
after_call = {
|
||||
@ -37,7 +37,7 @@ fn callee() -> S {
|
||||
// become visible to the outside. In codegen we can see them
|
||||
// but Miri should detect this as UB!
|
||||
RET.0 = 42;
|
||||
Call(_unit = startpanic(), after_call, UnwindContinue())
|
||||
Call(_unit = startpanic(), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
|
||||
after_call = {
|
||||
|
7
src/tools/miri/tests/fail/intrinsics/fast_math_result.rs
Normal file
7
src/tools/miri/tests/fail/intrinsics/fast_math_result.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _x: f32 = core::intrinsics::fdiv_fast(1.0, 0.0); //~ ERROR: `fdiv_fast` intrinsic produced non-finite value as result
|
||||
}
|
||||
}
|
15
src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr
Normal file
15
src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: Undefined Behavior: `fdiv_fast` intrinsic produced non-finite value as result
|
||||
--> $DIR/fast_math_result.rs:LL:CC
|
||||
|
|
||||
LL | let _x: f32 = core::intrinsics::fdiv_fast(1.0, 0.0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fdiv_fast` intrinsic produced non-finite value as result
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/fast_math_result.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -20,7 +20,7 @@ fn call(f: fn(NonZeroU32)) {
|
||||
let tmp = ptr::addr_of!(c);
|
||||
let ptr = tmp as *const NonZeroU32;
|
||||
// The call site now is a NonZeroU32-to-u32 transmute.
|
||||
Call(_res = f(*ptr), retblock, UnwindContinue()) //~ERROR: expected something greater or equal to 1
|
||||
Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) //~ERROR: expected something greater or equal to 1
|
||||
}
|
||||
retblock = {
|
||||
Return()
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
|
||||
--> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
|
||||
|
|
||||
LL | Call(_res = f(*ptr), retblock, UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
|
||||
LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -2,39 +2,30 @@
|
||||
// We are making scheduler assumptions here.
|
||||
//@compile-flags: -Zmiri-preemption-rate=0
|
||||
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::null_mut;
|
||||
use std::thread;
|
||||
|
||||
use windows_sys::Win32::System::Threading::{
|
||||
AcquireSRWLockExclusive, AcquireSRWLockShared, ReleaseSRWLockExclusive, ReleaseSRWLockShared,
|
||||
SleepConditionVariableSRW, WakeAllConditionVariable, CONDITION_VARIABLE,
|
||||
CONDITION_VARIABLE_LOCKMODE_SHARED, INFINITE, SRWLOCK,
|
||||
};
|
||||
|
||||
// not in windows-sys
|
||||
const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: null_mut() };
|
||||
const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: null_mut() };
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct SendPtr<T>(*mut T);
|
||||
|
||||
unsafe impl<T> Send for SendPtr<T> {}
|
||||
|
||||
extern "system" {
|
||||
fn SleepConditionVariableSRW(
|
||||
condvar: *mut *mut c_void,
|
||||
lock: *mut *mut c_void,
|
||||
timeout: u32,
|
||||
flags: u32,
|
||||
) -> i32;
|
||||
fn WakeAllConditionVariable(condvar: *mut *mut c_void);
|
||||
|
||||
fn AcquireSRWLockExclusive(lock: *mut *mut c_void);
|
||||
fn AcquireSRWLockShared(lock: *mut *mut c_void);
|
||||
fn ReleaseSRWLockExclusive(lock: *mut *mut c_void);
|
||||
fn ReleaseSRWLockShared(lock: *mut *mut c_void);
|
||||
}
|
||||
|
||||
const CONDITION_VARIABLE_LOCKMODE_SHARED: u32 = 1;
|
||||
const INFINITE: u32 = u32::MAX;
|
||||
|
||||
/// threads should be able to reacquire the lock while it is locked by multiple other threads in shared mode
|
||||
fn all_shared() {
|
||||
println!("all_shared");
|
||||
|
||||
let mut lock = null_mut();
|
||||
let mut condvar = null_mut();
|
||||
let mut lock = SRWLOCK_INIT;
|
||||
let mut condvar = CONDITION_VARIABLE_INIT;
|
||||
|
||||
let lock_ptr = SendPtr(&mut lock);
|
||||
let condvar_ptr = SendPtr(&mut condvar);
|
||||
@ -105,8 +96,8 @@ fn all_shared() {
|
||||
fn shared_sleep_and_exclusive_lock() {
|
||||
println!("shared_sleep_and_exclusive_lock");
|
||||
|
||||
let mut lock = null_mut();
|
||||
let mut condvar = null_mut();
|
||||
let mut lock = SRWLOCK_INIT;
|
||||
let mut condvar = CONDITION_VARIABLE_INIT;
|
||||
|
||||
let lock_ptr = SendPtr(&mut lock);
|
||||
let condvar_ptr = SendPtr(&mut condvar);
|
||||
@ -166,8 +157,8 @@ fn shared_sleep_and_exclusive_lock() {
|
||||
fn exclusive_sleep_and_shared_lock() {
|
||||
println!("exclusive_sleep_and_shared_lock");
|
||||
|
||||
let mut lock = null_mut();
|
||||
let mut condvar = null_mut();
|
||||
let mut lock = SRWLOCK_INIT;
|
||||
let mut condvar = CONDITION_VARIABLE_INIT;
|
||||
|
||||
let lock_ptr = SendPtr(&mut lock);
|
||||
let condvar_ptr = SendPtr(&mut condvar);
|
@ -5,12 +5,10 @@
|
||||
use std::os::windows::io::IntoRawHandle;
|
||||
use std::thread;
|
||||
|
||||
extern "system" {
|
||||
fn CloseHandle(handle: usize) -> i32;
|
||||
}
|
||||
use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
|
||||
|
||||
fn main() {
|
||||
let thread = thread::spawn(|| {}).into_raw_handle() as usize;
|
||||
let thread = thread::spawn(|| {}).into_raw_handle() as HANDLE;
|
||||
|
||||
// this yield ensures that `thread` is terminated by this point
|
||||
thread::yield_now();
|
@ -2,33 +2,24 @@
|
||||
// We are making scheduler assumptions here.
|
||||
//@compile-flags: -Zmiri-preemption-rate=0
|
||||
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::null_mut;
|
||||
use std::thread;
|
||||
|
||||
use windows_sys::Win32::Foundation::{FALSE, TRUE};
|
||||
use windows_sys::Win32::System::Threading::{
|
||||
InitOnceBeginInitialize, InitOnceComplete, INIT_ONCE, INIT_ONCE_INIT_FAILED,
|
||||
};
|
||||
|
||||
// not in windows-sys
|
||||
const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: null_mut() };
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct SendPtr<T>(*mut T);
|
||||
|
||||
unsafe impl<T> Send for SendPtr<T> {}
|
||||
|
||||
extern "system" {
|
||||
fn InitOnceBeginInitialize(
|
||||
init: *mut *mut c_void,
|
||||
flags: u32,
|
||||
pending: *mut i32,
|
||||
context: *mut c_void,
|
||||
) -> i32;
|
||||
|
||||
fn InitOnceComplete(init: *mut *mut c_void, flags: u32, context: *mut c_void) -> i32;
|
||||
}
|
||||
|
||||
const TRUE: i32 = 1;
|
||||
const FALSE: i32 = 0;
|
||||
|
||||
const INIT_ONCE_INIT_FAILED: u32 = 4;
|
||||
|
||||
fn single_thread() {
|
||||
let mut init_once = null_mut();
|
||||
let mut init_once = INIT_ONCE_STATIC_INIT;
|
||||
let mut pending = 0;
|
||||
|
||||
unsafe {
|
||||
@ -41,7 +32,7 @@ fn single_thread() {
|
||||
assert_eq!(pending, FALSE);
|
||||
}
|
||||
|
||||
let mut init_once = null_mut();
|
||||
let mut init_once = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
unsafe {
|
||||
assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE);
|
||||
@ -55,7 +46,7 @@ fn single_thread() {
|
||||
}
|
||||
|
||||
fn block_until_complete() {
|
||||
let mut init_once = null_mut();
|
||||
let mut init_once = INIT_ONCE_STATIC_INIT;
|
||||
let mut pending = 0;
|
||||
|
||||
unsafe {
|
||||
@ -92,7 +83,7 @@ fn block_until_complete() {
|
||||
}
|
||||
|
||||
fn retry_on_fail() {
|
||||
let mut init_once = null_mut();
|
||||
let mut init_once = INIT_ONCE_STATIC_INIT;
|
||||
let mut pending = 0;
|
||||
|
||||
unsafe {
|
||||
@ -134,7 +125,7 @@ fn retry_on_fail() {
|
||||
}
|
||||
|
||||
fn no_data_race_after_complete() {
|
||||
let mut init_once = null_mut();
|
||||
let mut init_once = INIT_ONCE_STATIC_INIT;
|
||||
let mut pending = 0;
|
||||
|
||||
unsafe {
|
@ -6,11 +6,8 @@ use std::os::windows::io::IntoRawHandle;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::thread;
|
||||
|
||||
extern "system" {
|
||||
fn WaitForSingleObject(handle: usize, timeout: u32) -> u32;
|
||||
}
|
||||
|
||||
const INFINITE: u32 = u32::MAX;
|
||||
use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0};
|
||||
use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE};
|
||||
|
||||
fn main() {
|
||||
static FLAG: AtomicBool = AtomicBool::new(false);
|
||||
@ -20,10 +17,10 @@ fn main() {
|
||||
thread::yield_now();
|
||||
}
|
||||
})
|
||||
.into_raw_handle() as usize;
|
||||
.into_raw_handle() as HANDLE;
|
||||
|
||||
let waiter = move || unsafe {
|
||||
assert_eq!(WaitForSingleObject(blocker, INFINITE), 0);
|
||||
assert_eq!(WaitForSingleObject(blocker, INFINITE), WAIT_OBJECT_0);
|
||||
};
|
||||
|
||||
let waiter1 = thread::spawn(waiter);
|
@ -90,9 +90,30 @@ fn test_mmap() {
|
||||
assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::ENOTSUP);
|
||||
}
|
||||
|
||||
// We report an error for mappings whose length cannot be rounded up to a multiple of
|
||||
// the page size.
|
||||
let ptr = unsafe {
|
||||
libc::mmap(
|
||||
ptr::null_mut(),
|
||||
usize::MAX - 1,
|
||||
libc::PROT_READ | libc::PROT_WRITE,
|
||||
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
|
||||
-1,
|
||||
0,
|
||||
)
|
||||
};
|
||||
assert_eq!(ptr, libc::MAP_FAILED);
|
||||
|
||||
// We report an error when trying to munmap an address which is not a multiple of the page size
|
||||
let res = unsafe { libc::munmap(ptr::invalid_mut(1), page_size) };
|
||||
assert_eq!(res, -1);
|
||||
assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL);
|
||||
|
||||
// We report an error when trying to munmap a length that cannot be rounded up to a multiple of
|
||||
// the page size.
|
||||
let res = unsafe { libc::munmap(ptr::invalid_mut(page_size), usize::MAX - 1) };
|
||||
assert_eq!(res, -1);
|
||||
assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
21
src/tools/miri/tests/pass-dep/tempfile.rs
Normal file
21
src/tools/miri/tests/pass-dep/tempfile.rs
Normal file
@ -0,0 +1,21 @@
|
||||
//@ignore-target-windows: File handling is not implemented yet
|
||||
//@ignore-host-windows: Only supported for UNIX hosts
|
||||
//@compile-flags: -Zmiri-disable-isolation
|
||||
|
||||
#[path = "../utils/mod.rs"]
|
||||
mod utils;
|
||||
|
||||
/// Test that the [`tempfile`] crate is compatible with miri for UNIX hosts and targets
|
||||
fn main() {
|
||||
test_tempfile();
|
||||
test_tempfile_in();
|
||||
}
|
||||
|
||||
fn test_tempfile() {
|
||||
tempfile::tempfile().unwrap();
|
||||
}
|
||||
|
||||
fn test_tempfile_in() {
|
||||
let dir_path = utils::tmp();
|
||||
tempfile::tempfile_in(dir_path).unwrap();
|
||||
}
|
@ -1,8 +1,16 @@
|
||||
#![feature(float_gamma, portable_simd, core_intrinsics, platform_intrinsics)]
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::hint::black_box;
|
||||
|
||||
fn ldexp(a: f64, b: i32) -> f64 {
|
||||
extern "C" {
|
||||
fn ldexp(x: f64, n: i32) -> f64;
|
||||
}
|
||||
unsafe { ldexp(a, b) }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum Sign {
|
||||
Neg = 1,
|
||||
@ -249,6 +257,58 @@ fn test_f32() {
|
||||
check_all_outcomes(HashSet::from_iter([F32::nan(Neg, Signaling, all1_payload)]), || {
|
||||
F32::from(-all1_snan)
|
||||
});
|
||||
|
||||
// Intrinsics
|
||||
let nan = F32::nan(Neg, Quiet, 0).as_f32();
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(f32::min(nan, nan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(nan.sin()),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([
|
||||
F32::nan(Pos, Quiet, 0),
|
||||
F32::nan(Neg, Quiet, 0),
|
||||
F32::nan(Pos, Quiet, 1),
|
||||
F32::nan(Neg, Quiet, 1),
|
||||
F32::nan(Pos, Quiet, 2),
|
||||
F32::nan(Neg, Quiet, 2),
|
||||
F32::nan(Pos, Quiet, all1_payload),
|
||||
F32::nan(Neg, Quiet, all1_payload),
|
||||
F32::nan(Pos, Signaling, all1_payload),
|
||||
F32::nan(Neg, Signaling, all1_payload),
|
||||
]),
|
||||
|| F32::from(just1.mul_add(F32::nan(Neg, Quiet, 2).as_f32(), all1_snan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(nan.powf(nan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([1.0f32.into()]),
|
||||
|| F32::from(1.0f32.powf(nan)), // special `pow` rule
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(nan.powi(1)),
|
||||
);
|
||||
|
||||
// libm functions
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(nan.sinh()),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(nan.atan2(nan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(nan.ln_gamma().0),
|
||||
);
|
||||
}
|
||||
|
||||
fn test_f64() {
|
||||
@ -309,6 +369,62 @@ fn test_f64() {
|
||||
]),
|
||||
|| F64::from(just1 % all1_snan),
|
||||
);
|
||||
|
||||
// Intrinsics
|
||||
let nan = F64::nan(Neg, Quiet, 0).as_f64();
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(f64::min(nan, nan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(nan.sin()),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([
|
||||
F64::nan(Pos, Quiet, 0),
|
||||
F64::nan(Neg, Quiet, 0),
|
||||
F64::nan(Pos, Quiet, 1),
|
||||
F64::nan(Neg, Quiet, 1),
|
||||
F64::nan(Pos, Quiet, 2),
|
||||
F64::nan(Neg, Quiet, 2),
|
||||
F64::nan(Pos, Quiet, all1_payload),
|
||||
F64::nan(Neg, Quiet, all1_payload),
|
||||
F64::nan(Pos, Signaling, all1_payload),
|
||||
F64::nan(Neg, Signaling, all1_payload),
|
||||
]),
|
||||
|| F64::from(just1.mul_add(F64::nan(Neg, Quiet, 2).as_f64(), all1_snan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(nan.powf(nan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([1.0f64.into()]),
|
||||
|| F64::from(1.0f64.powf(nan)), // special `pow` rule
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(nan.powi(1)),
|
||||
);
|
||||
|
||||
// libm functions
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(nan.sinh()),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(nan.atan2(nan)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(ldexp(nan, 1)),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(nan.ln_gamma().0),
|
||||
);
|
||||
}
|
||||
|
||||
fn test_casts() {
|
||||
@ -397,6 +513,61 @@ fn test_casts() {
|
||||
);
|
||||
}
|
||||
|
||||
fn test_simd() {
|
||||
use std::intrinsics::simd::*;
|
||||
use std::simd::*;
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_fsqrt<T>(x: T) -> T;
|
||||
fn simd_ceil<T>(x: T) -> T;
|
||||
fn simd_fma<T>(x: T, y: T, z: T) -> T;
|
||||
}
|
||||
|
||||
let nan = F32::nan(Neg, Quiet, 0).as_f32();
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(unsafe { simd_div(f32x4::splat(0.0), f32x4::splat(0.0)) }[0]),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(unsafe { simd_fmin(f32x4::splat(nan), f32x4::splat(nan)) }[0]),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(unsafe { simd_fmax(f32x4::splat(nan), f32x4::splat(nan)) }[0]),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| {
|
||||
F32::from(
|
||||
unsafe { simd_fma(f32x4::splat(nan), f32x4::splat(nan), f32x4::splat(nan)) }[0],
|
||||
)
|
||||
},
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(unsafe { simd_reduce_add_ordered::<_, f32>(f32x4::splat(nan), nan) }),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(unsafe { simd_reduce_max::<_, f32>(f32x4::splat(nan)) }),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(unsafe { simd_fsqrt(f32x4::splat(nan)) }[0]),
|
||||
);
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
|
||||
|| F32::from(unsafe { simd_ceil(f32x4::splat(nan)) }[0]),
|
||||
);
|
||||
|
||||
// Casts
|
||||
check_all_outcomes(
|
||||
HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
|
||||
|| F64::from(unsafe { simd_cast::<f32x4, f64x4>(f32x4::splat(nan)) }[0]),
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Check our constants against std, just to be sure.
|
||||
// We add 1 since our numbers are the number of bits stored
|
||||
@ -408,4 +579,5 @@ fn main() {
|
||||
test_f32();
|
||||
test_f64();
|
||||
test_casts();
|
||||
test_simd();
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ pub fn main() {
|
||||
{
|
||||
let x = 0;
|
||||
let ptr = &raw mut x;
|
||||
Call(*ptr = myfun(), after_call, UnwindContinue())
|
||||
Call(*ptr = myfun(), ReturnTo(after_call), UnwindContinue())
|
||||
}
|
||||
|
||||
after_call = {
|
||||
|
@ -112,6 +112,30 @@ check!(reg_i32, i32, reg, "lgr");
|
||||
// CHECK: #NO_APP
|
||||
check!(reg_i64, i64, reg, "lgr");
|
||||
|
||||
// CHECK-LABEL: reg_i8_addr:
|
||||
// CHECK: #APP
|
||||
// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
|
||||
// CHECK: #NO_APP
|
||||
check!(reg_i8_addr, i8, reg_addr, "lgr");
|
||||
|
||||
// CHECK-LABEL: reg_i16_addr:
|
||||
// CHECK: #APP
|
||||
// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
|
||||
// CHECK: #NO_APP
|
||||
check!(reg_i16_addr, i16, reg_addr, "lgr");
|
||||
|
||||
// CHECK-LABEL: reg_i32_addr:
|
||||
// CHECK: #APP
|
||||
// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
|
||||
// CHECK: #NO_APP
|
||||
check!(reg_i32_addr, i32, reg_addr, "lgr");
|
||||
|
||||
// CHECK-LABEL: reg_i64_addr:
|
||||
// CHECK: #APP
|
||||
// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
|
||||
// CHECK: #NO_APP
|
||||
check!(reg_i64_addr, i64, reg_addr, "lgr");
|
||||
|
||||
// CHECK-LABEL: reg_f32:
|
||||
// CHECK: #APP
|
||||
// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}}
|
||||
|
@ -13,7 +13,7 @@ fn ident<T>(t: T) -> T {
|
||||
fn direct_call(x: i32) -> i32 {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = ident(x), retblock, UnwindContinue())
|
||||
Call(RET = ident(x), ReturnTo(retblock), UnwindContinue())
|
||||
}
|
||||
|
||||
retblock = {
|
||||
@ -27,7 +27,7 @@ fn direct_call(x: i32) -> i32 {
|
||||
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = f(x), retblock, UnwindContinue())
|
||||
Call(RET = f(x), ReturnTo(retblock), UnwindContinue())
|
||||
}
|
||||
|
||||
retblock = {
|
||||
@ -49,7 +49,7 @@ impl<'a> Drop for WriteOnDrop<'a> {
|
||||
fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
|
||||
mir!(
|
||||
{
|
||||
Drop(a, retblock, UnwindContinue())
|
||||
Drop(a, ReturnTo(retblock), UnwindContinue())
|
||||
}
|
||||
|
||||
retblock = {
|
||||
@ -64,7 +64,7 @@ fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
|
||||
fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
|
||||
mir!(
|
||||
{
|
||||
Drop(b, retblock, UnwindContinue())
|
||||
Drop(b, ReturnTo(retblock), UnwindContinue())
|
||||
}
|
||||
|
||||
retblock = {
|
||||
|
@ -11,7 +11,7 @@ use core::intrinsics::mir::*;
|
||||
pub fn a() {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = a(), bb1, UnwindUnreachable())
|
||||
Call(RET = a(), ReturnTo(bb1), UnwindUnreachable())
|
||||
}
|
||||
bb1 = {
|
||||
Return()
|
||||
@ -26,7 +26,7 @@ pub fn a() {
|
||||
pub fn b() {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = b(), bb1, UnwindContinue())
|
||||
Call(RET = b(), ReturnTo(bb1), UnwindContinue())
|
||||
}
|
||||
bb1 = {
|
||||
Return()
|
||||
@ -41,7 +41,7 @@ pub fn b() {
|
||||
pub fn c() {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = c(), bb1, UnwindTerminate(ReasonAbi))
|
||||
Call(RET = c(), ReturnTo(bb1), UnwindTerminate(ReasonAbi))
|
||||
}
|
||||
bb1 = {
|
||||
Return()
|
||||
@ -56,7 +56,7 @@ pub fn c() {
|
||||
pub fn d() {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = d(), bb1, UnwindCleanup(bb2))
|
||||
Call(RET = d(), ReturnTo(bb1), UnwindCleanup(bb2))
|
||||
}
|
||||
bb1 = {
|
||||
Return()
|
||||
|
@ -22,11 +22,11 @@ fn f() -> bool {
|
||||
let b = a;
|
||||
// We cannot propagate the place `a`.
|
||||
let r2 = &b;
|
||||
Call(RET = cmp_ref(r1, r2), next, UnwindContinue())
|
||||
Call(RET = cmp_ref(r1, r2), ReturnTo(next), UnwindContinue())
|
||||
}
|
||||
next = {
|
||||
// But we can propagate the value `a`.
|
||||
Call(RET = opaque(b), ret, UnwindContinue())
|
||||
Call(RET = opaque(b), ReturnTo(ret), UnwindContinue())
|
||||
}
|
||||
ret = {
|
||||
Return()
|
||||
|
@ -26,7 +26,7 @@ fn multiple_edges(t: bool) -> u8 {
|
||||
match t { true => bbt, _ => ret }
|
||||
}
|
||||
bbt = {
|
||||
Call(x = dummy(13), ret, UnwindContinue())
|
||||
Call(x = dummy(13), ReturnTo(ret), UnwindContinue())
|
||||
}
|
||||
ret = {
|
||||
// `x` is not assigned on the `bb0 -> ret` edge,
|
||||
|
@ -14,11 +14,11 @@ struct NotCopy(bool);
|
||||
fn f(_1: NotCopy) {
|
||||
mir!({
|
||||
let _2 = _1;
|
||||
Call(RET = opaque(Move(_1)), bb1, UnwindContinue())
|
||||
Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindContinue())
|
||||
}
|
||||
bb1 = {
|
||||
let _3 = Move(_2);
|
||||
Call(RET = opaque(_3), bb2, UnwindContinue())
|
||||
Call(RET = opaque(_3), ReturnTo(bb2), UnwindContinue())
|
||||
}
|
||||
bb2 = {
|
||||
Return()
|
||||
|
@ -18,10 +18,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 = opaque(Move(a)), bb1, UnwindContinue())
|
||||
Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindContinue())
|
||||
}
|
||||
bb1 = {
|
||||
Call(RET = opaque(Move(c)), ret, UnwindContinue())
|
||||
Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindContinue())
|
||||
}
|
||||
ret = {
|
||||
Return()
|
||||
|
@ -28,7 +28,7 @@ struct Packed {
|
||||
fn move_packed(packed: Packed) {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = use_both(0, packed.y), ret, UnwindContinue())
|
||||
Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue())
|
||||
}
|
||||
ret = {
|
||||
Return()
|
||||
|
@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
|
||||
mir!(
|
||||
let condition: bool;
|
||||
{
|
||||
Call(condition = cond(), bb1, UnwindContinue())
|
||||
Call(condition = cond(), ReturnTo(bb1), UnwindContinue())
|
||||
}
|
||||
bb1 = {
|
||||
match condition { true => bb2, _ => ret }
|
||||
@ -30,7 +30,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
|
||||
z = y;
|
||||
y = x;
|
||||
x = temp;
|
||||
Call(condition = cond(), bb1, UnwindContinue())
|
||||
Call(condition = cond(), ReturnTo(bb1), UnwindContinue())
|
||||
}
|
||||
ret = {
|
||||
Return()
|
||||
|
@ -529,31 +529,31 @@ fn duplicate_slice() -> (bool, bool) {
|
||||
// CHECK: [[a:_.*]] = (const "a",);
|
||||
// CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute);
|
||||
let a = ("a",);
|
||||
Call(au = transmute::<_, u128>(a.0), bb1, UnwindContinue())
|
||||
Call(au = transmute::<_, u128>(a.0), ReturnTo(bb1), UnwindContinue())
|
||||
}
|
||||
bb1 = {
|
||||
// CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str))
|
||||
Call(c = identity(a.0), bb2, UnwindContinue())
|
||||
Call(c = identity(a.0), ReturnTo(bb2), UnwindContinue())
|
||||
}
|
||||
bb2 = {
|
||||
// CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute);
|
||||
Call(cu = transmute::<_, u128>(c), bb3, UnwindContinue())
|
||||
Call(cu = transmute::<_, u128>(c), ReturnTo(bb3), UnwindContinue())
|
||||
}
|
||||
bb3 = {
|
||||
// This slice is different from `a.0`. Hence `bu` is not `au`.
|
||||
// CHECK: [[b:_.*]] = const "a";
|
||||
// CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute);
|
||||
let b = "a";
|
||||
Call(bu = transmute::<_, u128>(b), bb4, UnwindContinue())
|
||||
Call(bu = transmute::<_, u128>(b), ReturnTo(bb4), UnwindContinue())
|
||||
}
|
||||
bb4 = {
|
||||
// This returns a copy of `b`, which is not `a`.
|
||||
// CHECK: [[d:_.*]] = identity::<&str>([[b]])
|
||||
Call(d = identity(b), bb5, UnwindContinue())
|
||||
Call(d = identity(b), ReturnTo(bb5), UnwindContinue())
|
||||
}
|
||||
bb5 = {
|
||||
// CHECK: [[du:_.*]] = [[d]] as u128 (Transmute);
|
||||
Call(du = transmute::<_, u128>(d), bb6, UnwindContinue())
|
||||
Call(du = transmute::<_, u128>(d), ReturnTo(bb6), UnwindContinue())
|
||||
}
|
||||
bb6 = {
|
||||
// `direct` must not fold to `true`, as `indirect` will not.
|
||||
|
@ -25,7 +25,7 @@ pub fn f(a: *mut u8) {
|
||||
Goto(bb1)
|
||||
}
|
||||
bb1 = {
|
||||
Call(*a = g(), bb1, UnwindUnreachable())
|
||||
Call(*a = g(), ReturnTo(bb1), UnwindUnreachable())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -696,7 +696,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 = opaque(y), retblock, UnwindContinue())
|
||||
Call(RET = opaque(y), ReturnTo(retblock), UnwindContinue())
|
||||
}
|
||||
|
||||
retblock = {
|
||||
@ -724,7 +724,7 @@ fn dominate_storage() {
|
||||
}
|
||||
bb1 = {
|
||||
let c = *r;
|
||||
Call(RET = opaque(c), bb2, UnwindContinue())
|
||||
Call(RET = opaque(c), ReturnTo(bb2), UnwindContinue())
|
||||
}
|
||||
bb2 = {
|
||||
StorageDead(x);
|
||||
@ -760,18 +760,18 @@ fn maybe_dead(m: bool) {
|
||||
bb1 = {
|
||||
StorageDead(x);
|
||||
StorageDead(y);
|
||||
Call(RET = opaque(u), bb2, UnwindContinue())
|
||||
Call(RET = opaque(u), ReturnTo(bb2), UnwindContinue())
|
||||
}
|
||||
bb2 = {
|
||||
// As `x` may be `StorageDead`, `a` may be dangling, so we do nothing.
|
||||
let z = *a;
|
||||
Call(RET = opaque(z), bb3, UnwindContinue())
|
||||
Call(RET = opaque(z), ReturnTo(bb3), UnwindContinue())
|
||||
}
|
||||
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 = opaque(t), retblock, UnwindContinue())
|
||||
Call(RET = opaque(t), ReturnTo(retblock), UnwindContinue())
|
||||
}
|
||||
retblock = {
|
||||
Return()
|
||||
|
@ -1,4 +1,6 @@
|
||||
// compile-flags:--test --error-format=short
|
||||
// check-stdout
|
||||
// error-pattern:cannot find function `foo` in this scope
|
||||
// normalize-stdout-test: "tests/rustdoc-ui/issues" -> "$$DIR"
|
||||
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
|
||||
// failure-status: 101
|
||||
@ -6,7 +8,6 @@
|
||||
/// ```rust
|
||||
/// foo();
|
||||
/// ```
|
||||
//~^^ ERROR cannot find function `foo` in this scope
|
||||
fn foo() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
|
||||
running 1 test
|
||||
test $DIR/issue-81662-shortness.rs - foo (line 6) ... FAILED
|
||||
test $DIR/issue-81662-shortness.rs - foo (line 8) ... FAILED
|
||||
|
||||
failures:
|
||||
|
||||
---- $DIR/issue-81662-shortness.rs - foo (line 6) stdout ----
|
||||
$DIR/issue-81662-shortness.rs:7:1: error[E0425]: cannot find function `foo` in this scope
|
||||
---- $DIR/issue-81662-shortness.rs - foo (line 8) stdout ----
|
||||
$DIR/issue-81662-shortness.rs:9:1: error[E0425]: cannot find function `foo` in this scope
|
||||
error: aborting due to 1 previous error
|
||||
Couldn't compile the test.
|
||||
|
||||
failures:
|
||||
$DIR/issue-81662-shortness.rs - foo (line 6)
|
||||
$DIR/issue-81662-shortness.rs - foo (line 8)
|
||||
|
||||
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
// compile-flags: --error-format human-annotate-rs -Z unstable-options
|
||||
// error-pattern:cannot find type `Iter` in this scope
|
||||
|
||||
pub fn main() {
|
||||
let x: Iter; //~ ERROR cannot find type `Iter` in this scope
|
||||
let x: Iter;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0412]: cannot find type `Iter` in this scope
|
||||
--> $DIR/missing-type.rs:4:12
|
||||
--> $DIR/missing-type.rs:5:12
|
||||
|
|
||||
LL | let x: Iter;
|
||||
| ^^^^ not found in this scope
|
||||
|
@ -1,4 +1,5 @@
|
||||
// aux-build:multispan.rs
|
||||
// error-pattern:hello to you, too!
|
||||
// compile-flags: --error-format human-annotate-rs -Z unstable-options
|
||||
|
||||
#![feature(proc_macro_hygiene)]
|
||||
@ -12,17 +13,17 @@ fn main() {
|
||||
hello!();
|
||||
|
||||
// Exactly one 'hi'.
|
||||
hello!(hi); //~ ERROR hello to you, too!
|
||||
hello!(hi);
|
||||
|
||||
// Now two, back to back.
|
||||
hello!(hi hi); //~ ERROR hello to you, too!
|
||||
hello!(hi hi);
|
||||
|
||||
// Now three, back to back.
|
||||
hello!(hi hi hi); //~ ERROR hello to you, too!
|
||||
hello!(hi hi hi);
|
||||
|
||||
// Now several, with spacing.
|
||||
hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
|
||||
hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
|
||||
hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
|
||||
hello!(hi good hi and good bye); //~ ERROR hello to you, too!
|
||||
hello!(hi hey hi yo hi beep beep hi hi);
|
||||
hello!(hi there, hi how are you? hi... hi.);
|
||||
hello!(whoah. hi di hi di ho);
|
||||
hello!(hi good hi and good bye);
|
||||
}
|
||||
|
@ -1,41 +1,41 @@
|
||||
error: hello to you, too!
|
||||
--> $DIR/multispan.rs:15:5
|
||||
--> $DIR/multispan.rs:16:5
|
||||
|
|
||||
LL | hello!(hi);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
error: hello to you, too!
|
||||
--> $DIR/multispan.rs:18:5
|
||||
--> $DIR/multispan.rs:19:5
|
||||
|
|
||||
LL | hello!(hi hi);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
error: hello to you, too!
|
||||
--> $DIR/multispan.rs:21:5
|
||||
--> $DIR/multispan.rs:22:5
|
||||
|
|
||||
LL | hello!(hi hi hi);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
error: hello to you, too!
|
||||
--> $DIR/multispan.rs:24:5
|
||||
--> $DIR/multispan.rs:25:5
|
||||
|
|
||||
LL | hello!(hi hey hi yo hi beep beep hi hi);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
error: hello to you, too!
|
||||
--> $DIR/multispan.rs:25:5
|
||||
--> $DIR/multispan.rs:26:5
|
||||
|
|
||||
LL | hello!(hi there, hi how are you? hi... hi.);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
error: hello to you, too!
|
||||
--> $DIR/multispan.rs:26:5
|
||||
--> $DIR/multispan.rs:27:5
|
||||
|
|
||||
LL | hello!(whoah. hi di hi di ho);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
error: hello to you, too!
|
||||
--> $DIR/multispan.rs:27:5
|
||||
--> $DIR/multispan.rs:28:5
|
||||
|
|
||||
LL | hello!(hi good hi and good bye);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,9 +1,9 @@
|
||||
// compile-flags: --diagnostic-width=20 --error-format=json
|
||||
// error-pattern:expected `()`, found integer
|
||||
|
||||
// This test checks that `-Z output-width` effects the JSON error output by restricting it to an
|
||||
// arbitrarily low value so that the effect is visible.
|
||||
|
||||
fn main() {
|
||||
let _: () = 42;
|
||||
//~^ ERROR arguments to this function are incorrect
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ This error occurs when an expression was used in a place where the compiler
|
||||
expected an expression of a different type. It can occur in several cases, the
|
||||
most common being when calling a function and passing an argument which has a
|
||||
different type than the matching type in the function declaration.
|
||||
"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":243,"byte_end":245,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":238,"byte_end":240,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types
|
||||
--> $DIR/flag-json.rs:7:17
|
||||
"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":289,"byte_end":291,"line_start":8,"line_end":8,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":284,"byte_end":286,"line_start":8,"line_end":8,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types
|
||||
--> $DIR/flag-json.rs:8:17
|
||||
|
|
||||
LL | ..._: () = 42;
|
||||
| -- ^^ expected `()`, found integer
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: --error-format json
|
||||
// error-pattern:unnecessary parentheses
|
||||
// run-rustfix
|
||||
|
||||
// The output for humans should just highlight the whole span without showing
|
||||
@ -13,7 +14,7 @@
|
||||
fn main() {
|
||||
// We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
|
||||
// the malformed `1 / (2 + 3`
|
||||
let _a = 1 / (2 + 3); //~ERROR unnecessary parentheses
|
||||
let _a = 1 / (2 + 3);
|
||||
f();
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: --error-format json
|
||||
// error-pattern:unnecessary parentheses
|
||||
// run-rustfix
|
||||
|
||||
// The output for humans should just highlight the whole span without showing
|
||||
@ -13,7 +14,7 @@
|
||||
fn main() {
|
||||
// We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
|
||||
// the malformed `1 / (2 + 3`
|
||||
let _a = (1 / (2 + 3)); //~ERROR unnecessary parentheses
|
||||
let _a = (1 / (2 + 3));
|
||||
f();
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));
|
||||
--> $DIR/unused_parens_json_suggestion.rs:16:14
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":618,"byte_end":619,"line_start":17,"line_end":17,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":630,"byte_end":631,"line_start":17,"line_end":17,"column_start":26,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":26,"highlight_end":27}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":436,"byte_end":449,"line_start":11,"line_end":11,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![deny(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":618,"byte_end":619,"line_start":17,"line_end":17,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":630,"byte_end":631,"line_start":17,"line_end":17,"column_start":26,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":26,"highlight_end":27}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around assigned value
|
||||
--> $DIR/unused_parens_json_suggestion.rs:17:14
|
||||
|
|
||||
LL | let _a = (1 / (2 + 3));
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_parens_json_suggestion.rs:10:9
|
||||
--> $DIR/unused_parens_json_suggestion.rs:11:9
|
||||
|
|
||||
LL | #![deny(unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: --error-format json
|
||||
// error-pattern:unnecessary parentheses
|
||||
// run-rustfix
|
||||
|
||||
// The output for humans should just highlight the whole span without showing
|
||||
@ -14,7 +15,7 @@ fn main() {
|
||||
|
||||
let _b = false;
|
||||
|
||||
if _b { //~ ERROR unnecessary parentheses
|
||||
if _b {
|
||||
println!("hello");
|
||||
}
|
||||
|
||||
@ -25,29 +26,29 @@ fn main() {
|
||||
fn f() -> bool {
|
||||
let c = false;
|
||||
|
||||
if c { //~ ERROR unnecessary parentheses
|
||||
if c {
|
||||
println!("next");
|
||||
}
|
||||
|
||||
if c { //~ ERROR unnecessary parentheses
|
||||
if c {
|
||||
println!("prev");
|
||||
}
|
||||
|
||||
while false && true {
|
||||
if c { //~ ERROR unnecessary parentheses
|
||||
if c {
|
||||
println!("norm");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while true && false { //~ ERROR unnecessary parentheses
|
||||
for _ in 0 .. 3 { //~ ERROR unnecessary parentheses
|
||||
while true && false {
|
||||
for _ in 0 .. 3 {
|
||||
println!("e~")
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0 .. 3 { //~ ERROR unnecessary parentheses
|
||||
while true && false { //~ ERROR unnecessary parentheses
|
||||
for _ in 0 .. 3 {
|
||||
while true && false {
|
||||
println!("e~")
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: --error-format json
|
||||
// error-pattern:unnecessary parentheses
|
||||
// run-rustfix
|
||||
|
||||
// The output for humans should just highlight the whole span without showing
|
||||
@ -14,7 +15,7 @@ fn main() {
|
||||
|
||||
let _b = false;
|
||||
|
||||
if (_b) { //~ ERROR unnecessary parentheses
|
||||
if (_b) {
|
||||
println!("hello");
|
||||
}
|
||||
|
||||
@ -25,29 +26,29 @@ fn main() {
|
||||
fn f() -> bool {
|
||||
let c = false;
|
||||
|
||||
if(c) { //~ ERROR unnecessary parentheses
|
||||
if(c) {
|
||||
println!("next");
|
||||
}
|
||||
|
||||
if (c){ //~ ERROR unnecessary parentheses
|
||||
if (c){
|
||||
println!("prev");
|
||||
}
|
||||
|
||||
while (false && true){
|
||||
if (c) { //~ ERROR unnecessary parentheses
|
||||
if (c) {
|
||||
println!("norm");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while(true && false) { //~ ERROR unnecessary parentheses
|
||||
for _ in (0 .. 3){ //~ ERROR unnecessary parentheses
|
||||
while(true && false) {
|
||||
for _ in (0 .. 3){
|
||||
println!("e~")
|
||||
}
|
||||
}
|
||||
|
||||
for _ in (0 .. 3) { //~ ERROR unnecessary parentheses
|
||||
while (true && false) { //~ ERROR unnecessary parentheses
|
||||
for _ in (0 .. 3) {
|
||||
while (true && false) {
|
||||
println!("e~")
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:17:8
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":522,"byte_end":523,"line_start":18,"line_end":18,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":525,"byte_end":526,"line_start":18,"line_end":18,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":436,"byte_end":449,"line_start":11,"line_end":11,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![deny(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":522,"byte_end":523,"line_start":18,"line_end":18,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":525,"byte_end":526,"line_start":18,"line_end":18,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:18:8
|
||||
|
|
||||
LL | if (_b) {
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:10:9
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:11:9
|
||||
|
|
||||
LL | #![deny(unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -16,8 +16,8 @@ LL + if _b {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:28:7
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":619,"byte_end":620,"line_start":29,"line_end":29,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":7,"highlight_end":8}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":621,"byte_end":622,"line_start":29,"line_end":29,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":619,"byte_end":620,"line_start":29,"line_end":29,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":7,"highlight_end":8}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":621,"byte_end":622,"line_start":29,"line_end":29,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:29:7
|
||||
|
|
||||
LL | if(c) {
|
||||
| ^ ^
|
||||
@ -29,8 +29,8 @@ LL + if c {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:32:8
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":665,"byte_end":666,"line_start":33,"line_end":33,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":667,"byte_end":668,"line_start":33,"line_end":33,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" if (c){","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":665,"byte_end":666,"line_start":33,"line_end":33,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":667,"byte_end":668,"line_start":33,"line_end":33,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" if (c){","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:33:8
|
||||
|
|
||||
LL | if (c){
|
||||
| ^ ^
|
||||
@ -42,8 +42,8 @@ LL + if c {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:36:11
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":713,"byte_end":714,"line_start":37,"line_end":37,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":727,"byte_end":728,"line_start":37,"line_end":37,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":713,"byte_end":714,"line_start":37,"line_end":37,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":727,"byte_end":728,"line_start":37,"line_end":37,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:37:11
|
||||
|
|
||||
LL | while (false && true){
|
||||
| ^ ^
|
||||
@ -55,8 +55,8 @@ LL + while false && true {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:37:12
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":741,"byte_end":742,"line_start":38,"line_end":38,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":12,"highlight_end":13}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":743,"byte_end":744,"line_start":38,"line_end":38,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":741,"byte_end":742,"line_start":38,"line_end":38,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":12,"highlight_end":13}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":743,"byte_end":744,"line_start":38,"line_end":38,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:38:12
|
||||
|
|
||||
LL | if (c) {
|
||||
| ^ ^
|
||||
@ -68,8 +68,8 @@ LL + if c {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:43:10
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":804,"byte_end":805,"line_start":44,"line_end":44,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":818,"byte_end":819,"line_start":44,"line_end":44,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":804,"byte_end":805,"line_start":44,"line_end":44,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":818,"byte_end":819,"line_start":44,"line_end":44,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:44:10
|
||||
|
|
||||
LL | while(true && false) {
|
||||
| ^ ^
|
||||
@ -81,8 +81,8 @@ LL + while true && false {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:44:18
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":839,"byte_end":840,"line_start":45,"line_end":45,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":18,"highlight_end":19}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":846,"byte_end":847,"line_start":45,"line_end":45,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":839,"byte_end":840,"line_start":45,"line_end":45,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":18,"highlight_end":19}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":846,"byte_end":847,"line_start":45,"line_end":45,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `for` iterator expression
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:45:18
|
||||
|
|
||||
LL | for _ in (0 .. 3){
|
||||
| ^ ^
|
||||
@ -94,8 +94,8 @@ LL + for _ in 0 .. 3 {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:49:14
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":906,"byte_end":907,"line_start":50,"line_end":50,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":913,"byte_end":914,"line_start":50,"line_end":50,"column_start":21,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":21,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":906,"byte_end":907,"line_start":50,"line_end":50,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":913,"byte_end":914,"line_start":50,"line_end":50,"column_start":21,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":21,"highlight_end":22}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `for` iterator expression
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:50:14
|
||||
|
|
||||
LL | for _ in (0 .. 3) {
|
||||
| ^ ^
|
||||
@ -107,8 +107,8 @@ LL + for _ in 0 .. 3 {
|
||||
|
|
||||
|
||||
"}
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:50:15
|
||||
{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":931,"byte_end":932,"line_start":51,"line_end":51,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":15,"highlight_end":16}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":945,"byte_end":946,"line_start":51,"line_end":51,"column_start":29,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":29,"highlight_end":30}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":931,"byte_end":932,"line_start":51,"line_end":51,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":15,"highlight_end":16}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":945,"byte_end":946,"line_start":51,"line_end":51,"column_start":29,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":29,"highlight_end":30}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:51:15
|
||||
|
|
||||
LL | while (true && false) {
|
||||
| ^ ^
|
||||
|
@ -13,7 +13,7 @@ pub fn f() -> u32 {
|
||||
mir!(
|
||||
let a: u32;
|
||||
{
|
||||
Call(a = g(), bb1, UnwindCleanup(bb2))
|
||||
Call(a = g(), ReturnTo(bb1), UnwindCleanup(bb2))
|
||||
}
|
||||
bb1 = {
|
||||
RET = a;
|
||||
|
@ -20,7 +20,7 @@ pub fn f(a: u32) -> u32 {
|
||||
}
|
||||
}
|
||||
bb1 = {
|
||||
Call(RET = f(1), bb2, UnwindTerminate(ReasonAbi))
|
||||
Call(RET = f(1), ReturnTo(bb2), UnwindTerminate(ReasonAbi))
|
||||
}
|
||||
|
||||
bb2 = {
|
||||
|
@ -11,7 +11,7 @@ use core::intrinsics::mir::*;
|
||||
pub fn main() {
|
||||
mir!(
|
||||
{
|
||||
Call(RET = main(), block, UnwindCleanup(block))
|
||||
Call(RET = main(), ReturnTo(block), UnwindCleanup(block))
|
||||
}
|
||||
block = {
|
||||
Return()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user