Auto merge of #123869 - matthiaskrgr:rollup-9kif9c9, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #123654 (typeck: fix `?` suggestion span) - #123807 (Remove `sys_common::thread`) - #123834 (Don't do coroutine-closure-specific upvar analysis if tainted by errors) - #123847 (Suppress `let else` suggestion for uninitialized refutable `let`s) - #123857 (std::net: TcpListener shrinks the backlog argument to 32 for Haiku.) - #123858 (zkvm: fix path to cmath in zkvm module) - #123867 (Add `unsafe` to two functions with safety invariants) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
79424056b0
@ -1287,12 +1287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]),
|
||||
))
|
||||
{
|
||||
let mut span = expr.span;
|
||||
while expr.span.eq_ctxt(span)
|
||||
&& let Some(parent_callsite) = span.parent_callsite()
|
||||
{
|
||||
span = parent_callsite;
|
||||
}
|
||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
||||
|
||||
let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
|
||||
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
||||
@ -1897,12 +1892,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
None => sugg.to_string(),
|
||||
};
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
msg,
|
||||
sugg,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
||||
err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,8 @@ use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, Pro
|
||||
use rustc_middle::mir::FakeReadCause;
|
||||
use rustc_middle::traits::ObligationCauseCode;
|
||||
use rustc_middle::ty::{
|
||||
self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture,
|
||||
self, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, UpvarArgs,
|
||||
UpvarCapture,
|
||||
};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::sym;
|
||||
@ -191,6 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
};
|
||||
let args = self.resolve_vars_if_possible(args);
|
||||
let closure_def_id = closure_def_id.expect_local();
|
||||
|
||||
assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);
|
||||
@ -361,7 +363,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// For coroutine-closures, we additionally must compute the
|
||||
// `coroutine_captures_by_ref_ty` type, which is used to generate the by-ref
|
||||
// version of the coroutine-closure's output coroutine.
|
||||
if let UpvarArgs::CoroutineClosure(args) = args {
|
||||
if let UpvarArgs::CoroutineClosure(args) = args
|
||||
&& !args.references_error()
|
||||
{
|
||||
let closure_env_region: ty::Region<'_> = ty::Region::new_bound(
|
||||
self.tcx,
|
||||
ty::INNERMOST,
|
||||
|
@ -771,7 +771,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, HashStable)]
|
||||
#[derive(Debug, Copy, Clone, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub enum UpvarArgs<'tcx> {
|
||||
Closure(GenericArgsRef<'tcx>),
|
||||
Coroutine(GenericArgsRef<'tcx>),
|
||||
|
@ -674,6 +674,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
||||
if let Some(span) = sp
|
||||
&& self.tcx.sess.source_map().is_span_accessible(span)
|
||||
&& interpreted_as_const.is_none()
|
||||
&& scrut.is_some()
|
||||
{
|
||||
let mut bindings = vec![];
|
||||
pat.each_binding(|name, _, _, _| bindings.push(name));
|
||||
|
@ -743,6 +743,45 @@ impl Span {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
/// Recursively walk down the expansion ancestors to find the oldest ancestor span with the same
|
||||
/// [`SyntaxContext`] the initial span.
|
||||
///
|
||||
/// This method is suitable for peeling through *local* macro expansions to find the "innermost"
|
||||
/// span that is still local and shares the same [`SyntaxContext`]. For example, given
|
||||
///
|
||||
/// ```ignore (illustrative example, contains type error)
|
||||
/// macro_rules! outer {
|
||||
/// ($x: expr) => {
|
||||
/// inner!($x)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// macro_rules! inner {
|
||||
/// ($x: expr) => {
|
||||
/// format!("error: {}", $x)
|
||||
/// //~^ ERROR mismatched types
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// Err(outer!(x))
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// if provided the initial span of `outer!(x)` inside `bar`, this method will recurse
|
||||
/// the parent callsites until we reach `format!("error: {}", $x)`, at which point it is the
|
||||
/// oldest ancestor span that is both still local and shares the same [`SyntaxContext`] as the
|
||||
/// initial span.
|
||||
pub fn find_oldest_ancestor_in_same_ctxt(self) -> Span {
|
||||
let mut cur = self;
|
||||
while cur.eq_ctxt(self)
|
||||
&& let Some(parent_callsite) = cur.parent_callsite()
|
||||
{
|
||||
cur = parent_callsite;
|
||||
}
|
||||
cur
|
||||
}
|
||||
|
||||
/// Edition of the crate from which this span came.
|
||||
pub fn edition(self) -> edition::Edition {
|
||||
self.ctxt().edition()
|
||||
|
@ -45,13 +45,11 @@ impl Thread {
|
||||
Err(io::Error::last_os_error())
|
||||
};
|
||||
|
||||
extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
|
||||
unsafe {
|
||||
// Next, reserve some stack space for if we otherwise run out of stack.
|
||||
stack_overflow::reserve_stack();
|
||||
// Finally, let's run some code.
|
||||
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
|
||||
}
|
||||
unsafe extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
|
||||
// Next, reserve some stack space for if we otherwise run out of stack.
|
||||
stack_overflow::reserve_stack();
|
||||
// Finally, let's run some code.
|
||||
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
|
||||
0
|
||||
}
|
||||
}
|
||||
@ -59,15 +57,19 @@ impl Thread {
|
||||
pub fn set_name(name: &CStr) {
|
||||
if let Ok(utf8) = name.to_str() {
|
||||
if let Ok(utf16) = to_u16s(utf8) {
|
||||
Self::set_name_wide(&utf16)
|
||||
unsafe {
|
||||
// SAFETY: the vec returned by `to_u16s` ends with a zero value
|
||||
Self::set_name_wide(&utf16)
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_name_wide(name: &[u16]) {
|
||||
unsafe {
|
||||
c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr());
|
||||
};
|
||||
/// # Safety
|
||||
///
|
||||
/// `name` must end with a zero value
|
||||
pub unsafe fn set_name_wide(name: &[u16]) {
|
||||
c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr());
|
||||
}
|
||||
|
||||
pub fn join(self) {
|
||||
|
@ -12,8 +12,6 @@ const WORD_SIZE: usize = core::mem::size_of::<u32>();
|
||||
pub mod alloc;
|
||||
#[path = "../zkvm/args.rs"]
|
||||
pub mod args;
|
||||
#[path = "../unix/cmath.rs"]
|
||||
pub mod cmath;
|
||||
pub mod env;
|
||||
#[path = "../unsupported/fs.rs"]
|
||||
pub mod fs;
|
||||
|
@ -25,7 +25,6 @@ pub mod fs;
|
||||
pub mod io;
|
||||
pub mod lazy_box;
|
||||
pub mod process;
|
||||
pub mod thread;
|
||||
pub mod thread_local_dtor;
|
||||
pub mod thread_parking;
|
||||
pub mod wstr;
|
||||
|
@ -417,6 +417,10 @@ impl TcpListener {
|
||||
// it allows up to about 37, but other times it doesn't even
|
||||
// accept 32. There may be a global limitation causing this.
|
||||
let backlog = 20;
|
||||
} else if #[cfg(target_os = "haiku")] {
|
||||
// Haiku does not support a queue length > 32
|
||||
// https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
|
||||
let backlog = 32;
|
||||
} else {
|
||||
// The default for all other platforms
|
||||
let backlog = 128;
|
||||
|
@ -1,18 +0,0 @@
|
||||
use crate::env;
|
||||
use crate::sync::atomic::{self, Ordering};
|
||||
use crate::sys::thread as imp;
|
||||
|
||||
pub fn min_stack() -> usize {
|
||||
static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
|
||||
match MIN.load(Ordering::Relaxed) {
|
||||
0 => {}
|
||||
n => return n - 1,
|
||||
}
|
||||
let amt = env::var_os("RUST_MIN_STACK").and_then(|s| s.to_str().and_then(|s| s.parse().ok()));
|
||||
let amt = amt.unwrap_or(imp::DEFAULT_MIN_STACK_SIZE);
|
||||
|
||||
// 0 is our sentinel value, so ensure that we'll never see 0 after
|
||||
// initialization has run
|
||||
MIN.store(amt + 1, Ordering::Relaxed);
|
||||
amt
|
||||
}
|
@ -160,6 +160,7 @@ mod tests;
|
||||
|
||||
use crate::any::Any;
|
||||
use crate::cell::{OnceCell, UnsafeCell};
|
||||
use crate::env;
|
||||
use crate::ffi::{CStr, CString};
|
||||
use crate::fmt;
|
||||
use crate::io;
|
||||
@ -171,9 +172,9 @@ use crate::panicking;
|
||||
use crate::pin::Pin;
|
||||
use crate::ptr::addr_of_mut;
|
||||
use crate::str;
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sync::Arc;
|
||||
use crate::sys::thread as imp;
|
||||
use crate::sys_common::thread;
|
||||
use crate::sys_common::thread_parking::Parker;
|
||||
use crate::sys_common::{AsInner, IntoInner};
|
||||
use crate::time::{Duration, Instant};
|
||||
@ -468,7 +469,23 @@ impl Builder {
|
||||
{
|
||||
let Builder { name, stack_size } = self;
|
||||
|
||||
let stack_size = stack_size.unwrap_or_else(thread::min_stack);
|
||||
let stack_size = stack_size.unwrap_or_else(|| {
|
||||
static MIN: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
match MIN.load(Ordering::Relaxed) {
|
||||
0 => {}
|
||||
n => return n - 1,
|
||||
}
|
||||
|
||||
let amt = env::var_os("RUST_MIN_STACK")
|
||||
.and_then(|s| s.to_str().and_then(|s| s.parse().ok()))
|
||||
.unwrap_or(imp::DEFAULT_MIN_STACK_SIZE);
|
||||
|
||||
// 0 is our sentinel value, so ensure that we'll never see 0 after
|
||||
// initialization has run
|
||||
MIN.store(amt + 1, Ordering::Relaxed);
|
||||
amt
|
||||
});
|
||||
|
||||
let my_thread = Thread::new(name.map(|name| {
|
||||
CString::new(name).expect("thread name may not contain interior null bytes")
|
||||
@ -1191,17 +1208,17 @@ impl ThreadId {
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_has_atomic = "64")] {
|
||||
use crate::sync::atomic::{AtomicU64, Ordering::Relaxed};
|
||||
use crate::sync::atomic::AtomicU64;
|
||||
|
||||
static COUNTER: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
let mut last = COUNTER.load(Relaxed);
|
||||
let mut last = COUNTER.load(Ordering::Relaxed);
|
||||
loop {
|
||||
let Some(id) = last.checked_add(1) else {
|
||||
exhausted();
|
||||
};
|
||||
|
||||
match COUNTER.compare_exchange_weak(last, id, Relaxed, Relaxed) {
|
||||
match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) {
|
||||
Ok(_) => return ThreadId(NonZero::new(id).unwrap()),
|
||||
Err(id) => last = id,
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(async_closure)]
|
||||
|
||||
struct DropMe;
|
||||
|
||||
trait Impossible {}
|
||||
fn trait_error<T: Impossible>() {}
|
||||
|
||||
pub fn main() {
|
||||
let b = DropMe;
|
||||
let async_closure = async move || {
|
||||
// Type error here taints the environment. This causes us to fallback all
|
||||
// variables to `Error`. This means that when we compute the upvars for the
|
||||
// *outer* coroutine-closure, we don't actually see any upvars since `MemCategorization`
|
||||
// and `ExprUseVisitor`` will bail early when it sees error. This means
|
||||
// that our underlying assumption that the parent and child captures are
|
||||
// compatible ends up being broken, previously leading to an ICE.
|
||||
trait_error::<()>();
|
||||
//~^ ERROR the trait bound `(): Impossible` is not satisfied
|
||||
let _b = b;
|
||||
};
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
error[E0277]: the trait bound `(): Impossible` is not satisfied
|
||||
--> $DIR/dont-ice-when-body-tainted-by-errors.rs:19:23
|
||||
|
|
||||
LL | trait_error::<()>();
|
||||
| ^^ the trait `Impossible` is not implemented for `()`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/dont-ice-when-body-tainted-by-errors.rs:7:1
|
||||
|
|
||||
LL | trait Impossible {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `trait_error`
|
||||
--> $DIR/dont-ice-when-body-tainted-by-errors.rs:8:19
|
||||
|
|
||||
LL | fn trait_error<T: Impossible>() {}
|
||||
| ^^^^^^^^^^ required by this bound in `trait_error`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -46,10 +46,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let ...$e; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -67,10 +67,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let $e...; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/half-open-range-pats-inclusive-no-end.rs:20:17
|
||||
@ -85,10 +81,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let $e..=; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
// https://github.com/rust-lang/rust/issues/123844
|
||||
// An uninitialized refutable let should not suggest `let else`, as it can't be used with deferred
|
||||
// initialization.
|
||||
|
||||
fn main() {
|
||||
let Some(x); //~ ERROR refutable pattern in local binding
|
||||
x = 1;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/uninitialized-refutable-let-issue-123844.rs:6:9
|
||||
|
|
||||
LL | let Some(x);
|
||||
| ^^^^^^^ pattern `None` not covered
|
||||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `Option<i32>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0005`.
|
@ -491,10 +491,6 @@ LL | mac2!(0, 1);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variants that aren't matched
|
||||
|
|
||||
LL | if let $e1..$e2; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:138:17
|
||||
@ -509,10 +505,6 @@ LL | mac2!(0, 1);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variants that aren't matched
|
||||
|
|
||||
LL | if let $e1...$e2; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:142:17
|
||||
@ -527,10 +519,6 @@ LL | mac2!(0, 1);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variants that aren't matched
|
||||
|
|
||||
LL | if let $e1..=$e2; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:151:17
|
||||
@ -545,10 +533,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let ..$e; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:153:17
|
||||
@ -563,10 +547,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let ...$e; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:156:17
|
||||
@ -581,10 +561,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let ..=$e; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:158:17
|
||||
@ -599,10 +575,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let $e..; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:160:17
|
||||
@ -617,10 +589,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let $e...; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recover-range-pats.rs:162:17
|
||||
@ -635,10 +603,6 @@ LL | mac!(0);
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let $e..=; { todo!() }
|
||||
| ++ +++++++++++
|
||||
|
||||
error: aborting due to 69 previous errors
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
//@ run-rustfix
|
||||
#![allow(dead_code)]
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/112007
|
||||
fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
if true {
|
||||
writeln!(w, "`;?` here ->")?;
|
||||
} else {
|
||||
return writeln!(w, "but not here");
|
||||
//~^ ERROR mismatched types
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
macro_rules! baz {
|
||||
($w: expr) => {
|
||||
bar!($w)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! bar {
|
||||
($w: expr) => {
|
||||
writeln!($w, "but not here")
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
if true {
|
||||
writeln!(w, "`;?` here ->")?;
|
||||
} else {
|
||||
return baz!(w);
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,8 +1,16 @@
|
||||
//@ run-rustfix
|
||||
#![allow(dead_code)]
|
||||
// Check that we don't leak stdlib implementation details through suggestions.
|
||||
// Also check that the suggestion provided tries as hard as it can to see through local macros.
|
||||
//
|
||||
// FIXME(jieyouxu): this test is NOT run-rustfix because this test contains conflicting
|
||||
// MaybeIncorrect suggestions:
|
||||
//
|
||||
// 1. `return ... ;`
|
||||
// 2. `?`
|
||||
//
|
||||
// when the suggestions are applied to the same file, it becomes uncompilable.
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/112007
|
||||
fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
if true {
|
||||
writeln!(w, "`;?` here ->")?;
|
||||
} else {
|
||||
@ -25,7 +33,7 @@ macro_rules! bar {
|
||||
}
|
||||
}
|
||||
|
||||
fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
pub fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
if true {
|
||||
writeln!(w, "`;?` here ->")?;
|
||||
} else {
|
||||
@ -34,4 +42,4 @@ fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
pub fn main() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:9:9
|
||||
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:17:9
|
||||
|
|
||||
LL | / if true {
|
||||
LL | | writeln!(w, "`;?` here ->")?;
|
||||
@ -21,9 +21,13 @@ help: you might have meant to return this value
|
||||
|
|
||||
LL | return writeln!(w, "but not here");
|
||||
| ++++++ +
|
||||
help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
|
||||
|
|
||||
LL | writeln!(w, "but not here")?
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:32:9
|
||||
--> $DIR/issue-112007-leaked-writeln-macro-internals.rs:40:9
|
||||
|
|
||||
LL | / if true {
|
||||
LL | | writeln!(w, "`;?` here ->")?;
|
||||
@ -44,6 +48,10 @@ help: you might have meant to return this value
|
||||
|
|
||||
LL | return baz!(w);
|
||||
| ++++++ +
|
||||
help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
|
||||
|
|
||||
LL | writeln!($w, "but not here")?
|
||||
| +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
22
tests/ui/typeck/question-mark-operator-suggestion-span.rs
Normal file
22
tests/ui/typeck/question-mark-operator-suggestion-span.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Check that we don't construct a span for `?` suggestions that point into non-local macros
|
||||
// like into the stdlib where the user has no control over.
|
||||
//
|
||||
// FIXME(jieyouxu): this test is currently NOT run-rustfix because there are conflicting
|
||||
// MaybeIncorrect suggestions:
|
||||
//
|
||||
// 1. adding `return ... ;`, and
|
||||
// 2. adding `?`.
|
||||
//
|
||||
// When rustfix puts those together, the fixed file now contains uncompilable code.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
if true {
|
||||
writeln!(w, "`;?` here ->")?;
|
||||
} else {
|
||||
writeln!(w, "but not here")
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/question-mark-operator-suggestion-span.rs:18:9
|
||||
|
|
||||
LL | / if true {
|
||||
LL | | writeln!(w, "`;?` here ->")?;
|
||||
LL | | } else {
|
||||
LL | | writeln!(w, "but not here")
|
||||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____- expected this to be `()`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found enum `Result<(), std::fmt::Error>`
|
||||
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider using a semicolon here
|
||||
|
|
||||
LL | };
|
||||
| +
|
||||
help: you might have meant to return this value
|
||||
|
|
||||
LL | return writeln!(w, "but not here");
|
||||
| ++++++ +
|
||||
help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
|
||||
|
|
||||
LL | writeln!(w, "but not here")?
|
||||
| +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
x
Reference in New Issue
Block a user