mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
Auto merge of #61527 - pietroalbini:rollup-vhxyqlk, r=pietroalbini
Rollup of 5 pull requests Successful merges: - #61069 (Make MIR drop terminators borrow the dropped location) - #61453 (Remove unneeded feature attr from atomic integers doctests) - #61488 (Fix NLL typeck ICEs) - #61500 (Fix regression 61475) - #61523 (Hide gen_future API from documentation) Failed merges: r? @ghost
This commit is contained in:
commit
81eb15210a
@ -1899,7 +1899,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"i8", "../../../std/primitive.i8.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_min, atomic_max,
|
||||
1,
|
||||
"AtomicI8::new(0)",
|
||||
@ -1915,7 +1915,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"u8", "../../../std/primitive.u8.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_umin, atomic_umax,
|
||||
1,
|
||||
"AtomicU8::new(0)",
|
||||
@ -1931,7 +1931,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"i16", "../../../std/primitive.i16.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_min, atomic_max,
|
||||
2,
|
||||
"AtomicI16::new(0)",
|
||||
@ -1947,7 +1947,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"u16", "../../../std/primitive.u16.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_umin, atomic_umax,
|
||||
2,
|
||||
"AtomicU16::new(0)",
|
||||
@ -1963,7 +1963,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"i32", "../../../std/primitive.i32.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_min, atomic_max,
|
||||
4,
|
||||
"AtomicI32::new(0)",
|
||||
@ -1979,7 +1979,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"u32", "../../../std/primitive.u32.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_umin, atomic_umax,
|
||||
4,
|
||||
"AtomicU32::new(0)",
|
||||
@ -1995,7 +1995,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"i64", "../../../std/primitive.i64.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_min, atomic_max,
|
||||
8,
|
||||
"AtomicI64::new(0)",
|
||||
@ -2011,7 +2011,7 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
"u64", "../../../std/primitive.u64.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
"",
|
||||
atomic_umin, atomic_umax,
|
||||
8,
|
||||
"AtomicU64::new(0)",
|
||||
|
@ -115,13 +115,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
/// A hacky variant of `canonicalize_query` that does not
|
||||
/// canonicalize `'static`. Unfortunately, the existing leak
|
||||
/// check treaks `'static` differently in some cases (see also
|
||||
/// check treats `'static` differently in some cases (see also
|
||||
/// #33684), so if we are performing an operation that may need to
|
||||
/// prove "leak-check" related things, we leave `'static`
|
||||
/// alone.
|
||||
///
|
||||
/// `'static` is also special cased when winnowing candidates when
|
||||
/// selecting implementation candidates, so we also have to leave `'static`
|
||||
/// alone for queries that do selection.
|
||||
//
|
||||
// FIXME(#48536): once we have universes, we can remove this and just use
|
||||
// `canonicalize_query`.
|
||||
// FIXME(#48536): once the above issues are resolved, we can remove this
|
||||
// and just use `canonicalize_query`.
|
||||
pub fn canonicalize_hr_query_hack<V>(
|
||||
&self,
|
||||
value: &V,
|
||||
|
@ -145,7 +145,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
let gcx = self.infcx.tcx.global_tcx();
|
||||
|
||||
let mut orig_values = OriginalQueryValues::default();
|
||||
let c_data = self.infcx.canonicalize_query(
|
||||
// HACK(matthewjasper) `'static` is special-cased in selection,
|
||||
// so we cannot canonicalize it.
|
||||
let c_data = self.infcx.canonicalize_hr_query_hack(
|
||||
&self.param_env.and(*data), &mut orig_values);
|
||||
debug!("QueryNormalizer: c_data = {:#?}", c_data);
|
||||
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
|
||||
|
@ -334,6 +334,13 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
|
||||
|
||||
match outlives_bound {
|
||||
OutlivesBound::RegionSubRegion(r1, r2) => {
|
||||
// `where Type:` is lowered to `where Type: 'empty` so that
|
||||
// we check `Type` is well formed, but there's no use for
|
||||
// this bound here.
|
||||
if let ty::ReEmpty = r1 {
|
||||
return;
|
||||
}
|
||||
|
||||
// The bound says that `r1 <= r2`; we store `r2: r1`.
|
||||
let r1 = self.universal_regions.to_region_vid(r1);
|
||||
let r2 = self.universal_regions.to_region_vid(r2);
|
||||
|
@ -56,9 +56,20 @@ impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
|
||||
fn terminator_effect(&self,
|
||||
sets: &mut BlockSets<'_, Local>,
|
||||
loc: Location) {
|
||||
let terminator = self.mir[loc.block].terminator();
|
||||
BorrowedLocalsVisitor {
|
||||
sets,
|
||||
}.visit_terminator(self.mir[loc.block].terminator(), loc);
|
||||
}.visit_terminator(terminator, loc);
|
||||
match &terminator.kind {
|
||||
// Drop terminators borrows the location
|
||||
TerminatorKind::Drop { location, .. } |
|
||||
TerminatorKind::DropAndReplace { location, .. } => {
|
||||
if let Some(local) = find_local(location) {
|
||||
sets.gen(local);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate_call_return(
|
||||
|
@ -16,12 +16,14 @@ pub use core::future::*;
|
||||
///
|
||||
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
|
||||
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
|
||||
GenFuture(x)
|
||||
}
|
||||
|
||||
/// A wrapper around generators used to implement `Future` for `async`/`await` code.
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
struct GenFuture<T: Generator<Yield = ()>>(T);
|
||||
@ -30,6 +32,7 @@ struct GenFuture<T: Generator<Yield = ()>>(T);
|
||||
// self-referential borrows in the underlying generator.
|
||||
impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
|
||||
type Output = T::Return;
|
||||
@ -57,6 +60,7 @@ impl Drop for SetOnDrop {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
/// Sets the thread-local task context used by async/await futures.
|
||||
pub fn set_task_context<F, R>(cx: &mut Context<'_>, f: F) -> R
|
||||
@ -74,6 +78,7 @@ where
|
||||
f()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
/// Retrieves the thread-local task context used by async/await futures.
|
||||
///
|
||||
@ -105,6 +110,7 @@ where
|
||||
unsafe { f(cx_ptr.as_mut()) }
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
/// Polls a future in the current thread-local task waker.
|
||||
pub fn poll_with_tls_context<F>(f: Pin<&mut F>) -> Poll<F::Output>
|
||||
|
@ -1657,8 +1657,8 @@ impl<'a> Parser<'a> {
|
||||
path = self.parse_path(PathStyle::Type)?;
|
||||
path_span = path_lo.to(self.prev_span);
|
||||
} else {
|
||||
path = ast::Path { segments: Vec::new(), span: DUMMY_SP };
|
||||
path_span = self.span.to(self.span);
|
||||
path = ast::Path { segments: Vec::new(), span: path_span };
|
||||
}
|
||||
|
||||
// See doc comment for `unmatched_angle_bracket_count`.
|
||||
@ -2844,7 +2844,11 @@ impl<'a> Parser<'a> {
|
||||
// want to keep their span info to improve diagnostics in these cases in a later stage.
|
||||
(true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
|
||||
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
|
||||
(true, Some(AssocOp::Add)) => { // `{ 42 } + 42
|
||||
(true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475)
|
||||
(true, Some(AssocOp::Add)) // `{ 42 } + 42
|
||||
// If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
|
||||
// `if x { a } else { b } && if y { c } else { d }`
|
||||
if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
|
||||
// These cases are ambiguous and can't be identified in the parser alone
|
||||
let sp = self.sess.source_map().start_point(self.span);
|
||||
self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
|
||||
@ -5298,7 +5302,7 @@ impl<'a> Parser<'a> {
|
||||
let mut where_clause = WhereClause {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
span: DUMMY_SP,
|
||||
span: self.prev_span.to(self.prev_span),
|
||||
};
|
||||
|
||||
if !self.eat_keyword(kw::Where) {
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(integer_atomics)]
|
||||
|
||||
// compile-pass
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
|
15
src/test/ui/issues/issue-61475.rs
Normal file
15
src/test/ui/issues/issue-61475.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// run-pass
|
||||
#![allow(dead_code)]
|
||||
|
||||
enum E {
|
||||
A, B
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match &&E::A {
|
||||
&&E::A => {
|
||||
}
|
||||
&&E::B => {
|
||||
}
|
||||
};
|
||||
}
|
11
src/test/ui/nll/empty-type-predicate.rs
Normal file
11
src/test/ui/nll/empty-type-predicate.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Regression test for #61315
|
||||
//
|
||||
// `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for
|
||||
// the unexpected region.
|
||||
|
||||
// compile-pass
|
||||
|
||||
trait T {}
|
||||
fn f() where dyn T: {}
|
||||
|
||||
fn main() {}
|
34
src/test/ui/nll/issue-61311-normalize.rs
Normal file
34
src/test/ui/nll/issue-61311-normalize.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Regression test for #61311
|
||||
// We would ICE after failing to normalize `Self::Proj` in the `impl` below.
|
||||
|
||||
// compile-pass
|
||||
|
||||
pub struct Unit;
|
||||
trait Obj {}
|
||||
|
||||
trait Bound {}
|
||||
impl Bound for Unit {}
|
||||
|
||||
pub trait HasProj {
|
||||
type Proj;
|
||||
}
|
||||
|
||||
impl<T> HasProj for T {
|
||||
type Proj = Unit;
|
||||
}
|
||||
|
||||
trait HasProjFn {
|
||||
type Proj;
|
||||
fn the_fn(_: Self::Proj);
|
||||
}
|
||||
|
||||
impl HasProjFn for Unit
|
||||
where
|
||||
Box<dyn Obj + 'static>: HasProj,
|
||||
<Box<dyn Obj + 'static> as HasProj>::Proj: Bound,
|
||||
{
|
||||
type Proj = Unit;
|
||||
fn the_fn(_: Self::Proj) {}
|
||||
}
|
||||
|
||||
fn main() {}
|
160
src/test/ui/nll/issue-61320-normalize.rs
Normal file
160
src/test/ui/nll/issue-61320-normalize.rs
Normal file
@ -0,0 +1,160 @@
|
||||
// Regression test for #61320
|
||||
// This is the same issue as #61311, just a larger test case.
|
||||
|
||||
// compile-pass
|
||||
|
||||
pub struct AndThen<A, B, F>
|
||||
where
|
||||
A: Future,
|
||||
B: IntoFuture,
|
||||
{
|
||||
state: (A, B::Future, F),
|
||||
}
|
||||
|
||||
pub struct FutureResult<T, E> {
|
||||
inner: Option<Result<T, E>>,
|
||||
}
|
||||
|
||||
impl<T, E> Future for FutureResult<T, E> {
|
||||
type Item = T;
|
||||
type Error = E;
|
||||
|
||||
fn poll(&mut self) -> Poll<T, E> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub type Poll<T, E> = Result<T, E>;
|
||||
|
||||
impl<A, B, F> Future for AndThen<A, B, F>
|
||||
where
|
||||
A: Future,
|
||||
B: IntoFuture<Error = A::Error>,
|
||||
F: FnOnce(A::Item) -> B,
|
||||
{
|
||||
type Item = B::Item;
|
||||
type Error = B::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<B::Item, B::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Future {
|
||||
type Item;
|
||||
|
||||
type Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error>;
|
||||
|
||||
fn and_then<F, B>(self, f: F) -> AndThen<Self, B, F>
|
||||
where
|
||||
F: FnOnce(Self::Item) -> B,
|
||||
B: IntoFuture<Error = Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoFuture {
|
||||
/// The future that this type can be converted into.
|
||||
type Future: Future<Item = Self::Item, Error = Self::Error>;
|
||||
|
||||
/// The item that the future may resolve with.
|
||||
type Item;
|
||||
/// The error that the future may resolve with.
|
||||
type Error;
|
||||
|
||||
/// Consumes this object and produces a future.
|
||||
fn into_future(self) -> Self::Future;
|
||||
}
|
||||
|
||||
impl<F: Future> IntoFuture for F {
|
||||
type Future = F;
|
||||
type Item = F::Item;
|
||||
type Error = F::Error;
|
||||
|
||||
fn into_future(self) -> F {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: ?Sized + Future> Future for ::std::boxed::Box<F> {
|
||||
type Item = F::Item;
|
||||
type Error = F::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
(**self).poll()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> IntoFuture for Result<T, E> {
|
||||
type Future = FutureResult<T, E>;
|
||||
type Item = T;
|
||||
type Error = E;
|
||||
|
||||
fn into_future(self) -> FutureResult<T, E> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
struct Request<T>(T);
|
||||
|
||||
trait RequestContext {}
|
||||
impl<T> RequestContext for T {}
|
||||
struct NoContext;
|
||||
impl AsRef<NoContext> for NoContext {
|
||||
fn as_ref(&self) -> &Self {
|
||||
&NoContext
|
||||
}
|
||||
}
|
||||
|
||||
type BoxedError = Box<dyn std::error::Error + Send + Sync>;
|
||||
type DefaultFuture<T, E> = Box<dyn Future<Item = T, Error = E> + Send>;
|
||||
|
||||
trait Guard: Sized {
|
||||
type Result: IntoFuture<Item = Self, Error = BoxedError>;
|
||||
fn from_request(request: &Request<()>) -> Self::Result;
|
||||
}
|
||||
|
||||
trait FromRequest: Sized {
|
||||
type Context;
|
||||
type Future: Future<Item = Self, Error = BoxedError> + Send;
|
||||
fn from_request(request: Request<()>) -> Self::Future;
|
||||
}
|
||||
|
||||
struct MyGuard;
|
||||
impl Guard for MyGuard {
|
||||
type Result = Result<Self, BoxedError>;
|
||||
fn from_request(_request: &Request<()>) -> Self::Result {
|
||||
Ok(MyGuard)
|
||||
}
|
||||
}
|
||||
|
||||
struct Generic<I> {
|
||||
_inner: I,
|
||||
}
|
||||
|
||||
impl<I> FromRequest for Generic<I>
|
||||
where
|
||||
MyGuard: Guard,
|
||||
<MyGuard as Guard>::Result: IntoFuture<Item = MyGuard, Error = BoxedError>,
|
||||
<<MyGuard as Guard>::Result as IntoFuture>::Future: Send,
|
||||
I: FromRequest<Context = NoContext>,
|
||||
{
|
||||
type Future = DefaultFuture<Self, BoxedError>;
|
||||
type Context = NoContext;
|
||||
fn from_request(headers: Request<()>) -> DefaultFuture<Self, BoxedError> {
|
||||
let _future = <MyGuard as Guard>::from_request(&headers)
|
||||
.into_future()
|
||||
.and_then(move |_| {
|
||||
<I as FromRequest>::from_request(headers)
|
||||
.into_future()
|
||||
.and_then(move |fld_inner| Ok(Generic { _inner: fld_inner }).into_future())
|
||||
});
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user