Skip to content

Commit

Permalink
Auto merge of #97654 - Dylan-DPC:rollup-w6zrzxf, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #97420 (Be a little nicer with casts when formatting `fn` pointers)
 - #97450 ([RFC 2011] Basic compiler infrastructure)
 - #97599 (Fix JSON reexport ICE)
 - #97617 (Rustdoc anonymous reexports)
 - #97636 (Revert #96682.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 2, 2022
2 parents 20976ba + 1d71237 commit 44e9516
Show file tree
Hide file tree
Showing 31 changed files with 336 additions and 208 deletions.
5 changes: 2 additions & 3 deletions compiler/rustc_ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,11 @@ pub enum Delimiter {
Brace,
/// `[ ... ]`
Bracket,
/// `/*«*/ ... /*»*/`
/// `Ø ... Ø`
/// An invisible delimiter, that may, for example, appear around tokens coming from a
/// "macro variable" `$var`. It is important to preserve operator priorities in cases like
/// `$var * 3` where `$var` is `1 + 2`.
/// Invisible delimiters are not directly writable in normal Rust code except as comments.
/// Therefore, they might not survive a roundtrip of a token stream through a string.
/// Invisible delimiters might not survive roundtrip of a token stream through a string.
Invisible,
}

Expand Down
23 changes: 5 additions & 18 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,28 +590,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.nbsp();
}
self.word("{");
let empty = tts.is_empty();
if !empty {
if !tts.is_empty() {
self.space();
}
self.ibox(0);
self.print_tts(tts, convert_dollar_crate);
self.end();
self.bclose(span, empty);
}
Some(Delimiter::Invisible) => {
self.word("/*«*/");
let empty = tts.is_empty();
if !empty {
self.space();
}
self.ibox(0);
self.print_tts(tts, convert_dollar_crate);
self.end();
if !empty {
self.space();
}
self.word("/*»*/");
self.bclose(span, empty);
}
Some(delim) => {
let token_str = self.token_kind_to_string(&token::OpenDelim(delim));
Expand Down Expand Up @@ -786,8 +772,9 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
token::CloseDelim(Delimiter::Bracket) => "]".into(),
token::OpenDelim(Delimiter::Brace) => "{".into(),
token::CloseDelim(Delimiter::Brace) => "}".into(),
token::OpenDelim(Delimiter::Invisible) => "/*«*/".into(),
token::CloseDelim(Delimiter::Invisible) => "/*»*/".into(),
token::OpenDelim(Delimiter::Invisible) | token::CloseDelim(Delimiter::Invisible) => {
"".into()
}
token::Pound => "#".into(),
token::Dollar => "$".into(),
token::Question => "?".into(),
Expand Down
70 changes: 48 additions & 22 deletions compiler/rustc_builtin_macros/src/assert.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod context;

use crate::edition_panic::use_panic_2021;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{self as ast, *};
use rustc_ast::{Expr, ExprKind, MacArgs, MacCall, MacDelimiter, Path, PathSegment, UnOp};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, PResult};
use rustc_expand::base::*;
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
use rustc_parse::parser::Parser;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
Expand All @@ -25,13 +27,13 @@ pub fn expand_assert<'cx>(

// `core::panic` and `std::panic` are different macros, so we use call-site
// context to pick up whichever is currently in scope.
let sp = cx.with_call_site_ctxt(span);
let call_site_span = cx.with_call_site_ctxt(span);

let panic_call = if let Some(tokens) = custom_message {
let path = if use_panic_2021(span) {
let panic_path = || {
if use_panic_2021(span) {
// On edition 2021, we always call `$crate::panic::panic_2021!()`.
Path {
span: sp,
span: call_site_span,
segments: cx
.std_path(&[sym::panic, sym::panic_2021])
.into_iter()
Expand All @@ -42,27 +44,40 @@ pub fn expand_assert<'cx>(
} else {
// Before edition 2021, we call `panic!()` unqualified,
// such that it calls either `std::panic!()` or `core::panic!()`.
Path::from_ident(Ident::new(sym::panic, sp))
};
// Pass the custom message to panic!().
cx.expr(
sp,
Path::from_ident(Ident::new(sym::panic, call_site_span))
}
};

// Simply uses the user provided message instead of generating custom outputs
let expr = if let Some(tokens) = custom_message {
let then = cx.expr(
call_site_span,
ExprKind::MacCall(MacCall {
path,
path: panic_path(),
args: P(MacArgs::Delimited(
DelimSpan::from_single(sp),
DelimSpan::from_single(call_site_span),
MacDelimiter::Parenthesis,
tokens,
)),
prior_type_ascription: None,
}),
)
} else {
);
expr_if_not(cx, call_site_span, cond_expr, then, None)
}
// If `generic_assert` is enabled, generates rich captured outputs
//
// FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949
else if let Some(features) = cx.ecfg.features && features.generic_assert {
context::Context::new(cx, call_site_span).build(cond_expr, panic_path())
}
// If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..."
// string
else {
// Pass our own message directly to $crate::panicking::panic(),
// because it might contain `{` and `}` that should always be
// passed literally.
cx.expr_call_global(
sp,
let then = cx.expr_call_global(
call_site_span,
cx.std_path(&[sym::panicking, sym::panic]),
vec![cx.expr_str(
DUMMY_SP,
Expand All @@ -71,18 +86,29 @@ pub fn expand_assert<'cx>(
pprust::expr_to_string(&cond_expr).escape_debug()
)),
)],
)
);
expr_if_not(cx, call_site_span, cond_expr, then, None)
};
let if_expr =
cx.expr_if(sp, cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), panic_call, None);
MacEager::expr(if_expr)

MacEager::expr(expr)
}

struct Assert {
cond_expr: P<ast::Expr>,
cond_expr: P<Expr>,
custom_message: Option<TokenStream>,
}

// if !{ ... } { ... } else { ... }
fn expr_if_not(
cx: &ExtCtxt<'_>,
span: Span,
cond: P<Expr>,
then: P<Expr>,
els: Option<P<Expr>>,
) -> P<Expr> {
cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
}

fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
let mut parser = cx.new_parser_from_tts(stream);

Expand Down
44 changes: 44 additions & 0 deletions compiler/rustc_builtin_macros/src/assert/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use rustc_ast::{ptr::P, Expr, Path};
use rustc_expand::base::ExtCtxt;
use rustc_span::Span;

pub(super) struct Context<'cx, 'a> {
cx: &'cx ExtCtxt<'a>,
span: Span,
}

impl<'cx, 'a> Context<'cx, 'a> {
pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self {
Self { cx, span }
}

/// Builds the whole `assert!` expression.
///
/// {
/// use ::core::asserting::{ ... };
///
/// let mut __capture0 = Capture::new();
/// ...
/// ...
/// ...
///
/// if !{
/// ...
/// ...
/// ...
/// } {
/// panic!(
/// "Assertion failed: ... \n With expansion: ...",
/// __capture0,
/// ...
/// ...
/// ...
/// );
/// }
/// }
pub(super) fn build(self, _cond_expr: P<Expr>, _panic_path: Path) -> P<Expr> {
let Self { cx, span, .. } = self;
let stmts = Vec::new();
cx.expr_block(cx.block(span, stmts))
}
}
5 changes: 3 additions & 2 deletions compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! This crate contains implementations of built-in macros and other code generating facilities
//! injecting code into the crate before it is lowered to HIR.

#![allow(rustc::potential_query_instability)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(is_sorted)]
#![feature(nll)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(nll)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_quote)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]

extern crate proc_macro;

Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_expand/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl<'a> ExtCtxt<'a> {
attrs: AttrVec::new(),
tokens: None,
});
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
self.stmt_local(local, sp)
}

// Generates `let _: Type;`, which is usually used for type assertions.
Expand All @@ -174,6 +174,10 @@ impl<'a> ExtCtxt<'a> {
attrs: AttrVec::new(),
tokens: None,
});
self.stmt_local(local, span)
}

pub fn stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt {
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span }
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ declare_features! (
(active, allow_internal_unstable, "1.0.0", None, None),
/// Allows identifying the `compiler_builtins` crate.
(active, compiler_builtins, "1.13.0", None, None),
/// Outputs useful `assert!` messages
(active, generic_assert, "1.63.0", None, None),
/// Allows using the `rust-intrinsic`'s "ABI".
(active, intrinsics, "1.0.0", None, None),
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ symbols! {
generator_state,
generators,
generic_arg_infer,
generic_assert,
generic_associated_types,
generic_associated_types_extended,
generic_const_exprs,
Expand Down
54 changes: 30 additions & 24 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2233,35 +2233,41 @@ impl Display for char {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Pointer for *const T {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
/// Since the formatting will be identical for all pointer types, use a non-monomorphized
/// implementation for the actual formatting to reduce the amount of codegen work needed
fn inner(ptr: *const (), f: &mut Formatter<'_>) -> Result {
let old_width = f.width;
let old_flags = f.flags;

// The alternate flag is already treated by LowerHex as being special-
// it denotes whether to prefix with 0x. We use it to work out whether
// or not to zero extend, and then unconditionally set it to get the
// prefix.
if f.alternate() {
f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);

if f.width.is_none() {
f.width = Some((usize::BITS / 4) as usize + 2);
}
}
f.flags |= 1 << (FlagV1::Alternate as u32);
// Cast is needed here because `.addr()` requires `T: Sized`.
pointer_fmt_inner((*self as *const ()).addr(), f)
}
}

let ret = LowerHex::fmt(&(ptr.addr()), f);
/// Since the formatting will be identical for all pointer types, use a non-monomorphized
/// implementation for the actual formatting to reduce the amount of codegen work needed.
///
/// This uses `ptr_addr: usize` and not `ptr: *const ()` to be able to use this for
/// `fn(...) -> ...` without using [problematic] "Oxford Casts".
///
/// [problematic]: https://github.com/rust-lang/rust/issues/95489
pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result {
let old_width = f.width;
let old_flags = f.flags;

f.width = old_width;
f.flags = old_flags;
// The alternate flag is already treated by LowerHex as being special-
// it denotes whether to prefix with 0x. We use it to work out whether
// or not to zero extend, and then unconditionally set it to get the
// prefix.
if f.alternate() {
f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);

ret
if f.width.is_none() {
f.width = Some((usize::BITS / 4) as usize + 2);
}

inner(*self as *const (), f)
}
f.flags |= 1 << (FlagV1::Alternate as u32);

let ret = LowerHex::fmt(&ptr_addr, f);

f.width = old_width;
f.flags = old_flags;

ret
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
14 changes: 2 additions & 12 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1878,24 +1878,14 @@ macro_rules! fnptr_impls_safety_abi {
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// HACK: The intermediate cast as usize is required for AVR
// so that the address space of the source function pointer
// is preserved in the final function pointer.
//
// https://github.com/avr-rust/rust/issues/143
fmt::Pointer::fmt(&(*self as usize as *const ()), f)
fmt::pointer_fmt_inner(*self as usize, f)
}
}

#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// HACK: The intermediate cast as usize is required for AVR
// so that the address space of the source function pointer
// is preserved in the final function pointer.
//
// https://github.com/avr-rust/rust/issues/143
fmt::Pointer::fmt(&(*self as usize as *const ()), f)
fmt::pointer_fmt_inner(*self as usize, f)
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,12 +703,11 @@ pub enum Delimiter {
/// `[ ... ]`
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Bracket,
/// `/*«*/ ... /*»*/`
/// `Ø ... Ø`
/// An invisible delimiter, that may, for example, appear around tokens coming from a
/// "macro variable" `$var`. It is important to preserve operator priorities in cases like
/// `$var * 3` where `$var` is `1 + 2`.
/// Invisible delimiters are not directly writable in normal Rust code except as comments.
/// Therefore, they might not survive a roundtrip of a token stream through a string.
/// Invisible delimiters might not survive roundtrip of a token stream through a string.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
None,
}
Expand Down
Loading

0 comments on commit 44e9516

Please sign in to comment.