Skip to content
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

Rollup of 6 pull requests #117769

Merged
merged 15 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 20 additions & 4 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2441,10 +2441,26 @@ impl<'a> Parser<'a> {
self.error_on_extra_if(&cond)?;
// Parse block, which will always fail, but we can add a nice note to the error
self.parse_block().map_err(|mut err| {
err.span_note(
cond_span,
"the `if` expression is missing a block after this condition",
);
if self.prev_token == token::Semi
&& self.token == token::AndAnd
&& let maybe_let = self.look_ahead(1, |t| t.clone())
&& maybe_let.is_keyword(kw::Let)
{
err.span_suggestion(
self.prev_token.span,
"consider removing this semicolon to parse the `let` as part of the same chain",
"",
Applicability::MachineApplicable,
).span_note(
self.token.span.to(maybe_let.span),
"you likely meant to continue parsing the let-chain starting here",
);
} else {
err.span_note(
cond_span,
"the `if` expression is missing a block after this condition",
);
}
err
})?
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_smir/src/rustc_internal/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Cons
match constant.internal(tables) {
rustc_middle::mir::Const::Ty(c) => c,
cnst => {
panic!("Trying to covert constant `{constant:?}` to type constant, but found {cnst:?}")
panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}")
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions library/alloc/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,8 @@
pub use core::fmt::Alignment;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::Error;
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub use core::fmt::FormatterFn;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{write, Arguments};
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
144 changes: 131 additions & 13 deletions library/core/src/fmt/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self {
self.field_with(name, |f| value.fmt(f))
}

/// Adds a new field to the generated struct output.
///
/// This method is equivalent to [`DebugStruct::field`], but formats the
/// value using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub fn field_with<F>(&mut self, name: &str, value_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.result = self.result.and_then(|_| {
if self.is_pretty() {
if !self.has_fields {
Expand All @@ -140,14 +152,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
writer.write_str(name)?;
writer.write_str(": ")?;
value.fmt(&mut writer)?;
value_fmt(&mut writer)?;
writer.write_str(",\n")
} else {
let prefix = if self.has_fields { ", " } else { " { " };
self.fmt.write_str(prefix)?;
self.fmt.write_str(name)?;
self.fmt.write_str(": ")?;
value.fmt(self.fmt)
value_fmt(self.fmt)
}
});

Expand Down Expand Up @@ -315,6 +327,18 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self {
self.field_with(|f| value.fmt(f))
}

/// Adds a new field to the generated tuple struct output.
///
/// This method is equivalent to [`DebugTuple::field`], but formats the
/// value using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub fn field_with<F>(&mut self, value_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.result = self.result.and_then(|_| {
if self.is_pretty() {
if self.fields == 0 {
Expand All @@ -323,12 +347,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
let mut slot = None;
let mut state = Default::default();
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
value.fmt(&mut writer)?;
value_fmt(&mut writer)?;
writer.write_str(",\n")
} else {
let prefix = if self.fields == 0 { "(" } else { ", " };
self.fmt.write_str(prefix)?;
value.fmt(self.fmt)
value_fmt(self.fmt)
}
});

Expand Down Expand Up @@ -385,7 +409,10 @@ struct DebugInner<'a, 'b: 'a> {
}

impl<'a, 'b: 'a> DebugInner<'a, 'b> {
fn entry(&mut self, entry: &dyn fmt::Debug) {
fn entry_with<F>(&mut self, entry_fmt: F)
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.result = self.result.and_then(|_| {
if self.is_pretty() {
if !self.has_fields {
Expand All @@ -394,13 +421,13 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
let mut slot = None;
let mut state = Default::default();
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
entry.fmt(&mut writer)?;
entry_fmt(&mut writer)?;
writer.write_str(",\n")
} else {
if self.has_fields {
self.fmt.write_str(", ")?
}
entry.fmt(self.fmt)
entry_fmt(self.fmt)
}
});

Expand Down Expand Up @@ -475,7 +502,20 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
self.inner.entry(entry);
self.inner.entry_with(|f| entry.fmt(f));
self
}

/// Adds a new entry to the set output.
///
/// This method is equivalent to [`DebugSet::entry`], but formats the
/// entry using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.inner.entry_with(entry_fmt);
self
}

Expand Down Expand Up @@ -605,7 +645,20 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
self.inner.entry(entry);
self.inner.entry_with(|f| entry.fmt(f));
self
}

/// Adds a new entry to the list output.
///
/// This method is equivalent to [`DebugList::entry`], but formats the
/// entry using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.inner.entry_with(entry_fmt);
self
}

Expand Down Expand Up @@ -775,6 +828,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
/// ```
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self {
self.key_with(|f| key.fmt(f))
}

/// Adds the key part of a new entry to the map output.
///
/// This method is equivalent to [`DebugMap::key`], but formats the
/// key using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub fn key_with<F>(&mut self, key_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.result = self.result.and_then(|_| {
assert!(
!self.has_key,
Expand All @@ -789,13 +854,13 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
let mut slot = None;
self.state = Default::default();
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
key.fmt(&mut writer)?;
key_fmt(&mut writer)?;
writer.write_str(": ")?;
} else {
if self.has_fields {
self.fmt.write_str(", ")?
}
key.fmt(self.fmt)?;
key_fmt(self.fmt)?;
self.fmt.write_str(": ")?;
}

Expand Down Expand Up @@ -839,16 +904,28 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
/// ```
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self {
self.value_with(|f| value.fmt(f))
}

/// Adds the value part of a new entry to the map output.
///
/// This method is equivalent to [`DebugMap::value`], but formats the
/// value using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub fn value_with<F>(&mut self, value_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.result = self.result.and_then(|_| {
assert!(self.has_key, "attempted to format a map value before its key");

if self.is_pretty() {
let mut slot = None;
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
value.fmt(&mut writer)?;
value_fmt(&mut writer)?;
writer.write_str(",\n")?;
} else {
value.fmt(self.fmt)?;
value_fmt(self.fmt)?;
}

self.has_key = false;
Expand Down Expand Up @@ -936,3 +1013,44 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
self.fmt.alternate()
}
}

/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
///
/// # Examples
///
/// ```
/// #![feature(debug_closure_helpers)]
/// use std::fmt;
///
/// let value = 'a';
/// assert_eq!(format!("{}", value), "a");
/// assert_eq!(format!("{:?}", value), "'a'");
///
/// let wrapped = fmt::FormatterFn(|f| write!(f, "{:?}", &value));
/// assert_eq!(format!("{}", wrapped), "'a'");
/// assert_eq!(format!("{:?}", wrapped), "'a'");
/// ```
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub struct FormatterFn<F>(pub F)
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result;

#[unstable(feature = "debug_closure_helpers", issue = "117729")]
impl<F> fmt::Debug for FormatterFn<F>
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(self.0)(f)
}
}

#[unstable(feature = "debug_closure_helpers", issue = "117729")]
impl<F> fmt::Display for FormatterFn<F>
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(self.0)(f)
}
}
3 changes: 3 additions & 0 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ pub enum Alignment {
#[stable(feature = "debug_builders", since = "1.2.0")]
pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};

#[unstable(feature = "debug_closure_helpers", issue = "117729")]
pub use self::builders::FormatterFn;

/// The type returned by formatter methods.
///
/// # Examples
Expand Down
10 changes: 10 additions & 0 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,11 @@ impl<T> [T] {
/// Calling this method with an out-of-bounds index is *[undefined behavior]*
/// even if the resulting reference is not used.
///
/// You can think of this like `.get(index).unwrap_unchecked()`. It's UB
/// to call `.get_unchecked(len)`, even if you immediately convert to a
/// pointer. And it's UB to call `.get_unchecked(..len + 1)`,
/// `.get_unchecked(..=len)`, or similar.
///
/// [`get`]: slice::get
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
Expand Down Expand Up @@ -675,6 +680,11 @@ impl<T> [T] {
/// Calling this method with an out-of-bounds index is *[undefined behavior]*
/// even if the resulting reference is not used.
///
/// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's
/// UB to call `.get_unchecked_mut(len)`, even if you immediately convert
/// to a pointer. And it's UB to call `.get_unchecked_mut(..len + 1)`,
/// `.get_unchecked_mut(..=len)`, or similar.
///
/// [`get_mut`]: slice::get_mut
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
Expand Down
Loading
Loading