Skip to content

Commit

Permalink
Auto merge of rust-lang#78661 - JohnTitor:rollup-er2isja, r=JohnTitor
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - rust-lang#78606 (Clarify handling of final line ending in str::lines())
 - rust-lang#78610 (Do not remove tokens before AST json serialization)
 - rust-lang#78620 (Trivial fixes to bitwise operator documentation)
 - rust-lang#78627 (Point out that total_cmp is no strict superset of partial comparison)
 - rust-lang#78637 (Add fetch_update methods to AtomicBool and AtomicPtr)

Failed merges:

r? `@ghost`
  • Loading branch information
bors committed Nov 2, 2020
2 parents 234099d + 50d7716 commit 4051473
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 158 deletions.
5 changes: 3 additions & 2 deletions compiler/rustc_ast/src/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,9 @@ impl fmt::Debug for LazyTokenStream {
}

impl<S: Encoder> Encodable<S> for LazyTokenStream {
fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
panic!("Attempted to encode LazyTokenStream");
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
// Used by AST json printing.
Encodable::encode(&self.create_token_stream(), s)
}
}

Expand Down
90 changes: 2 additions & 88 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use crate::interface::{Compiler, Result};
use crate::proc_macro_decls;
use crate::util;

use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, token, visit};
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::{self as ast, visit};
use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
Expand Down Expand Up @@ -37,7 +36,6 @@ use rustc_span::symbol::Symbol;
use rustc_span::{FileName, RealFileName};
use rustc_trait_selection::traits;
use rustc_typeck as typeck;
use smallvec::SmallVec;
use tracing::{info, warn};

use rustc_serialize::json;
Expand All @@ -52,82 +50,6 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::{env, fs, iter, mem};

/// Remove alls `LazyTokenStreams` from an AST struct
/// Normally, this is done during AST lowering. However,
/// printing the AST JSON requires us to serialize
/// the entire AST, and we don't want to serialize
/// a `LazyTokenStream`.
struct TokenStripper;
impl mut_visit::MutVisitor for TokenStripper {
fn flat_map_item(&mut self, mut i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
i.tokens = None;
mut_visit::noop_flat_map_item(i, self)
}
fn flat_map_foreign_item(
&mut self,
mut i: P<ast::ForeignItem>,
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
i.tokens = None;
mut_visit::noop_flat_map_foreign_item(i, self)
}
fn flat_map_trait_item(
&mut self,
mut i: P<ast::AssocItem>,
) -> SmallVec<[P<ast::AssocItem>; 1]> {
i.tokens = None;
mut_visit::noop_flat_map_assoc_item(i, self)
}
fn flat_map_impl_item(&mut self, mut i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
i.tokens = None;
mut_visit::noop_flat_map_assoc_item(i, self)
}
fn visit_block(&mut self, b: &mut P<ast::Block>) {
b.tokens = None;
mut_visit::noop_visit_block(b, self);
}
fn flat_map_stmt(&mut self, mut stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
stmt.tokens = None;
mut_visit::noop_flat_map_stmt(stmt, self)
}
fn visit_pat(&mut self, p: &mut P<ast::Pat>) {
p.tokens = None;
mut_visit::noop_visit_pat(p, self);
}
fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
ty.tokens = None;
mut_visit::noop_visit_ty(ty, self);
}
fn visit_attribute(&mut self, attr: &mut ast::Attribute) {
attr.tokens = None;
if let ast::AttrKind::Normal(ast::AttrItem { tokens, .. }) = &mut attr.kind {
*tokens = None;
}
mut_visit::noop_visit_attribute(attr, self);
}

fn visit_interpolated(&mut self, nt: &mut token::Nonterminal) {
if let token::Nonterminal::NtMeta(meta) = nt {
meta.tokens = None;
}
// Handles all of the other cases
mut_visit::noop_visit_interpolated(nt, self);
}

fn visit_path(&mut self, p: &mut ast::Path) {
p.tokens = None;
mut_visit::noop_visit_path(p, self);
}
fn visit_vis(&mut self, vis: &mut ast::Visibility) {
vis.tokens = None;
mut_visit::noop_visit_vis(vis, self);
}
fn visit_expr(&mut self, e: &mut P<ast::Expr>) {
e.tokens = None;
mut_visit::noop_visit_expr(e, self);
}
fn visit_mac(&mut self, _mac: &mut ast::MacCall) {}
}

pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
let krate = sess.time("parse_crate", || match input {
Input::File(file) => parse_crate_from_file(file, &sess.parse_sess),
Expand All @@ -137,10 +59,6 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
})?;

if sess.opts.debugging_opts.ast_json_noexpand {
// Set any `token` fields to `None` before
// we display the AST.
let mut krate = krate.clone();
TokenStripper.visit_crate(&mut krate);
println!("{}", json::as_json(&krate));
}

Expand Down Expand Up @@ -464,10 +382,6 @@ fn configure_and_expand_inner<'a>(
}

if sess.opts.debugging_opts.ast_json {
// Set any `token` fields to `None` before
// we display the AST.
let mut krate = krate.clone();
TokenStripper.visit_crate(&mut krate);
println!("{}", json::as_json(&krate));
}

Expand Down
4 changes: 4 additions & 0 deletions library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,10 @@ impl f32 {
/// - Positive signaling NaN
/// - Positive quiet NaN
///
/// Note that this function does not always agree with the [`PartialOrd`]
/// and [`PartialEq`] implementations of `f32`. In particular, they regard
/// negative and positive zero as equal, while `total_cmp` doesn't.
///
/// # Example
/// ```
/// #![feature(total_cmp)]
Expand Down
4 changes: 4 additions & 0 deletions library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,10 @@ impl f64 {
/// - Positive signaling NaN
/// - Positive quiet NaN
///
/// Note that this function does not always agree with the [`PartialOrd`]
/// and [`PartialEq`] implementations of `f64`. In particular, they regard
/// negative and positive zero as equal, while `total_cmp` doesn't.
///
/// # Example
/// ```
/// #![feature(total_cmp)]
Expand Down
35 changes: 23 additions & 12 deletions library/core/src/ops/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// fn bitand(self, Self(rhs): Self) -> Self::Output {
/// let Self(lhs) = self;
/// assert_eq!(lhs.len(), rhs.len());
/// Self(lhs.iter()
/// Self(
/// lhs.iter()
/// .zip(rhs.iter())
/// .map(|(x, y)| *x && *y)
/// .collect())
/// .map(|(x, y)| *x & *y)
/// .collect()
/// )
/// }
/// }
///
Expand Down Expand Up @@ -207,7 +209,12 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// fn bitor(self, Self(rhs): Self) -> Self::Output {
/// let Self(lhs) = self;
/// assert_eq!(lhs.len(), rhs.len());
/// Self(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect())
/// Self(
/// lhs.iter()
/// .zip(rhs.iter())
/// .map(|(x, y)| *x | *y)
/// .collect()
/// )
/// }
/// }
///
Expand Down Expand Up @@ -302,10 +309,12 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// fn bitxor(self, Self(rhs): Self) -> Self::Output {
/// let Self(lhs) = self;
/// assert_eq!(lhs.len(), rhs.len());
/// Self(lhs.iter()
/// Self(
/// lhs.iter()
/// .zip(rhs.iter())
/// .map(|(x, y)| (*x || *y) && !(*x && *y))
/// .collect())
/// .map(|(x, y)| *x ^ *y)
/// .collect()
/// )
/// }
/// }
///
Expand Down Expand Up @@ -643,11 +652,13 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// // `rhs` is the "right-hand side" of the expression `a &= b`.
/// fn bitand_assign(&mut self, rhs: Self) {
/// assert_eq!(self.0.len(), rhs.0.len());
/// *self = Self(self.0
/// .iter()
/// .zip(rhs.0.iter())
/// .map(|(x, y)| *x && *y)
/// .collect());
/// *self = Self(
/// self.0
/// .iter()
/// .zip(rhs.0.iter())
/// .map(|(x, y)| *x & *y)
/// .collect()
/// );
/// }
/// }
///
Expand Down
4 changes: 3 additions & 1 deletion library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,9 @@ impl str {
/// Lines are ended with either a newline (`\n`) or a carriage return with
/// a line feed (`\r\n`).
///
/// The final line ending is optional.
/// The final line ending is optional. A string that ends with a final line
/// ending will return the same lines as an otherwise identical string
/// without a final line ending.
///
/// # Examples
///
Expand Down
125 changes: 125 additions & 0 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,64 @@ impl AtomicBool {
pub fn as_mut_ptr(&self) -> *mut bool {
self.v.get() as *mut bool
}

/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function
/// returned `Some(_)`, else `Err(previous_value)`.
///
/// Note: This may call the function multiple times if the value has been
/// changed from other threads in the meantime, as long as the function
/// returns `Some(_)`, but the function will have been applied only once to
/// the stored value.
///
/// `fetch_update` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. The first describes the required ordering for
/// when the operation finally succeeds while the second describes the
/// required ordering for loads. These correspond to the success and failure
/// orderings of [`AtomicBool::compare_exchange`] respectively.
///
/// Using [`Acquire`] as success ordering makes the store part of this
/// operation [`Relaxed`], and using [`Release`] makes the final successful
/// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
/// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the
/// success ordering.
///
/// **Note:** This method is only available on platforms that support atomic
/// operations on `u8`.
///
/// # Examples
///
/// ```rust
/// #![feature(atomic_fetch_update)]
/// use std::sync::atomic::{AtomicBool, Ordering};
///
/// let x = AtomicBool::new(false);
/// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false));
/// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false));
/// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true));
/// assert_eq!(x.load(Ordering::SeqCst), false);
/// ```
#[inline]
#[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")]
#[cfg(target_has_atomic = "8")]
pub fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
mut f: F,
) -> Result<bool, bool>
where
F: FnMut(bool) -> Option<bool>,
{
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
}

#[cfg(target_has_atomic_load_store = "ptr")]
Expand Down Expand Up @@ -1123,6 +1181,73 @@ impl<T> AtomicPtr<T> {
}
}
}

/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function
/// returned `Some(_)`, else `Err(previous_value)`.
///
/// Note: This may call the function multiple times if the value has been
/// changed from other threads in the meantime, as long as the function
/// returns `Some(_)`, but the function will have been applied only once to
/// the stored value.
///
/// `fetch_update` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. The first describes the required ordering for
/// when the operation finally succeeds while the second describes the
/// required ordering for loads. These correspond to the success and failure
/// orderings of [`AtomicPtr::compare_exchange`] respectively.
///
/// Using [`Acquire`] as success ordering makes the store part of this
/// operation [`Relaxed`], and using [`Release`] makes the final successful
/// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
/// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the
/// success ordering.
///
/// **Note:** This method is only available on platforms that support atomic
/// operations on pointers.
///
/// # Examples
///
/// ```rust
/// #![feature(atomic_fetch_update)]
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr: *mut _ = &mut 5;
/// let some_ptr = AtomicPtr::new(ptr);
///
/// let new: *mut _ = &mut 10;
/// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr));
/// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
/// if x == ptr {
/// Some(new)
/// } else {
/// None
/// }
/// });
/// assert_eq!(result, Ok(ptr));
/// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
/// ```
#[inline]
#[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")]
#[cfg(target_has_atomic = "ptr")]
pub fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
mut f: F,
) -> Result<*mut T, *mut T>
where
F: FnMut(*mut T) -> Option<*mut T>,
{
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
}

#[cfg(target_has_atomic_load_store = "8")]
Expand Down
Loading

0 comments on commit 4051473

Please sign in to comment.