Skip to content

Commit

Permalink
Auto merge of #97939 - JohnTitor:rollup-79pxupb, r=JohnTitor
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Jun 10, 2022
2 parents 3dea003 + 9d25bc3 commit f19ccc2
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 29 deletions.
29 changes: 17 additions & 12 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
119 changes: 119 additions & 0 deletions library/core/src/future/into_future.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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;
Expand Down
23 changes: 10 additions & 13 deletions library/panic_unwind/src/emcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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;
}
2 changes: 0 additions & 2 deletions library/std/src/io/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 14 additions & 0 deletions src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion src/test/ui/hrtb/hrtb-just-for-static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// check-pass
#![feature(lint_reasons)]

#[expect(drop_bounds)]
fn trigger_rustc_lints<T: Drop>() {
}

fn main() {}

0 comments on commit f19ccc2

Please sign in to comment.