From 47279b33e03587e55c50eacdf710d64ff15f17fb Mon Sep 17 00:00:00 2001 From: Dave Rolsky Date: Sat, 31 Oct 2020 11:34:32 -0500 Subject: [PATCH 1/8] Clarify handling of final line ending in str::lines() I found the description as it stands a bit confusing. I've added a bit more explanation to make it clear that a trailing line ending does not produce a final empty line. --- library/core/src/str/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index b36d9f5c38841..f4e8529a58f6f 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -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 (carriage return or line feed) will return the same lines as an + /// otherwise identical string without a final line ending. /// /// # Examples /// From 6b63e9b990b1624df3f93aeca849a33efcf156e9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 31 Oct 2020 22:47:57 +0300 Subject: [PATCH 2/8] Do not remove tokens before AST json serialization --- compiler/rustc_ast/src/tokenstream.rs | 5 +- compiler/rustc_interface/src/passes.rs | 90 +------------------ src/test/ui/ast-json/ast-json-ice.rs | 23 +++++ .../ast-json/ast-json-noexpand-output.stdout | 2 +- src/test/ui/ast-json/ast-json-output.stdout | 2 +- .../ui/ast-json/issue-78398-foreign-ice.rs | 18 ---- .../ast-json/issue-78398-foreign-ice.stdout | 1 - src/test/ui/ast-json/issue-78510-assoc-ice.rs | 18 ---- .../ui/ast-json/issue-78510-assoc-ice.stderr | 15 ---- .../ui/ast-json/issue-78510-assoc-ice.stdout | 1 - 10 files changed, 30 insertions(+), 145 deletions(-) delete mode 100644 src/test/ui/ast-json/issue-78398-foreign-ice.rs delete mode 100644 src/test/ui/ast-json/issue-78398-foreign-ice.stdout delete mode 100644 src/test/ui/ast-json/issue-78510-assoc-ice.rs delete mode 100644 src/test/ui/ast-json/issue-78510-assoc-ice.stderr delete mode 100644 src/test/ui/ast-json/issue-78510-assoc-ice.stdout diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index b53acb97aeb9e..98da20af8f691 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -153,8 +153,9 @@ impl fmt::Debug for LazyTokenStream { } impl Encodable 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) } } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a1487aa0060d5..d9c24cc399482 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -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}; @@ -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; @@ -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) -> SmallVec<[P; 1]> { - i.tokens = None; - mut_visit::noop_flat_map_item(i, self) - } - fn flat_map_foreign_item( - &mut self, - mut i: P, - ) -> SmallVec<[P; 1]> { - i.tokens = None; - mut_visit::noop_flat_map_foreign_item(i, self) - } - fn flat_map_trait_item( - &mut self, - mut i: P, - ) -> SmallVec<[P; 1]> { - i.tokens = None; - mut_visit::noop_flat_map_assoc_item(i, self) - } - fn flat_map_impl_item(&mut self, mut i: P) -> SmallVec<[P; 1]> { - i.tokens = None; - mut_visit::noop_flat_map_assoc_item(i, self) - } - fn visit_block(&mut self, b: &mut P) { - 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) { - p.tokens = None; - mut_visit::noop_visit_pat(p, self); - } - fn visit_ty(&mut self, ty: &mut P) { - 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) { - 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), @@ -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)); } @@ -461,10 +379,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)); } diff --git a/src/test/ui/ast-json/ast-json-ice.rs b/src/test/ui/ast-json/ast-json-ice.rs index 60e6c88fc7924..bbdd7e33ba067 100644 --- a/src/test/ui/ast-json/ast-json-ice.rs +++ b/src/test/ui/ast-json/ast-json-ice.rs @@ -39,3 +39,26 @@ fn main() { struct A; } + +// Regressions tests for issues #78398 and #78510 (captured tokens in associated and foreign items) + +struct S; + +macro_rules! mac_extern { + ($i:item) => { + extern "C" { $i } + } +} +macro_rules! mac_assoc { + ($i:item) => { + impl S { $i } + trait Bar { $i } + } +} + +mac_extern! { + fn foo(); +} +mac_assoc! { + fn foo() {} +} diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout index 259206ba90718..fb311a9045b35 100644 --- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout +++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 76e32044add18..d1e0f409948c2 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/ast-json/issue-78398-foreign-ice.rs b/src/test/ui/ast-json/issue-78398-foreign-ice.rs deleted file mode 100644 index a1a20f9568178..0000000000000 --- a/src/test/ui/ast-json/issue-78398-foreign-ice.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Regression test for issue #78398 -// Tests that we don't ICE when trying to print the AST json -// when we have capturd tokens for a foreign item - -// check-pass -// compile-flags: -Zast-json - -fn main() {} - -macro_rules! mac_extern { - ($i:item) => { - extern "C" { $i } - } -} - -mac_extern! { - fn foo(); -} diff --git a/src/test/ui/ast-json/issue-78398-foreign-ice.stdout b/src/test/ui/ast-json/issue-78398-foreign-ice.stdout deleted file mode 100644 index f1d0e44e9fc8c..0000000000000 --- a/src/test/ui/ast-json/issue-78398-foreign-ice.stdout +++ /dev/null @@ -1 +0,0 @@ -{"module":{"inner":{"lo":192,"hi":315},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":3,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":4,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":5,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":6,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":7,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":8,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":9,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":10,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":11,"span":{"lo":192,"hi":204},"vis":{"kind":"Inherited","span":{"lo":192,"hi":192},"tokens":null},"ident":{"name":"main","span":{"lo":195,"hi":199}},"kind":{"variant":"Fn","fields":["Final",{"header":{"unsafety":"No","asyncness":"No","constness":"No","ext":"None"},"decl":{"inputs":[],"output":{"variant":"Default","fields":[{"lo":202,"hi":202}]}},"span":{"lo":192,"hi":201}},{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":201,"hi":201}},"span":{"lo":199,"hi":199}},{"stmts":[],"id":12,"rules":"Default","span":{"lo":202,"hi":204},"tokens":null}]},"tokens":null},{"attrs":[],"id":13,"span":{"lo":206,"hi":284},"vis":{"kind":"Inherited","span":{"lo":206,"hi":206},"tokens":null},"ident":{"name":"mac_extern","span":{"lo":219,"hi":229}},"kind":{"variant":"MacroDef","fields":[{"body":{"variant":"Delimited","fields":[{"open":{"lo":230,"hi":231},"close":{"lo":283,"hi":284}},"Brace",{"0":[[{"variant":"Delimited","fields":[{"open":{"lo":236,"hi":237},"close":{"lo":244,"hi":245}},"Paren",{"0":[[{"variant":"Token","fields":[{"kind":"Dollar","span":{"lo":237,"hi":238}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["i",false]},"span":{"lo":238,"hi":239}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Colon","span":{"lo":239,"hi":240}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["item",false]},"span":{"lo":240,"hi":244}}]},"Alone"]]}]},"Alone"],[{"variant":"Token","fields":[{"kind":"FatArrow","span":{"lo":246,"hi":248}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":249,"hi":250},"close":{"lo":281,"hi":282}},"Brace",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":259,"hi":265}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"C","suffix":null}]},"span":{"lo":266,"hi":269}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":270,"hi":271},"close":{"lo":275,"hi":276}},"Brace",{"0":[[{"variant":"Token","fields":[{"kind":"Dollar","span":{"lo":272,"hi":273}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["i",false]},"span":{"lo":273,"hi":274}}]},"Alone"]]}]},"Alone"]]}]},"Alone"]]}]},"macro_rules":true}]},"tokens":null},{"attrs":[],"id":14,"span":{"lo":259,"hi":276},"vis":{"kind":"Inherited","span":{"lo":259,"hi":259},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"ForeignMod","fields":[{"unsafety":"No","abi":{"style":"Cooked","symbol":"C","suffix":null,"span":{"lo":266,"hi":269},"symbol_unescaped":"C"},"items":[{"attrs":[],"id":15,"span":{"lo":304,"hi":313},"vis":{"kind":"Inherited","span":{"lo":304,"hi":304},"tokens":null},"ident":{"name":"foo","span":{"lo":307,"hi":310}},"kind":{"variant":"Fn","fields":["Final",{"header":{"unsafety":"No","asyncness":"No","constness":"No","ext":"None"},"decl":{"inputs":[],"output":{"variant":"Default","fields":[{"lo":312,"hi":312}]}},"span":{"lo":304,"hi":313}},{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":312,"hi":312}},"span":{"lo":310,"hi":310}},null]},"tokens":null}]}]},"tokens":null}],"inline":true},"attrs":[],"span":{"lo":192,"hi":315},"proc_macros":[]} diff --git a/src/test/ui/ast-json/issue-78510-assoc-ice.rs b/src/test/ui/ast-json/issue-78510-assoc-ice.rs deleted file mode 100644 index ef3117c49cad3..0000000000000 --- a/src/test/ui/ast-json/issue-78510-assoc-ice.rs +++ /dev/null @@ -1,18 +0,0 @@ -// compile-flags: -Zast-json -// -// Regression test for issue #78510 -// Tests that we don't ICE when we have tokens for an associated item - -struct S; - -impl S { - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions - fn f() {} -} - -trait Bar { - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions - fn foo() {} -} - -fn main() {} diff --git a/src/test/ui/ast-json/issue-78510-assoc-ice.stderr b/src/test/ui/ast-json/issue-78510-assoc-ice.stderr deleted file mode 100644 index 3573c203a7893..0000000000000 --- a/src/test/ui/ast-json/issue-78510-assoc-ice.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-78510-assoc-ice.rs:9:5 - | -LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ - -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-78510-assoc-ice.rs:14:5 - | -LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/ast-json/issue-78510-assoc-ice.stdout b/src/test/ui/ast-json/issue-78510-assoc-ice.stdout deleted file mode 100644 index fef9504285b53..0000000000000 --- a/src/test/ui/ast-json/issue-78510-assoc-ice.stdout +++ /dev/null @@ -1 +0,0 @@ -{"module":{"inner":{"lo":139,"hi":397},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":3,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":4,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":5,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":6,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":7,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":8,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":9,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":10,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":11,"span":{"lo":139,"hi":148},"vis":{"kind":"Inherited","span":{"lo":139,"hi":139},"tokens":null},"ident":{"name":"S","span":{"lo":146,"hi":147}},"kind":{"variant":"Struct","fields":[{"variant":"Unit","fields":[12]},{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":147,"hi":147}},"span":{"lo":147,"hi":147}}]},"tokens":null},{"attrs":[],"id":13,"span":{"lo":150,"hi":263},"vis":{"kind":"Inherited","span":{"lo":150,"hi":150},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Impl","fields":["No","Positive","Final","No",{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":156,"hi":156}},"span":{"lo":154,"hi":154}},null,{"id":14,"kind":{"variant":"Path","fields":[null,{"span":{"lo":155,"hi":156},"segments":[{"ident":{"name":"S","span":{"lo":155,"hi":156}},"id":15,"args":null}],"tokens":null}]},"span":{"lo":155,"hi":156},"tokens":null},[{"attrs":[],"id":19,"span":{"lo":252,"hi":261},"vis":{"kind":"Inherited","span":{"lo":252,"hi":252},"tokens":null},"ident":{"name":"f","span":{"lo":255,"hi":256}},"kind":{"variant":"Fn","fields":["Final",{"header":{"unsafety":"No","asyncness":"No","constness":"No","ext":"None"},"decl":{"inputs":[],"output":{"variant":"Default","fields":[{"lo":259,"hi":259}]}},"span":{"lo":252,"hi":258}},{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":258,"hi":258}},"span":{"lo":256,"hi":256}},{"stmts":[],"id":20,"rules":"Default","span":{"lo":259,"hi":261},"tokens":null}]},"tokens":null}]]},"tokens":null},{"attrs":[],"id":16,"span":{"lo":265,"hi":383},"vis":{"kind":"Inherited","span":{"lo":265,"hi":265},"tokens":null},"ident":{"name":"Bar","span":{"lo":271,"hi":274}},"kind":{"variant":"Trait","fields":["No","No",{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":274,"hi":274}},"span":{"lo":274,"hi":274}},[],[{"attrs":[],"id":21,"span":{"lo":370,"hi":381},"vis":{"kind":"Inherited","span":{"lo":370,"hi":370},"tokens":null},"ident":{"name":"foo","span":{"lo":373,"hi":376}},"kind":{"variant":"Fn","fields":["Final",{"header":{"unsafety":"No","asyncness":"No","constness":"No","ext":"None"},"decl":{"inputs":[],"output":{"variant":"Default","fields":[{"lo":379,"hi":379}]}},"span":{"lo":370,"hi":378}},{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":378,"hi":378}},"span":{"lo":376,"hi":376}},{"stmts":[],"id":22,"rules":"Default","span":{"lo":379,"hi":381},"tokens":null}]},"tokens":null}]]},"tokens":null},{"attrs":[],"id":17,"span":{"lo":385,"hi":397},"vis":{"kind":"Inherited","span":{"lo":385,"hi":385},"tokens":null},"ident":{"name":"main","span":{"lo":388,"hi":392}},"kind":{"variant":"Fn","fields":["Final",{"header":{"unsafety":"No","asyncness":"No","constness":"No","ext":"None"},"decl":{"inputs":[],"output":{"variant":"Default","fields":[{"lo":395,"hi":395}]}},"span":{"lo":385,"hi":394}},{"params":[],"where_clause":{"has_where_token":false,"predicates":[],"span":{"lo":394,"hi":394}},"span":{"lo":392,"hi":392}},{"stmts":[],"id":18,"rules":"Default","span":{"lo":395,"hi":397},"tokens":null}]},"tokens":null}],"inline":true},"attrs":[],"span":{"lo":139,"hi":397},"proc_macros":[]} From 66d68cdc6f5bb508052b890f8766a84a98533865 Mon Sep 17 00:00:00 2001 From: Abhijit Gadgil Date: Sun, 1 Nov 2020 08:22:25 +0530 Subject: [PATCH 3/8] Trivial fixes to bitwise operator documentation Added fixes to documentation of `BitAnd`, `BitOr`, `BitXor` and `BitAndAssign`, where the documentation for implementation on `Vector` was using logical operators in place of the bitwise operators. r? @steveklabnik cc #78619 --- library/core/src/ops/bit.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index 6120da50c3cdf..3dae57938bec5 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -111,7 +111,7 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(lhs.len(), rhs.len()); /// Self(lhs.iter() /// .zip(rhs.iter()) -/// .map(|(x, y)| *x && *y) +/// .map(|(x, y)| *x & *y) /// .collect()) /// } /// } @@ -207,7 +207,10 @@ 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()) /// } /// } /// @@ -304,7 +307,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(lhs.len(), rhs.len()); /// Self(lhs.iter() /// .zip(rhs.iter()) -/// .map(|(x, y)| (*x || *y) && !(*x && *y)) +/// .map(|(x, y)| *x ^ *y)) /// .collect()) /// } /// } @@ -646,7 +649,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// *self = Self(self.0 /// .iter() /// .zip(rhs.0.iter()) -/// .map(|(x, y)| *x && *y) +/// .map(|(x, y)| *x & *y) /// .collect()); /// } /// } From 7c88bcc3f6a055093eafff8d4cfb1dfcd813ebbe Mon Sep 17 00:00:00 2001 From: Abhijit Gadgil Date: Sun, 1 Nov 2020 09:08:19 +0530 Subject: [PATCH 4/8] Fixes incorrect paranthesis. --- library/core/src/ops/bit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index 3dae57938bec5..b91f87be90af1 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -307,7 +307,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(lhs.len(), rhs.len()); /// Self(lhs.iter() /// .zip(rhs.iter()) -/// .map(|(x, y)| *x ^ *y)) +/// .map(|(x, y)| *x ^ *y) /// .collect()) /// } /// } From d422e2424f08ebc420882e2a668174028341dc65 Mon Sep 17 00:00:00 2001 From: Abhijit Gadgil Date: Sun, 1 Nov 2020 18:53:22 +0530 Subject: [PATCH 5/8] documentation examples fixes in rustfmt convention --- library/core/src/ops/bit.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index b91f87be90af1..51f8043817345 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -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()) +/// .collect() +/// ) /// } /// } /// @@ -207,10 +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() +/// Self( +/// lhs.iter() /// .zip(rhs.iter()) /// .map(|(x, y)| *x | *y) -/// .collect()) +/// .collect() +/// ) /// } /// } /// @@ -305,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) -/// .collect()) +/// .collect() +/// ) /// } /// } /// @@ -646,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() +/// ); /// } /// } /// From b2d7b3aa26e1821bfdfd8be8a8b65cd6e674ff04 Mon Sep 17 00:00:00 2001 From: Dave Rolsky Date: Sun, 1 Nov 2020 09:11:20 -0600 Subject: [PATCH 6/8] Remove incorrect statement about line ending content in lines doc change --- library/core/src/str/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index f4e8529a58f6f..5658e28fbff11 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -843,8 +843,8 @@ impl str { /// a line feed (`\r\n`). /// /// The final line ending is optional. A string that ends with a final line - /// ending (carriage return or line feed) will return the same lines as an - /// otherwise identical string without a final line ending. + /// ending will return the same lines as an otherwise identical string + /// without a final line ending. /// /// # Examples /// From a79059d42d8f6b1e2c2f109aa55a8ff98f4eb453 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 1 Nov 2020 14:27:36 +0100 Subject: [PATCH 7/8] Point out that total_cmp is no strict superset of partial comparison Partial comparison and total_cmp are not equal. This helps preventing the mistake of creating float wrappers that base their Ord impl on total_cmp and their PartialOrd impl on the PartialOrd impl of the float type. PartialOrd and Ord are required to agree with each other. --- library/core/src/num/f32.rs | 4 ++++ library/core/src/num/f64.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index bf7c87f685d3c..86e6352d13215 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -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)] diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index e31e176ba1b0a..9b1405b479f7c 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -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)] From 00f32e6631cb5603d072b24e0c1db2104fc63a26 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sun, 1 Nov 2020 13:24:22 -0500 Subject: [PATCH 8/8] Add fetch_update methods to AtomicBool and AtomicPtr These methods were stabilized for the integer atomics in #71843, but the methods were not added for the non-integer atomics `AtomicBool` and `AtomicPtr`. --- library/core/src/sync/atomic.rs | 125 ++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index a3d93d7074b69..0c53b6ed54a84 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -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( + &self, + set_order: Ordering, + fetch_order: Ordering, + mut f: F, + ) -> Result + where + F: FnMut(bool) -> Option, + { + 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")] @@ -1123,6 +1181,73 @@ impl AtomicPtr { } } } + + /// 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( + &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")]