Auto merge of #97939 - JohnTitor:rollup-79pxupb, r=JohnTitor
Rollup of 6 pull requests Successful merges: - #97718 (Fix `delayed_good_path_bug` ice for expected diagnostics (RFC 2383)) - #97876 (update docs for `std::future::IntoFuture`) - #97888 (Don't use __gxx_personality_v0 in panic_unwind on emscripten target) - #97922 (Remove redundant calls to reserve in impl Write for VecDeque) - #97927 (Do not introduce bindings for types and consts in HRTB.) - #97937 (Fix a typo in `test/ui/hrtb/hrtb-just-for-static.rs`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f19ccc2e8d
9 changed files with 182 additions and 29 deletions
|
@ -400,6 +400,9 @@ struct HandlerInner {
|
|||
emitter: Box<dyn Emitter + sync::Send>,
|
||||
delayed_span_bugs: Vec<Diagnostic>,
|
||||
delayed_good_path_bugs: Vec<DelayedDiagnostic>,
|
||||
/// This flag indicates that an expected diagnostic was emitted and suppressed.
|
||||
/// This is used for the `delayed_good_path_bugs` check.
|
||||
suppressed_expected_diag: bool,
|
||||
|
||||
/// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
|
||||
/// emitting the same diagnostic with extended help (`--teach`) twice, which
|
||||
|
@ -495,7 +498,7 @@ impl Drop for HandlerInner {
|
|||
// instead of "require some error happened". Sadly that isn't ideal, as
|
||||
// lints can be `#[allow]`'d, potentially leading to this triggering.
|
||||
// Also, "good path" should be replaced with a better naming.
|
||||
if !self.has_any_message() {
|
||||
if !self.has_any_message() && !self.suppressed_expected_diag {
|
||||
let bugs = std::mem::replace(&mut self.delayed_good_path_bugs, Vec::new());
|
||||
self.flush_delayed(
|
||||
bugs.into_iter().map(DelayedDiagnostic::decorate),
|
||||
|
@ -577,6 +580,7 @@ impl Handler {
|
|||
emitter,
|
||||
delayed_span_bugs: Vec::new(),
|
||||
delayed_good_path_bugs: Vec::new(),
|
||||
suppressed_expected_diag: false,
|
||||
taught_diagnostics: Default::default(),
|
||||
emitted_diagnostic_codes: Default::default(),
|
||||
emitted_diagnostics: Default::default(),
|
||||
|
@ -1000,20 +1004,20 @@ impl Handler {
|
|||
let mut inner = self.inner.borrow_mut();
|
||||
let diags = std::mem::take(&mut inner.unstable_expect_diagnostics);
|
||||
inner.check_unstable_expect_diagnostics = true;
|
||||
if diags.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
for mut diag in diags.into_iter() {
|
||||
diag.update_unstable_expectation_id(unstable_to_stable);
|
||||
if !diags.is_empty() {
|
||||
inner.suppressed_expected_diag = true;
|
||||
for mut diag in diags.into_iter() {
|
||||
diag.update_unstable_expectation_id(unstable_to_stable);
|
||||
|
||||
let stable_id = diag
|
||||
.level
|
||||
.get_expectation_id()
|
||||
.expect("all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`");
|
||||
inner.fulfilled_expectations.insert(stable_id);
|
||||
let stable_id = diag
|
||||
.level
|
||||
.get_expectation_id()
|
||||
.expect("all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`");
|
||||
inner.fulfilled_expectations.insert(stable_id);
|
||||
|
||||
(*TRACK_DIAGNOSTICS)(&diag);
|
||||
(*TRACK_DIAGNOSTICS)(&diag);
|
||||
}
|
||||
}
|
||||
|
||||
inner
|
||||
|
@ -1100,6 +1104,7 @@ impl HandlerInner {
|
|||
(*TRACK_DIAGNOSTICS)(diagnostic);
|
||||
|
||||
if let Level::Expect(expectation_id) = diagnostic.level {
|
||||
self.suppressed_expected_diag = true;
|
||||
self.fulfilled_expectations.insert(expectation_id);
|
||||
return None;
|
||||
} else if diagnostic.level == Allow {
|
||||
|
|
|
@ -1981,7 +1981,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
continue;
|
||||
}
|
||||
};
|
||||
let res = Res::Def(def_kind, def_id.to_def_id());
|
||||
|
||||
let res = match kind {
|
||||
ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()),
|
||||
NormalRibKind => Res::Err,
|
||||
_ => bug!("Unexpected rib kind {:?}", kind),
|
||||
};
|
||||
self.r.record_partial_res(param.id, PartialRes::new(res));
|
||||
rib.bindings.insert(ident, res);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,109 @@
|
|||
use crate::future::Future;
|
||||
|
||||
/// Conversion into a `Future`.
|
||||
///
|
||||
/// By implementing `Intofuture` for a type, you define how it will be
|
||||
/// converted to a future.
|
||||
///
|
||||
/// # `.await` desugaring
|
||||
///
|
||||
/// The `.await` keyword desugars into a call to `IntoFuture::into_future`
|
||||
/// first before polling the future to completion. `IntoFuture` is implemented
|
||||
/// for all `T: Future` which means the `into_future` method will be available
|
||||
/// on all futures.
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(into_future)]
|
||||
///
|
||||
/// use std::future::IntoFuture;
|
||||
///
|
||||
/// # async fn foo() {
|
||||
/// let v = async { "meow" };
|
||||
/// let mut fut = v.into_future();
|
||||
/// assert_eq!("meow", fut.await);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// # Async builders
|
||||
///
|
||||
/// When implementing futures manually there will often be a choice between
|
||||
/// implementing `Future` or `IntoFuture` for a type. Implementing `Future` is a
|
||||
/// good choice in most cases. But implementing `IntoFuture` is most useful when
|
||||
/// implementing "async builder" types, which allows the type to be modified
|
||||
/// multiple times before being `.await`ed.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(into_future)]
|
||||
///
|
||||
/// use std::future::{ready, Ready, IntoFuture};
|
||||
///
|
||||
/// /// Eventually multiply two numbers
|
||||
/// pub struct Multiply {
|
||||
/// num: u16,
|
||||
/// factor: u16,
|
||||
/// }
|
||||
///
|
||||
/// impl Multiply {
|
||||
/// /// Construct a new instance of `Multiply`.
|
||||
/// pub fn new(num: u16, factor: u16) -> Self {
|
||||
/// Self { num, factor }
|
||||
/// }
|
||||
///
|
||||
/// /// Set the number to multiply by the factor.
|
||||
/// pub fn number(mut self, num: u16) -> Self {
|
||||
/// self.num = num;
|
||||
/// self
|
||||
/// }
|
||||
///
|
||||
/// /// Set the factor to multiply the number with.
|
||||
/// pub fn factor(mut self, factor: u16) -> Self {
|
||||
/// self.factor = factor;
|
||||
/// self
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl IntoFuture for Multiply {
|
||||
/// type Output = u16;
|
||||
/// type IntoFuture = Ready<Self::Output>;
|
||||
///
|
||||
/// fn into_future(self) -> Self::IntoFuture {
|
||||
/// ready(self.num * self.factor)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // NOTE: Rust does not yet have an `async fn main` function, that functionality
|
||||
/// // currently only exists in the ecosystem.
|
||||
/// async fn run() {
|
||||
/// let num = Multiply::new(0, 0) // initialize the builder to number: 0, factor: 0
|
||||
/// .number(2) // change the number to 2
|
||||
/// .factor(2) // change the factor to 2
|
||||
/// .await; // convert to future and .await
|
||||
///
|
||||
/// assert_eq!(num, 4);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Usage in trait bounds
|
||||
///
|
||||
/// Using `IntoFuture` in trait bounds allows a function to be generic over both
|
||||
/// `Future` and `IntoFuture`. This is convenient for users of the function, so
|
||||
/// when they are using it they don't have to make an extra call to
|
||||
/// `IntoFuture::into_future` to obtain an instance of `Future`:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(into_future)]
|
||||
///
|
||||
/// use std::future::IntoFuture;
|
||||
///
|
||||
/// /// Convert the output of a future to a string.
|
||||
/// async fn fut_to_string<Fut>(fut: Fut) -> String
|
||||
/// where
|
||||
/// Fut: IntoFuture,
|
||||
/// Fut::Output: std::fmt::Debug,
|
||||
/// {
|
||||
/// format!("{:?}", fut.await)
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
pub trait IntoFuture {
|
||||
/// The output that the future will produce on completion.
|
||||
|
@ -12,6 +115,22 @@ pub trait IntoFuture {
|
|||
type IntoFuture: Future<Output = Self::Output>;
|
||||
|
||||
/// Creates a future from a value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(into_future)]
|
||||
///
|
||||
/// use std::future::IntoFuture;
|
||||
///
|
||||
/// # async fn foo() {
|
||||
/// let v = async { "meow" };
|
||||
/// let mut fut = v.into_future();
|
||||
/// assert_eq!("meow", fut.await);
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
#[lang = "into_future"]
|
||||
fn into_future(self) -> Self::IntoFuture;
|
||||
|
|
|
@ -105,15 +105,19 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void {
|
|||
}
|
||||
}
|
||||
|
||||
// This is required by the compiler to exist (e.g., it's a lang item), but it's
|
||||
// never actually called by the compiler. Emscripten EH doesn't use a
|
||||
// personality function at all, it instead uses __cxa_find_matching_catch.
|
||||
// Wasm error handling would use __gxx_personality_wasm0.
|
||||
#[lang = "eh_personality"]
|
||||
unsafe extern "C" fn rust_eh_personality(
|
||||
version: c_int,
|
||||
actions: uw::_Unwind_Action,
|
||||
exception_class: uw::_Unwind_Exception_Class,
|
||||
exception_object: *mut uw::_Unwind_Exception,
|
||||
context: *mut uw::_Unwind_Context,
|
||||
_version: c_int,
|
||||
_actions: uw::_Unwind_Action,
|
||||
_exception_class: uw::_Unwind_Exception_Class,
|
||||
_exception_object: *mut uw::_Unwind_Exception,
|
||||
_context: *mut uw::_Unwind_Context,
|
||||
) -> uw::_Unwind_Reason_Code {
|
||||
__gxx_personality_v0(version, actions, exception_class, exception_object, context)
|
||||
core::intrinsics::abort()
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
@ -125,11 +129,4 @@ extern "C" {
|
|||
tinfo: *const TypeInfo,
|
||||
dest: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void,
|
||||
) -> !;
|
||||
fn __gxx_personality_v0(
|
||||
version: c_int,
|
||||
actions: uw::_Unwind_Action,
|
||||
exception_class: uw::_Unwind_Exception_Class,
|
||||
exception_object: *mut uw::_Unwind_Exception,
|
||||
context: *mut uw::_Unwind_Context,
|
||||
) -> uw::_Unwind_Reason_Code;
|
||||
}
|
||||
|
|
|
@ -441,14 +441,12 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
|
|||
impl<A: Allocator> Write for VecDeque<u8, A> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.reserve(buf.len());
|
||||
self.extend(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.reserve(buf.len());
|
||||
self.extend(buf);
|
||||
Ok(())
|
||||
}
|
||||
|
|
7
src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs
Normal file
7
src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
fn a() where for<T> T: Copy {}
|
||||
//~^ ERROR only lifetime parameters can be used in this context
|
||||
|
||||
fn b() where for<const C: usize> [(); C]: Copy {}
|
||||
//~^ ERROR only lifetime parameters can be used in this context
|
||||
|
||||
fn main() {}
|
14
src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
Normal file
14
src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error: only lifetime parameters can be used in this context
|
||||
--> $DIR/hrtb-wrong-kind.rs:1:18
|
||||
|
|
||||
LL | fn a() where for<T> T: Copy {}
|
||||
| ^
|
||||
|
||||
error: only lifetime parameters can be used in this context
|
||||
--> $DIR/hrtb-wrong-kind.rs:4:24
|
||||
|
|
||||
LL | fn b() where for<const C: usize> [(); C]: Copy {}
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -24,7 +24,7 @@ fn give_static() {
|
|||
want_hrtb::<StaticInt>() //~ ERROR
|
||||
}
|
||||
|
||||
// AnyInt implements Foo<&'a isize> for any 'a, so it is a match.
|
||||
// &'a u32 only implements Foo<&'a isize> for specific 'a, so it is an error.
|
||||
impl<'a> Foo<&'a isize> for &'a u32 { }
|
||||
fn give_some<'a>() {
|
||||
want_hrtb::<&'a u32>()
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// check-pass
|
||||
#![feature(lint_reasons)]
|
||||
|
||||
#[expect(drop_bounds)]
|
||||
fn trigger_rustc_lints<T: Drop>() {
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Add table
Reference in a new issue