Skip to content

Rollup of 7 pull requests #142028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jun 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ee1c2d5
Remove `MetaItemListParser::all_{word,path}_list`, which are unused.
nnethercote May 20, 2025
a822e55
Remove an unnecessary lifetime.
nnethercote May 20, 2025
ea3b3fd
Remove `MetaItemParser::{word,word_without_args,path_is}`.
nnethercote May 20, 2025
2cd2d24
Remove `MetaItemParser::{path,deconstruct}`.
nnethercote May 20, 2025
e5c78de
Rename `MetaItemParser::path_without_args` as `MetaItemParser::path`.
nnethercote May 20, 2025
6b5b97a
Fix incorrect eq_unspanned in TokenStream
chenyukang May 26, 2025
d3347bb
remove eq_unspanned from TokenStream
chenyukang May 26, 2025
80e44de
remove f16: From<u16>
usamoi Jun 2, 2025
a20cf47
Lightly tweak docs for BTree{Map,Set}::extract_if
rs-sac Jun 2, 2025
e87f138
add tests
Qelxiros Jun 3, 2025
4996946
Add missing 2015 edition directives
Veykril Jun 3, 2025
21a739f
add tests for negative numbers
Qelxiros Jun 4, 2025
ed300d8
Improve some `Visitor` comments.
nnethercote Jun 4, 2025
c1e8fe7
Rollup merge of #141271 - nnethercote:attr-streamline, r=jdonszelmann
matthiaskrgr Jun 4, 2025
0736a03
Rollup merge of #141570 - chenyukang:yukang-fix-eq_unspanned, r=worki…
matthiaskrgr Jun 4, 2025
005490c
Rollup merge of #141893 - usamoi:lossless, r=tgross35
matthiaskrgr Jun 4, 2025
98421b7
Rollup merge of #141924 - rs-sac:extr-doc, r=jhpratt
matthiaskrgr Jun 4, 2025
5be375d
Rollup merge of #141939 - Qelxiros:139911-exact-div-tests, r=workingj…
matthiaskrgr Jun 4, 2025
8209715
Rollup merge of #141959 - ferrocene:lw/2015-edition-directives2, r=co…
matthiaskrgr Jun 4, 2025
a06160d
Rollup merge of #142007 - nnethercote:visitor-comments, r=chenyukang
matthiaskrgr Jun 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions compiler/rustc_ast/src/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ impl TokenTree {
match (self, other) {
(TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind,
(TokenTree::Delimited(.., delim, tts), TokenTree::Delimited(.., delim2, tts2)) => {
delim == delim2 && tts.eq_unspanned(tts2)
delim == delim2
&& tts.len() == tts2.len()
&& tts.iter().zip(tts2.iter()).all(|(a, b)| a.eq_unspanned(b))
}
_ => false,
}
Expand Down Expand Up @@ -694,18 +696,6 @@ impl TokenStream {
TokenStreamIter::new(self)
}

/// Compares two `TokenStream`s, checking equality without regarding span information.
pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
let mut iter1 = self.iter();
let mut iter2 = other.iter();
for (tt1, tt2) in iter::zip(&mut iter1, &mut iter2) {
if !tt1.eq_unspanned(tt2) {
return false;
}
}
iter1.next().is_none() && iter2.next().is_none()
}

/// Create a token stream containing a single token with alone spacing. The
/// spacing used for the final token in a constructed stream doesn't matter
/// because it's never used. In practice we arbitrarily use
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ pub enum LifetimeCtxt {
/// explicitly, you need to override each method. (And you also need
/// to monitor future changes to `Visitor` in case a new method with a
/// new default implementation gets introduced.)
///
/// Every `walk_*` method uses deconstruction to access fields of structs and
/// enums. This will result in a compile error if a field is added, which makes
/// it more likely the appropriate visit call will be added for it.
pub trait Visitor<'ast>: Sized {
/// The result type of the `visit_*` methods. Can be either `()`,
/// or `ControlFlow<T>`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn parse_unstable<'a>(

for param in list.mixed() {
let param_span = param.span();
if let Some(ident) = param.meta_item().and_then(|i| i.path_without_args().word()) {
if let Some(ident) = param.meta_item().and_then(|i| i.path().word()) {
res.push(ident.name);
} else {
cx.emit_err(session_diagnostics::ExpectsFeatures {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl SingleAttributeParser for DeprecationParser {
return None;
};

let ident_name = param.path_without_args().word_sym();
let ident_name = param.path().word_sym();

match ident_name {
Some(name @ sym::since) => {
Expand All @@ -102,7 +102,7 @@ impl SingleAttributeParser for DeprecationParser {
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param_span,
item: param.path_without_args().to_string(),
item: param.path().to_string(),
expected: if features.deprecated_suggestion() {
&["since", "note", "suggestion"]
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option<Repr

// FIXME(jdonszelmann): invert the parsing here to match on the word first and then the
// structure.
let (name, ident_span) = if let Some(ident) = param.path_without_args().word() {
let (name, ident_span) = if let Some(ident) = param.path().word() {
(Some(ident.name), ident.span)
} else {
(None, DUMMY_SP)
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_attr_parsing/src/attributes/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ fn insert_value_into_option_or_error(
if item.is_some() {
cx.emit_err(session_diagnostics::MultipleItem {
span: param.span(),
item: param.path_without_args().to_string(),
item: param.path().to_string(),
});
None
} else if let Some(v) = param.args().name_value()
Expand Down Expand Up @@ -242,13 +242,13 @@ pub(crate) fn parse_stability(
return None;
};

match param.path_without_args().word_sym() {
match param.path().word_sym() {
Some(sym::feature) => insert_value_into_option_or_error(cx, &param, &mut feature)?,
Some(sym::since) => insert_value_into_option_or_error(cx, &param, &mut since)?,
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param_span,
item: param.path_without_args().to_string(),
item: param.path().to_string(),
expected: &["feature", "since"],
});
return None;
Expand Down Expand Up @@ -310,7 +310,7 @@ pub(crate) fn parse_unstability(
return None;
};

match param.path_without_args().word_sym() {
match param.path().word_sym() {
Some(sym::feature) => insert_value_into_option_or_error(cx, &param, &mut feature)?,
Some(sym::reason) => insert_value_into_option_or_error(cx, &param, &mut reason)?,
Some(sym::issue) => {
Expand Down Expand Up @@ -349,7 +349,7 @@ pub(crate) fn parse_unstability(
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param.span(),
item: param.path_without_args().to_string(),
item: param.path().to_string(),
expected: &["feature", "reason", "issue", "soft", "implied_by"],
});
return None;
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ impl<'sess> AttributeParser<'sess> {
// }
ast::AttrKind::Normal(n) => {
let parser = MetaItemParser::from_attr(n, self.dcx());
let (path, args) = parser.deconstruct();
let path = parser.path();
let args = parser.args();
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();

if let Some(accept) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {
Expand Down
62 changes: 8 additions & 54 deletions compiler/rustc_attr_parsing/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,35 +252,18 @@ impl<'a> MetaItemParser<'a> {
}
}

/// Gets just the path, without the args.
pub fn path_without_args(&self) -> PathParser<'a> {
self.path.clone()
}

/// Gets just the args parser, without caring about the path.
pub fn args(&self) -> &ArgParser<'a> {
&self.args
}

pub fn deconstruct(&self) -> (PathParser<'a>, &ArgParser<'a>) {
(self.path_without_args(), self.args())
}

/// Asserts that this MetaItem starts with a path. Some examples:
/// Gets just the path, without the args. Some examples:
///
/// - `#[rustfmt::skip]`: `rustfmt::skip` is a path
/// - `#[allow(clippy::complexity)]`: `clippy::complexity` is a path
/// - `#[inline]`: `inline` is a single segment path
pub fn path(&self) -> (PathParser<'a>, &ArgParser<'a>) {
self.deconstruct()
pub fn path(&self) -> &PathParser<'a> {
&self.path
}

/// Asserts that this MetaItem starts with a word, or single segment path.
/// Doesn't return the args parser.
///
/// For examples. see [`Self::word`]
pub fn word_without_args(&self) -> Option<Ident> {
Some(self.word()?.0)
/// Gets just the args parser, without caring about the path.
pub fn args(&self) -> &ArgParser<'a> {
&self.args
}

/// Asserts that this MetaItem starts with a word, or single segment path.
Expand All @@ -289,23 +272,8 @@ impl<'a> MetaItemParser<'a> {
/// - `#[inline]`: `inline` is a word
/// - `#[rustfmt::skip]`: `rustfmt::skip` is a path,
/// and not a word and should instead be parsed using [`path`](Self::path)
pub fn word(&self) -> Option<(Ident, &ArgParser<'a>)> {
let (path, args) = self.deconstruct();
Some((path.word()?, args))
}

/// Asserts that this MetaItem starts with some specific word.
///
/// See [`word`](Self::word) for examples of what a word is.
pub fn word_is(&self, sym: Symbol) -> Option<&ArgParser<'a>> {
self.path_without_args().word_is(sym).then(|| self.args())
}

/// Asserts that this MetaItem starts with some specific path.
///
/// See [`word`](Self::path) for examples of what a word is.
pub fn path_is(&self, segments: &[Symbol]) -> Option<&ArgParser<'a>> {
self.path_without_args().segments_is(segments).then(|| self.args())
self.path().word_is(sym).then(|| self.args())
}
}

Expand Down Expand Up @@ -548,7 +516,7 @@ impl<'a> MetaItemListParser<'a> {
}

/// Lets you pick and choose as what you want to parse each element in the list
pub fn mixed<'s>(&'s self) -> impl Iterator<Item = &'s MetaItemOrLitParser<'a>> + 's {
pub fn mixed(&self) -> impl Iterator<Item = &MetaItemOrLitParser<'a>> {
self.sub_parsers.iter()
}

Expand All @@ -560,20 +528,6 @@ impl<'a> MetaItemListParser<'a> {
self.len() == 0
}

/// Asserts that every item in the list is another list starting with a word.
///
/// See [`MetaItemParser::word`] for examples of words.
pub fn all_word_list<'s>(&'s self) -> Option<Vec<(Ident, &'s ArgParser<'a>)>> {
self.mixed().map(|i| i.meta_item()?.word()).collect()
}

/// Asserts that every item in the list is another list starting with a full path.
///
/// See [`MetaItemParser::path`] for examples of paths.
pub fn all_path_list<'s>(&'s self) -> Option<Vec<(PathParser<'a>, &'s ArgParser<'a>)>> {
self.mixed().map(|i| Some(i.meta_item()?.path())).collect()
}

/// Returns Some if the list contains only a single element.
///
/// Inside the Some is the parser to parse this single element.
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ use nested_filter::NestedFilter;
/// explicitly, you need to override each method. (And you also need
/// to monitor future changes to `Visitor` in case a new method with a
/// new default implementation gets introduced.)
///
/// Every `walk_*` method uses deconstruction to access fields of structs and
/// enums. This will result in a compile error if a field is added, which makes
/// it more likely the appropriate visit call will be added for it.
pub trait Visitor<'v>: Sized {
// This type should not be overridden, it exists for convenient usage as `Self::MaybeTyCtxt`.
type MaybeTyCtxt: HirTyCtxt<'v> = <Self::NestedFilter as NestedFilter<'v>>::MaybeTyCtxt;
Expand Down Expand Up @@ -1201,7 +1205,6 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
visitor: &mut V,
trait_item: &'v TraitItem<'v>,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
let hir_id = trait_item.hir_id();
try_visit!(visitor.visit_ident(ident));
Expand Down Expand Up @@ -1240,7 +1243,6 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
trait_item_ref: &'v TraitItemRef,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let TraitItemRef { id, ident, ref kind, span: _ } = *trait_item_ref;
try_visit!(visitor.visit_nested_trait_item(id));
try_visit!(visitor.visit_ident(ident));
Expand All @@ -1251,7 +1253,6 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
visitor: &mut V,
impl_item: &'v ImplItem<'v>,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItem {
owner_id: _,
ident,
Expand Down Expand Up @@ -1286,7 +1287,6 @@ pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
foreign_item_ref: &'v ForeignItemRef,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref;
try_visit!(visitor.visit_nested_foreign_item(id));
visitor.visit_ident(ident)
Expand All @@ -1296,7 +1296,6 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
impl_item_ref: &'v ImplItemRef,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItemRef { id, ident, ref kind, span: _, trait_item_def_id: _ } = *impl_item_ref;
try_visit!(visitor.visit_nested_impl_item(id));
try_visit!(visitor.visit_ident(ident));
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use super::{
Pat, PatKind, Stmt, StmtKind, Thir,
};

/// Every `walk_*` method uses deconstruction to access fields of structs and
/// enums. This will result in a compile error if a field is added, which makes
/// it more likely the appropriate visit call will be added for it.
pub trait Visitor<'thir, 'tcx: 'thir>: Sized {
fn thir(&self) -> &'thir Thir<'tcx>;

Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_parse/src/parser/tokenstream/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ fn sp(a: u32, b: u32) -> Span {
Span::with_root_ctxt(BytePos(a), BytePos(b))
}

fn cmp_token_stream(a: &TokenStream, b: &TokenStream) -> bool {
a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.eq_unspanned(y))
}

#[test]
fn test_concat() {
create_default_session_globals_then(|| {
Expand All @@ -25,7 +29,7 @@ fn test_concat() {
eq_res.push_stream(test_snd);
assert_eq!(test_res.iter().count(), 5);
assert_eq!(eq_res.iter().count(), 5);
assert_eq!(test_res.eq_unspanned(&eq_res), true);
assert_eq!(cmp_token_stream(&test_res, &eq_res), true);
})
}

Expand Down Expand Up @@ -104,7 +108,7 @@ fn test_dotdotdot() {
stream.push_tree(TokenTree::token_joint(token::Dot, sp(0, 1)));
stream.push_tree(TokenTree::token_joint(token::Dot, sp(1, 2)));
stream.push_tree(TokenTree::token_alone(token::Dot, sp(2, 3)));
assert!(stream.eq_unspanned(&string_to_ts("...")));
assert!(cmp_token_stream(&stream, &string_to_ts("...")));
assert_eq!(stream.iter().count(), 1);
})
}
4 changes: 2 additions & 2 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1416,18 +1416,18 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
///
/// # Examples
///
/// Splitting a map into even and odd keys, reusing the original map:
///
/// ```
/// #![feature(btree_extract_if)]
/// use std::collections::BTreeMap;
///
/// // Splitting a map into even and odd keys, reusing the original map:
/// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let evens: BTreeMap<_, _> = map.extract_if(.., |k, _v| k % 2 == 0).collect();
/// let odds = map;
/// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), [0, 2, 4, 6]);
/// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]);
///
/// // Splitting a map into low and high halves, reusing the original map:
/// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let low: BTreeMap<_, _> = map.extract_if(0..4, |_k, _v| true).collect();
/// let high = map;
Expand Down
10 changes: 5 additions & 5 deletions library/alloc/src/collections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,21 +1201,21 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// [`retain`]: BTreeSet::retain
/// # Examples
///
/// Splitting a set into even and odd values, reusing the original set:
///
/// ```
/// #![feature(btree_extract_if)]
/// use std::collections::BTreeSet;
///
/// // Splitting a set into even and odd values, reusing the original set:
/// let mut set: BTreeSet<i32> = (0..8).collect();
/// let evens: BTreeSet<_> = set.extract_if(.., |v| v % 2 == 0).collect();
/// let odds = set;
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
///
/// let mut map: BTreeSet<i32> = (0..8).collect();
/// let low: BTreeSet<_> = map.extract_if(0..4, |_v| true).collect();
/// let high = map;
/// // Splitting a set into low and high halves, reusing the original set:
/// let mut set: BTreeSet<i32> = (0..8).collect();
/// let low: BTreeSet<_> = set.extract_if(0..4, |_v| true).collect();
/// let high = set;
/// assert_eq!(low.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
/// assert_eq!(high.into_iter().collect::<Vec<_>>(), [4, 5, 6, 7]);
/// ```
Expand Down
1 change: 0 additions & 1 deletion library/core/src/convert/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ impl_from!(u8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")
impl_from!(u8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
Expand Down
1 change: 1 addition & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#![feature(duration_constructors)]
#![feature(duration_constructors_lite)]
#![feature(error_generic_member_access)]
#![feature(exact_div)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(extern_types)]
Expand Down
Loading
Loading