Skip to content

Commit 8b6b857

Browse files
committed
Auto merge of #128253 - tgross35:rollup-rpmoebz, r=tgross35
Rollup of 9 pull requests Successful merges: - #124941 (Stabilize const `{integer}::from_str_radix` i.e. `const_int_from_str`) - #128201 (Implement `Copy`/`Clone` for async closures) - #128210 (rustdoc: change title of search results) - #128223 (Refactor complex conditions in `collect_tokens_trailing_token`) - #128224 (Remove unnecessary range replacements) - #128226 (Remove redundant option that was just encoding that a slice was empty) - #128227 (CI: do not respect custom try jobs for unrolled perf builds) - #128229 (Improve `extern "<abi>" unsafe fn()` error message) - #128235 (Fix `Iterator::filter` docs) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7c2012d + 8385f3b commit 8b6b857

File tree

32 files changed

+265
-133
lines changed

32 files changed

+265
-133
lines changed

compiler/rustc_ast_lowering/src/item.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
172172
id: NodeId,
173173
hir_id: hir::HirId,
174174
ident: &mut Ident,
175-
attrs: Option<&'hir [Attribute]>,
175+
attrs: &'hir [Attribute],
176176
vis_span: Span,
177177
i: &ItemKind,
178178
) -> hir::ItemKind<'hir> {
@@ -488,7 +488,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
488488
id: NodeId,
489489
vis_span: Span,
490490
ident: &mut Ident,
491-
attrs: Option<&'hir [Attribute]>,
491+
attrs: &'hir [Attribute],
492492
) -> hir::ItemKind<'hir> {
493493
let path = &tree.prefix;
494494
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
@@ -566,7 +566,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
566566
// `ItemLocalId` and the new owner. (See `lower_node_id`)
567567
let kind =
568568
this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
569-
if let Some(attrs) = attrs {
569+
if !attrs.is_empty() {
570570
this.attrs.insert(hir::ItemLocalId::ZERO, attrs);
571571
}
572572

compiler/rustc_ast_lowering/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -913,15 +913,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
913913
ret
914914
}
915915

916-
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
916+
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> &'hir [Attribute] {
917917
if attrs.is_empty() {
918-
None
918+
&[]
919919
} else {
920920
debug_assert_eq!(id.owner, self.current_hir_id_owner);
921921
let ret = self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)));
922922
debug_assert!(!ret.is_empty());
923923
self.attrs.insert(id.local_id, ret);
924-
Some(ret)
924+
ret
925925
}
926926
}
927927

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1442,9 +1442,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
14421442
// See `tests/ui/moves/needs-clone-through-deref.rs`
14431443
return false;
14441444
}
1445+
// We don't want to suggest `.clone()` in a move closure, since the value has already been captured.
14451446
if self.in_move_closure(expr) {
14461447
return false;
14471448
}
1449+
// We also don't want to suggest cloning a closure itself, since the value has already been captured.
1450+
if let hir::ExprKind::Closure(_) = expr.kind {
1451+
return false;
1452+
}
14481453
// Try to find predicates on *generic params* that would allow copying `ty`
14491454
let mut suggestion =
14501455
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {

compiler/rustc_mir_transform/src/shim.rs

+3
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,9 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
435435
match self_ty.kind() {
436436
ty::FnDef(..) | ty::FnPtr(_) => builder.copy_shim(),
437437
ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
438+
ty::CoroutineClosure(_, args) => {
439+
builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())
440+
}
438441
ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
439442
ty::Coroutine(coroutine_def_id, args) => {
440443
assert_eq!(tcx.coroutine_movability(*coroutine_def_id), hir::Movability::Movable);

compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,10 @@ where
217217
// impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
218218
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
219219

220-
ty::CoroutineClosure(..) => Err(NoSolution),
220+
// impl Copy/Clone for CoroutineClosure where Self::TupledUpvars: Copy/Clone
221+
ty::CoroutineClosure(_, args) => {
222+
Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())])
223+
}
221224

222225
// only when `coroutine_clone` is enabled and the coroutine is movable
223226
// impl Copy/Clone for Coroutine where T: Copy/Clone forall T in (upvars, witnesses)

compiler/rustc_parse/src/parser/attr.rs

-11
Original file line numberDiff line numberDiff line change
@@ -457,14 +457,3 @@ impl<'a> Parser<'a> {
457457
Err(self.dcx().create_err(err))
458458
}
459459
}
460-
461-
/// The attributes are complete if all attributes are either a doc comment or a
462-
/// builtin attribute other than `cfg_attr`.
463-
pub fn is_complete(attrs: &[ast::Attribute]) -> bool {
464-
attrs.iter().all(|attr| {
465-
attr.is_doc_comment()
466-
|| attr.ident().is_some_and(|ident| {
467-
ident.name != sym::cfg_attr && rustc_feature::is_builtin_attr_name(ident.name)
468-
})
469-
})
470-
}

compiler/rustc_parse/src/parser/attr_wrapper.rs

+64-59
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@ impl AttrWrapper {
6060
pub fn is_empty(&self) -> bool {
6161
self.attrs.is_empty()
6262
}
63-
64-
pub fn is_complete(&self) -> bool {
65-
crate::parser::attr::is_complete(&self.attrs)
66-
}
6763
}
6864

6965
/// Returns `true` if `attrs` contains a `cfg` or `cfg_attr` attribute
@@ -114,17 +110,15 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
114110
replace_ranges.sort_by_key(|(range, _)| range.start);
115111

116112
#[cfg(debug_assertions)]
117-
{
118-
for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() {
119-
assert!(
120-
range.end <= next_range.start || range.end >= next_range.end,
121-
"Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
122-
range,
123-
tokens,
124-
next_range,
125-
next_tokens,
126-
);
127-
}
113+
for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() {
114+
assert!(
115+
range.end <= next_range.start || range.end >= next_range.end,
116+
"Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
117+
range,
118+
tokens,
119+
next_range,
120+
next_tokens,
121+
);
128122
}
129123

130124
// Process the replace ranges, starting from the highest start
@@ -137,9 +131,9 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
137131
// `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
138132
//
139133
// By starting processing from the replace range with the greatest
140-
// start position, we ensure that any replace range which encloses
141-
// another replace range will capture the *replaced* tokens for the inner
142-
// range, not the original tokens.
134+
// start position, we ensure that any (outer) replace range which
135+
// encloses another (inner) replace range will fully overwrite the
136+
// inner range's replacement.
143137
for (range, target) in replace_ranges.into_iter().rev() {
144138
assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}");
145139

@@ -199,20 +193,20 @@ impl<'a> Parser<'a> {
199193
force_collect: ForceCollect,
200194
f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, (R, bool)>,
201195
) -> PResult<'a, R> {
202-
// Skip collection when nothing could observe the collected tokens, i.e.
203-
// all of the following conditions hold.
204-
// - We are not force collecting tokens (because force collection
205-
// requires tokens by definition).
206-
if matches!(force_collect, ForceCollect::No)
207-
// - None of our outer attributes require tokens.
208-
&& attrs.is_complete()
209-
// - Our target doesn't support custom inner attributes (custom
196+
// We must collect if anything could observe the collected tokens, i.e.
197+
// if any of the following conditions hold.
198+
// - We are force collecting tokens (because force collection requires
199+
// tokens by definition).
200+
let needs_collection = matches!(force_collect, ForceCollect::Yes)
201+
// - Any of our outer attributes require tokens.
202+
|| needs_tokens(&attrs.attrs)
203+
// - Our target supports custom inner attributes (custom
210204
// inner attribute invocation might require token capturing).
211-
&& !R::SUPPORTS_CUSTOM_INNER_ATTRS
212-
// - We are not in `capture_cfg` mode (which requires tokens if
205+
|| R::SUPPORTS_CUSTOM_INNER_ATTRS
206+
// - We are in `capture_cfg` mode (which requires tokens if
213207
// the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
214-
&& !self.capture_cfg
215-
{
208+
|| self.capture_cfg;
209+
if !needs_collection {
216210
return Ok(f(self, attrs.attrs)?.0);
217211
}
218212

@@ -250,28 +244,28 @@ impl<'a> Parser<'a> {
250244
return Ok(ret);
251245
}
252246

253-
// This is similar to the "skip collection" check at the start of this
254-
// function, but now that we've parsed an AST node we have more
247+
// This is similar to the `needs_collection` check at the start of this
248+
// function, but now that we've parsed an AST node we have complete
255249
// information available. (If we return early here that means the
256250
// setup, such as cloning the token cursor, was unnecessary. That's
257251
// hard to avoid.)
258252
//
259-
// Skip collection when nothing could observe the collected tokens, i.e.
260-
// all of the following conditions hold.
261-
// - We are not force collecting tokens.
262-
if matches!(force_collect, ForceCollect::No)
263-
// - None of our outer *or* inner attributes require tokens.
264-
// (`attrs` was just outer attributes, but `ret.attrs()` is outer
265-
// and inner attributes. That makes this check more precise than
266-
// `attrs.is_complete()` at the start of the function, and we can
267-
// skip the subsequent check on `R::SUPPORTS_CUSTOM_INNER_ATTRS`.
268-
&& crate::parser::attr::is_complete(ret.attrs())
269-
// - We are not in `capture_cfg` mode, or we are but there are no
270-
// `#[cfg]` or `#[cfg_attr]` attributes. (During normal
271-
// non-`capture_cfg` parsing, we don't need any special capturing
272-
// for those attributes, because they're builtin.)
273-
&& (!self.capture_cfg || !has_cfg_or_cfg_attr(ret.attrs()))
274-
{
253+
// We must collect if anything could observe the collected tokens, i.e.
254+
// if any of the following conditions hold.
255+
// - We are force collecting tokens.
256+
let needs_collection = matches!(force_collect, ForceCollect::Yes)
257+
// - Any of our outer *or* inner attributes require tokens.
258+
// (`attr.attrs` was just outer attributes, but `ret.attrs()` is
259+
// outer and inner attributes. So this check is more precise than
260+
// the earlier `needs_tokens` check, and we don't need to
261+
// check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
262+
|| needs_tokens(ret.attrs())
263+
// - We are in `capture_cfg` mode and there are `#[cfg]` or
264+
// `#[cfg_attr]` attributes. (During normal non-`capture_cfg`
265+
// parsing, we don't need any special capturing for those
266+
// attributes, because they're builtin.)
267+
|| (self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs()));
268+
if !needs_collection {
275269
return Ok(ret);
276270
}
277271

@@ -297,11 +291,13 @@ impl<'a> Parser<'a> {
297291
// with `None`, which means the relevant tokens will be removed. (More
298292
// details below.)
299293
let mut inner_attr_replace_ranges = Vec::new();
300-
for inner_attr in ret.attrs().iter().filter(|a| a.style == ast::AttrStyle::Inner) {
301-
if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) {
302-
inner_attr_replace_ranges.push((attr_range, None));
303-
} else {
304-
self.dcx().span_delayed_bug(inner_attr.span, "Missing token range for attribute");
294+
for attr in ret.attrs() {
295+
if attr.style == ast::AttrStyle::Inner {
296+
if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&attr.id) {
297+
inner_attr_replace_ranges.push((attr_range, None));
298+
} else {
299+
self.dcx().span_delayed_bug(attr.span, "Missing token range for attribute");
300+
}
305301
}
306302
}
307303

@@ -337,8 +333,7 @@ impl<'a> Parser<'a> {
337333
// When parsing `m`:
338334
// - `start_pos..end_pos` is `0..34` (`mod m`, excluding the `#[cfg_eval]` attribute).
339335
// - `inner_attr_replace_ranges` is empty.
340-
// - `replace_range_start..replace_ranges_end` has two entries.
341-
// - One to delete the inner attribute (`17..27`), obtained when parsing `g` (see above).
336+
// - `replace_range_start..replace_ranges_end` has one entry.
342337
// - One `AttrsTarget` (added below when parsing `g`) to replace all of `g` (`3..33`,
343338
// including its outer attribute), with:
344339
// - `attrs`: includes the outer and the inner attr.
@@ -369,12 +364,10 @@ impl<'a> Parser<'a> {
369364

370365
// What is the status here when parsing the example code at the top of this method?
371366
//
372-
// When parsing `g`, we add two entries:
367+
// When parsing `g`, we add one entry:
373368
// - The `start_pos..end_pos` (`3..33`) entry has a new `AttrsTarget` with:
374369
// - `attrs`: includes the outer and the inner attr.
375370
// - `tokens`: lazy tokens for `g` (with its inner attr deleted).
376-
// - `inner_attr_replace_ranges` contains the one entry to delete the inner attr's
377-
// tokens (`17..27`).
378371
//
379372
// When parsing `m`, we do nothing here.
380373

@@ -384,7 +377,6 @@ impl<'a> Parser<'a> {
384377
let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos };
385378
let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens };
386379
self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target)));
387-
self.capture_state.replace_ranges.extend(inner_attr_replace_ranges);
388380
} else if matches!(self.capture_state.capturing, Capturing::No) {
389381
// Only clear the ranges once we've finished capturing entirely, i.e. we've finished
390382
// the outermost call to this method.
@@ -461,6 +453,19 @@ fn make_attr_token_stream(
461453
AttrTokenStream::new(stack_top.inner)
462454
}
463455

456+
/// Tokens are needed if:
457+
/// - any non-single-segment attributes (other than doc comments) are present; or
458+
/// - any `cfg_attr` attributes are present;
459+
/// - any single-segment, non-builtin attributes are present.
460+
fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
461+
attrs.iter().any(|attr| match attr.ident() {
462+
None => !attr.is_doc_comment(),
463+
Some(ident) => {
464+
ident.name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(ident.name)
465+
}
466+
})
467+
}
468+
464469
// Some types are used a lot. Make sure they don't unintentionally get bigger.
465470
#[cfg(target_pointer_width = "64")]
466471
mod size_asserts {

compiler/rustc_parse/src/parser/item.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -2483,12 +2483,15 @@ impl<'a> Parser<'a> {
24832483
/// `check_pub` adds additional `pub` to the checks in case users place it
24842484
/// wrongly, can be used to ensure `pub` never comes after `default`.
24852485
pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2486+
const ALL_QUALS: &[Symbol] =
2487+
&[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern];
2488+
24862489
// We use an over-approximation here.
24872490
// `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
24882491
// `pub` is added in case users got confused with the ordering like `async pub fn`,
24892492
// only if it wasn't preceded by `default` as `default pub` is invalid.
24902493
let quals: &[Symbol] = if check_pub {
2491-
&[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
2494+
ALL_QUALS
24922495
} else {
24932496
&[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
24942497
};
@@ -2518,9 +2521,9 @@ impl<'a> Parser<'a> {
25182521
|| self.check_keyword_case(kw::Extern, case)
25192522
&& self.look_ahead(1, |t| t.can_begin_string_literal())
25202523
&& (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) ||
2521-
// this branch is only for better diagnostic in later, `pub` is not allowed here
2524+
// this branch is only for better diagnostics; `pub`, `unsafe`, etc. are not allowed here
25222525
(self.may_recover()
2523-
&& self.look_ahead(2, |t| t.is_keyword(kw::Pub))
2526+
&& self.look_ahead(2, |t| ALL_QUALS.iter().any(|&kw| t.is_keyword(kw)))
25242527
&& self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case))))
25252528
}
25262529

compiler/rustc_trait_selection/src/traits/select/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -2262,8 +2262,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
22622262
}
22632263
}
22642264

2265-
// FIXME(async_closures): These are never clone, for now.
2266-
ty::CoroutineClosure(_, _) => None,
2265+
ty::CoroutineClosure(_, args) => {
2266+
// (*) binder moved here
2267+
let ty = self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
2268+
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
2269+
// Not yet resolved.
2270+
Ambiguous
2271+
} else {
2272+
Where(
2273+
obligation
2274+
.predicate
2275+
.rebind(args.as_coroutine_closure().upvar_tys().to_vec()),
2276+
)
2277+
}
2278+
}
2279+
22672280
// `Copy` and `Clone` are automatically implemented for an anonymous adt
22682281
// if all of its fields are `Copy` and `Clone`
22692282
ty::Adt(adt, args) if adt.is_anonymous() => {

library/core/src/iter/traits/iterator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ pub trait Iterator {
823823
///
824824
/// Given an element the closure must return `true` or `false`. The returned
825825
/// iterator will yield only the elements for which the closure returns
826-
/// true.
826+
/// `true`.
827827
///
828828
/// # Examples
829829
///

library/core/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@
127127
#![feature(const_hash)]
128128
#![feature(const_heap)]
129129
#![feature(const_index_range_slice_index)]
130-
#![feature(const_int_from_str)]
131130
#![feature(const_intrinsic_copy)]
132131
#![feature(const_intrinsic_forget)]
133132
#![feature(const_ipv4)]

library/core/src/num/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub enum IntErrorKind {
113113
impl ParseIntError {
114114
/// Outputs the detailed cause of parsing an integer failing.
115115
#[must_use]
116-
#[rustc_const_unstable(feature = "const_int_from_str", issue = "59133")]
116+
#[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
117117
#[stable(feature = "int_error_matching", since = "1.55.0")]
118118
pub const fn kind(&self) -> &IntErrorKind {
119119
&self.kind

0 commit comments

Comments
 (0)