Skip to content

Commit 0bd13c3

Browse files
committed
Auto merge of #150306 - JonathanBrouwer:rollup-pxp25ib, r=JonathanBrouwer
Rollup of 6 pull requests Successful merges: - #150130 (Support syntax for one-line trait reuse) - #150205 (compiletest: Add `LineNumber` newtype to avoid `+1` magic here and there) - #150282 (move a ui test to coretests unit test) - #150295 (Fix compilation error in hermit-abi time.rs) - #150301 (std: remove unsupported pipe module from VEXos pal) - #150303 (`target_features::Stability`: tweak docs of `requires_nightly()`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0ac9e59 + d7eee19 commit 0bd13c3

31 files changed

+944
-80
lines changed

compiler/rustc_parse/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ parse_default_not_followed_by_item = `default` is not followed by an item
162162
.label = the `default` qualifier
163163
.note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
164164
165+
parse_delegation_non_trait_impl_reuse = only trait impls can be reused
166+
165167
parse_do_catch_syntax_removed = found removed `do catch` syntax
166168
.note = following RFC #2388, the new non-placeholder syntax is `try`
167169
.suggestion = replace with the new syntax

compiler/rustc_parse/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3671,3 +3671,10 @@ pub(crate) struct VarargsWithoutPattern {
36713671
#[suggestion(code = "_: ...", applicability = "machine-applicable")]
36723672
pub span: Span,
36733673
}
3674+
3675+
#[derive(Diagnostic)]
3676+
#[diag(parse_delegation_non_trait_impl_reuse)]
3677+
pub(crate) struct ImplReuseInherentImpl {
3678+
#[primary_span]
3679+
pub span: Span,
3680+
}

compiler/rustc_parse/src/parser/item.rs

Lines changed: 111 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ impl<'a> Parser<'a> {
117117
}
118118
}
119119

120+
enum ReuseKind {
121+
Path,
122+
Impl,
123+
}
124+
120125
impl<'a> Parser<'a> {
121126
pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Box<Item>>> {
122127
let fn_parse_mode =
@@ -249,9 +254,9 @@ impl<'a> Parser<'a> {
249254
} else if self.check_keyword_case(exp!(Trait), case) || self.check_trait_front_matter() {
250255
// TRAIT ITEM
251256
self.parse_item_trait(attrs, lo)?
252-
} else if self.check_impl_frontmatter() {
257+
} else if self.check_impl_frontmatter(0) {
253258
// IMPL ITEM
254-
self.parse_item_impl(attrs, def_())?
259+
self.parse_item_impl(attrs, def_(), false)?
255260
} else if let Const::Yes(const_span) = self.parse_constness(case) {
256261
// CONST ITEM
257262
self.recover_const_mut(const_span);
@@ -265,8 +270,8 @@ impl<'a> Parser<'a> {
265270
rhs,
266271
define_opaque: None,
267272
}))
268-
} else if self.is_reuse_path_item() {
269-
self.parse_item_delegation()?
273+
} else if let Some(kind) = self.is_reuse_item() {
274+
self.parse_item_delegation(attrs, def_(), kind)?
270275
} else if self.check_keyword_case(exp!(Mod), case)
271276
|| self.check_keyword_case(exp!(Unsafe), case) && self.is_keyword_ahead(1, &[kw::Mod])
272277
{
@@ -367,16 +372,25 @@ impl<'a> Parser<'a> {
367372
/// When parsing a statement, would the start of a path be an item?
368373
pub(super) fn is_path_start_item(&mut self) -> bool {
369374
self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }`
370-
|| self.is_reuse_path_item()
375+
|| self.is_reuse_item().is_some() // yes: `reuse impl Trait for Struct { self.0 }`, yes: `reuse some_path::foo;`
371376
|| self.check_trait_front_matter() // no: `auto::b`, yes: `auto trait X { .. }`
372377
|| self.is_async_fn() // no(2015): `async::b`, yes: `async fn`
373378
|| matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac`
374379
}
375380

376-
fn is_reuse_path_item(&mut self) -> bool {
381+
fn is_reuse_item(&mut self) -> Option<ReuseKind> {
382+
if !self.token.is_keyword(kw::Reuse) {
383+
return None;
384+
}
385+
377386
// no: `reuse ::path` for compatibility reasons with macro invocations
378-
self.token.is_keyword(kw::Reuse)
379-
&& self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep)
387+
if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
388+
Some(ReuseKind::Path)
389+
} else if self.check_impl_frontmatter(1) {
390+
Some(ReuseKind::Impl)
391+
} else {
392+
None
393+
}
380394
}
381395

382396
/// Are we sure this could not possibly be a macro invocation?
@@ -560,6 +574,7 @@ impl<'a> Parser<'a> {
560574
&mut self,
561575
attrs: &mut AttrVec,
562576
defaultness: Defaultness,
577+
is_reuse: bool,
563578
) -> PResult<'a, ItemKind> {
564579
let mut constness = self.parse_constness(Case::Sensitive);
565580
let safety = self.parse_safety(Case::Sensitive);
@@ -628,7 +643,11 @@ impl<'a> Parser<'a> {
628643

629644
generics.where_clause = self.parse_where_clause()?;
630645

631-
let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?;
646+
let impl_items = if is_reuse {
647+
Default::default()
648+
} else {
649+
self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
650+
};
632651

633652
let (of_trait, self_ty) = match ty_second {
634653
Some(ty_second) => {
@@ -699,10 +718,76 @@ impl<'a> Parser<'a> {
699718
Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
700719
}
701720

702-
fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> {
721+
fn parse_item_delegation(
722+
&mut self,
723+
attrs: &mut AttrVec,
724+
defaultness: Defaultness,
725+
kind: ReuseKind,
726+
) -> PResult<'a, ItemKind> {
703727
let span = self.token.span;
704728
self.expect_keyword(exp!(Reuse))?;
705729

730+
let item_kind = match kind {
731+
ReuseKind::Path => self.parse_path_like_delegation(),
732+
ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
733+
}?;
734+
735+
self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
736+
737+
Ok(item_kind)
738+
}
739+
740+
fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
741+
Ok(if self.check(exp!(OpenBrace)) {
742+
Some(self.parse_block()?)
743+
} else {
744+
self.expect(exp!(Semi))?;
745+
None
746+
})
747+
}
748+
749+
fn parse_impl_delegation(
750+
&mut self,
751+
span: Span,
752+
attrs: &mut AttrVec,
753+
defaultness: Defaultness,
754+
) -> PResult<'a, ItemKind> {
755+
let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
756+
let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { unreachable!() };
757+
758+
let until_expr_span = span.to(self.prev_token.span);
759+
760+
let Some(of_trait) = of_trait else {
761+
return Err(self
762+
.dcx()
763+
.create_err(errors::ImplReuseInherentImpl { span: until_expr_span }));
764+
};
765+
766+
let body = self.parse_delegation_body()?;
767+
let whole_reuse_span = span.to(self.prev_token.span);
768+
769+
items.push(Box::new(AssocItem {
770+
id: DUMMY_NODE_ID,
771+
attrs: Default::default(),
772+
span: whole_reuse_span,
773+
tokens: None,
774+
vis: Visibility {
775+
kind: VisibilityKind::Inherited,
776+
span: whole_reuse_span,
777+
tokens: None,
778+
},
779+
kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
780+
qself: None,
781+
prefix: of_trait.trait_ref.path.clone(),
782+
suffixes: None,
783+
body,
784+
})),
785+
}));
786+
787+
Ok(impl_item)
788+
}
789+
790+
fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
706791
let (qself, path) = if self.eat_lt() {
707792
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
708793
(Some(qself), path)
@@ -713,43 +798,35 @@ impl<'a> Parser<'a> {
713798
let rename = |this: &mut Self| {
714799
Ok(if this.eat_keyword(exp!(As)) { Some(this.parse_ident()?) } else { None })
715800
};
716-
let body = |this: &mut Self| {
717-
Ok(if this.check(exp!(OpenBrace)) {
718-
Some(this.parse_block()?)
719-
} else {
720-
this.expect(exp!(Semi))?;
721-
None
722-
})
723-
};
724801

725-
let item_kind = if self.eat_path_sep() {
802+
Ok(if self.eat_path_sep() {
726803
let suffixes = if self.eat(exp!(Star)) {
727804
None
728805
} else {
729806
let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
730807
Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0)
731808
};
732-
let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? };
733-
ItemKind::DelegationMac(Box::new(deleg))
809+
810+
ItemKind::DelegationMac(Box::new(DelegationMac {
811+
qself,
812+
prefix: path,
813+
suffixes,
814+
body: self.parse_delegation_body()?,
815+
}))
734816
} else {
735817
let rename = rename(self)?;
736818
let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
737-
let deleg = Delegation {
819+
820+
ItemKind::Delegation(Box::new(Delegation {
738821
id: DUMMY_NODE_ID,
739822
qself,
740823
path,
741824
ident,
742825
rename,
743-
body: body(self)?,
826+
body: self.parse_delegation_body()?,
744827
from_glob: false,
745-
};
746-
ItemKind::Delegation(Box::new(deleg))
747-
};
748-
749-
let span = span.to(self.prev_token.span);
750-
self.psess.gated_spans.gate(sym::fn_delegation, span);
751-
752-
Ok(item_kind)
828+
}))
829+
})
753830
}
754831

755832
fn parse_item_list<T>(
@@ -2594,7 +2671,7 @@ impl<'a> Parser<'a> {
25942671
Ok(body)
25952672
}
25962673

2597-
fn check_impl_frontmatter(&mut self) -> bool {
2674+
fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
25982675
const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
25992676
// In contrast to the loop below, this call inserts `impl` into the
26002677
// list of expected tokens shown in diagnostics.
@@ -2603,7 +2680,7 @@ impl<'a> Parser<'a> {
26032680
}
26042681
let mut i = 0;
26052682
while i < ALL_QUALS.len() {
2606-
let action = self.look_ahead(i, |token| {
2683+
let action = self.look_ahead(i + look_ahead, |token| {
26072684
if token.is_keyword(kw::Impl) {
26082685
return Some(true);
26092686
}
@@ -2618,6 +2695,7 @@ impl<'a> Parser<'a> {
26182695
}
26192696
i += 1;
26202697
}
2698+
26212699
self.is_keyword_ahead(i, &[kw::Impl])
26222700
}
26232701

compiler/rustc_target/src/target_features.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ impl Stability {
6262
/// the feature gate to actually be enabled when using a nightly compiler.)
6363
///
6464
/// Before calling this, ensure the feature is even permitted for this use:
65-
/// - for `#[target_feature]`/`-Ctarget-feature`, check `allow_toggle()`
66-
/// - for `cfg(target_feature)`, check `in_cfg`
65+
/// - for `#[target_feature]`/`-Ctarget-feature`, check `toggle_allowed()`
66+
/// - for `cfg(target_feature)`, check `in_cfg()`
6767
pub fn requires_nightly(&self) -> Option<Symbol> {
6868
match *self {
6969
Stability::Unstable(nightly_feature) => Some(nightly_feature),

library/coretests/tests/fmt/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,25 @@ fn test_fmt_debug_of_mut_reference() {
7676
assert_eq!(format!("{:?}", &mut x), "0");
7777
}
7878

79+
#[test]
80+
fn test_fmt_pointer() {
81+
use std::rc::Rc;
82+
use std::sync::Arc;
83+
let p: *const u8 = std::ptr::null();
84+
let rc = Rc::new(1usize);
85+
let arc = Arc::new(1usize);
86+
let b = Box::new("hi");
87+
88+
let _ = format!("{rc:p}{arc:p}{b:p}");
89+
90+
if cfg!(target_pointer_width = "32") {
91+
assert_eq!(format!("{:#p}", p), "0x00000000");
92+
} else {
93+
assert_eq!(format!("{:#p}", p), "0x0000000000000000");
94+
}
95+
assert_eq!(format!("{:p}", p), "0x0");
96+
}
97+
7998
#[test]
8099
fn test_default_write_impls() {
81100
use core::fmt::Write;

library/std/src/sys/pal/hermit/time.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,9 @@ pub struct SystemTime(Timespec);
213213
pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
214214

215215
impl SystemTime {
216-
pub const MAX: SystemTime = SystemTime { t: Timespec::MAX };
216+
pub const MAX: SystemTime = SystemTime(Timespec::MAX);
217217

218-
pub const MIN: SystemTime = SystemTime { t: Timespec::MIN };
218+
pub const MIN: SystemTime = SystemTime(Timespec::MIN);
219219

220220
pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime {
221221
SystemTime(Timespec::new(tv_sec, tv_nsec))

library/std/src/sys/pal/vexos/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
pub mod os;
2-
#[path = "../unsupported/pipe.rs"]
3-
pub mod pipe;
42
pub mod time;
53

64
#[expect(dead_code)]

src/tools/compiletest/src/directives.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ mod directive_names;
2929
mod file;
3030
mod handlers;
3131
mod line;
32+
mod line_number;
33+
pub(crate) use line_number::LineNumber;
3234
mod needs;
3335
#[cfg(test)]
3436
mod tests;
@@ -591,7 +593,7 @@ fn iter_directives(
591593
];
592594
// Process the extra implied directives, with a dummy line number of 0.
593595
for directive_str in extra_directives {
594-
let directive_line = line_directive(testfile, 0, directive_str)
596+
let directive_line = line_directive(testfile, LineNumber::ZERO, directive_str)
595597
.unwrap_or_else(|| panic!("bad extra-directive line: {directive_str:?}"));
596598
it(&directive_line);
597599
}

src/tools/compiletest/src/directives/file.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use camino::Utf8Path;
22

3+
use crate::directives::LineNumber;
34
use crate::directives::line::{DirectiveLine, line_directive};
45

56
pub(crate) struct FileDirectives<'a> {
@@ -11,7 +12,7 @@ impl<'a> FileDirectives<'a> {
1112
pub(crate) fn from_file_contents(path: &'a Utf8Path, file_contents: &'a str) -> Self {
1213
let mut lines = vec![];
1314

14-
for (line_number, ln) in (1..).zip(file_contents.lines()) {
15+
for (line_number, ln) in LineNumber::enumerate().zip(file_contents.lines()) {
1516
let ln = ln.trim();
1617

1718
if let Some(directive_line) = line_directive(path, line_number, ln) {

src/tools/compiletest/src/directives/line.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ use std::fmt;
22

33
use camino::Utf8Path;
44

5+
use crate::directives::LineNumber;
6+
57
const COMPILETEST_DIRECTIVE_PREFIX: &str = "//@";
68

79
/// If the given line begins with the appropriate comment prefix for a directive,
810
/// returns a struct containing various parts of the directive.
911
pub(crate) fn line_directive<'a>(
1012
file_path: &'a Utf8Path,
11-
line_number: usize,
13+
line_number: LineNumber,
1214
original_line: &'a str,
1315
) -> Option<DirectiveLine<'a>> {
1416
// Ignore lines that don't start with the comment prefix.
@@ -60,7 +62,7 @@ pub(crate) struct DirectiveLine<'a> {
6062
/// Mostly used for diagnostics, but some directives (e.g. `//@ pp-exact`)
6163
/// also use it to compute a value based on the filename.
6264
pub(crate) file_path: &'a Utf8Path,
63-
pub(crate) line_number: usize,
65+
pub(crate) line_number: LineNumber,
6466

6567
/// Some test directives start with a revision name in square brackets
6668
/// (e.g. `[foo]`), and only apply to that revision of the test.

0 commit comments

Comments
 (0)