Skip to content

Commit 15bf62b

Browse files
authored
Rollup merge of rust-lang#97450 - c410-f3r:assert-compiler, r=oli-obk
[RFC 2011] Basic compiler infrastructure Splitting rust-lang#96496 into smaller pieces as was done in rust-lang#97233. Hope review will be easier. This PR practically contains no logic and only serves as a building ground for the actual code that will be placed in a posterior step. * Adds `context.rs` to place the new `assert!` logic. Has a lot of unused elements but all of them are used by the implementation. * Creates an unstable flag because the feature is not yet complete and also to allow external feedback. * Creates the necessary `sym` identifiers that are mostly based on the library elements -> https://github.com/rust-lang/rust/blob/master/library/core/src/asserting.rs * Modifies `assert.rs` to branch to `context.rs` if the unstable flag is enabled. * Adds a test to satisfy tidy but the test does nothing in reality.
2 parents 0b2d48e + aa115eb commit 15bf62b

File tree

7 files changed

+129
-25
lines changed

7 files changed

+129
-25
lines changed

compiler/rustc_builtin_macros/src/assert.rs

+48-22
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
mod context;
2+
13
use crate::edition_panic::use_panic_2021;
24
use rustc_ast::ptr::P;
35
use rustc_ast::token;
46
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
5-
use rustc_ast::{self as ast, *};
7+
use rustc_ast::{Expr, ExprKind, MacArgs, MacCall, MacDelimiter, Path, PathSegment, UnOp};
68
use rustc_ast_pretty::pprust;
79
use rustc_errors::{Applicability, PResult};
8-
use rustc_expand::base::*;
10+
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
911
use rustc_parse::parser::Parser;
1012
use rustc_span::symbol::{sym, Ident, Symbol};
1113
use rustc_span::{Span, DUMMY_SP};
@@ -25,13 +27,13 @@ pub fn expand_assert<'cx>(
2527

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

30-
let panic_call = if let Some(tokens) = custom_message {
31-
let path = if use_panic_2021(span) {
32+
let panic_path = || {
33+
if use_panic_2021(span) {
3234
// On edition 2021, we always call `$crate::panic::panic_2021!()`.
3335
Path {
34-
span: sp,
36+
span: call_site_span,
3537
segments: cx
3638
.std_path(&[sym::panic, sym::panic_2021])
3739
.into_iter()
@@ -42,27 +44,40 @@ pub fn expand_assert<'cx>(
4244
} else {
4345
// Before edition 2021, we call `panic!()` unqualified,
4446
// such that it calls either `std::panic!()` or `core::panic!()`.
45-
Path::from_ident(Ident::new(sym::panic, sp))
46-
};
47-
// Pass the custom message to panic!().
48-
cx.expr(
49-
sp,
47+
Path::from_ident(Ident::new(sym::panic, call_site_span))
48+
}
49+
};
50+
51+
// Simply uses the user provided message instead of generating custom outputs
52+
let expr = if let Some(tokens) = custom_message {
53+
let then = cx.expr(
54+
call_site_span,
5055
ExprKind::MacCall(MacCall {
51-
path,
56+
path: panic_path(),
5257
args: P(MacArgs::Delimited(
53-
DelimSpan::from_single(sp),
58+
DelimSpan::from_single(call_site_span),
5459
MacDelimiter::Parenthesis,
5560
tokens,
5661
)),
5762
prior_type_ascription: None,
5863
}),
59-
)
60-
} else {
64+
);
65+
expr_if_not(cx, call_site_span, cond_expr, then, None)
66+
}
67+
// If `generic_assert` is enabled, generates rich captured outputs
68+
//
69+
// FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949
70+
else if let Some(features) = cx.ecfg.features && features.generic_assert {
71+
context::Context::new(cx, call_site_span).build(cond_expr, panic_path())
72+
}
73+
// If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..."
74+
// string
75+
else {
6176
// Pass our own message directly to $crate::panicking::panic(),
6277
// because it might contain `{` and `}` that should always be
6378
// passed literally.
64-
cx.expr_call_global(
65-
sp,
79+
let then = cx.expr_call_global(
80+
call_site_span,
6681
cx.std_path(&[sym::panicking, sym::panic]),
6782
vec![cx.expr_str(
6883
DUMMY_SP,
@@ -71,18 +86,29 @@ pub fn expand_assert<'cx>(
7186
pprust::expr_to_string(&cond_expr).escape_debug()
7287
)),
7388
)],
74-
)
89+
);
90+
expr_if_not(cx, call_site_span, cond_expr, then, None)
7591
};
76-
let if_expr =
77-
cx.expr_if(sp, cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), panic_call, None);
78-
MacEager::expr(if_expr)
92+
93+
MacEager::expr(expr)
7994
}
8095

8196
struct Assert {
82-
cond_expr: P<ast::Expr>,
97+
cond_expr: P<Expr>,
8398
custom_message: Option<TokenStream>,
8499
}
85100

101+
// if !{ ... } { ... } else { ... }
102+
fn expr_if_not(
103+
cx: &ExtCtxt<'_>,
104+
span: Span,
105+
cond: P<Expr>,
106+
then: P<Expr>,
107+
els: Option<P<Expr>>,
108+
) -> P<Expr> {
109+
cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
110+
}
111+
86112
fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
87113
let mut parser = cx.new_parser_from_tts(stream);
88114

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use rustc_ast::{ptr::P, Expr, Path};
2+
use rustc_expand::base::ExtCtxt;
3+
use rustc_span::Span;
4+
5+
pub(super) struct Context<'cx, 'a> {
6+
cx: &'cx ExtCtxt<'a>,
7+
span: Span,
8+
}
9+
10+
impl<'cx, 'a> Context<'cx, 'a> {
11+
pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self {
12+
Self { cx, span }
13+
}
14+
15+
/// Builds the whole `assert!` expression.
16+
///
17+
/// {
18+
/// use ::core::asserting::{ ... };
19+
///
20+
/// let mut __capture0 = Capture::new();
21+
/// ...
22+
/// ...
23+
/// ...
24+
///
25+
/// if !{
26+
/// ...
27+
/// ...
28+
/// ...
29+
/// } {
30+
/// panic!(
31+
/// "Assertion failed: ... \n With expansion: ...",
32+
/// __capture0,
33+
/// ...
34+
/// ...
35+
/// ...
36+
/// );
37+
/// }
38+
/// }
39+
pub(super) fn build(self, _cond_expr: P<Expr>, _panic_path: Path) -> P<Expr> {
40+
let Self { cx, span, .. } = self;
41+
let stmts = Vec::new();
42+
cx.expr_block(cx.block(span, stmts))
43+
}
44+
}

compiler/rustc_builtin_macros/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
//! This crate contains implementations of built-in macros and other code generating facilities
22
//! injecting code into the crate before it is lowered to HIR.
33
4+
#![allow(rustc::potential_query_instability)]
45
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
56
#![feature(array_windows)]
67
#![feature(box_patterns)]
78
#![feature(decl_macro)]
89
#![feature(is_sorted)]
9-
#![feature(nll)]
10+
#![feature(let_chains)]
1011
#![feature(let_else)]
12+
#![feature(nll)]
1113
#![feature(proc_macro_internals)]
1214
#![feature(proc_macro_quote)]
1315
#![recursion_limit = "256"]
14-
#![allow(rustc::potential_query_instability)]
1516

1617
extern crate proc_macro;
1718

compiler/rustc_expand/src/build.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ impl<'a> ExtCtxt<'a> {
160160
attrs: AttrVec::new(),
161161
tokens: None,
162162
});
163-
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
163+
self.stmt_local(local, sp)
164164
}
165165

166166
// Generates `let _: Type;`, which is usually used for type assertions.
@@ -174,6 +174,10 @@ impl<'a> ExtCtxt<'a> {
174174
attrs: AttrVec::new(),
175175
tokens: None,
176176
});
177+
self.stmt_local(local, span)
178+
}
179+
180+
pub fn stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt {
177181
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span }
178182
}
179183

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ declare_features! (
150150
(active, allow_internal_unstable, "1.0.0", None, None),
151151
/// Allows identifying the `compiler_builtins` crate.
152152
(active, compiler_builtins, "1.13.0", None, None),
153+
/// Outputs useful `assert!` messages
154+
(active, generic_assert, "1.63.0", None, None),
153155
/// Allows using the `rust-intrinsic`'s "ABI".
154156
(active, intrinsics, "1.0.0", None, None),
155157
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ symbols! {
733733
generator_state,
734734
generators,
735735
generic_arg_infer,
736+
generic_assert,
736737
generic_associated_types,
737738
generic_associated_types_extended,
738739
generic_const_exprs,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// compile-flags: --test
2+
// run-pass
3+
4+
// `generic_assert` is completely unimplemented and doesn't generate any logic, thus the
5+
// reason why this test currently passes
6+
#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
7+
8+
use std::fmt::{Debug, Formatter};
9+
10+
#[derive(Clone, Copy, PartialEq)]
11+
struct CopyDebug(i32);
12+
13+
impl Debug for CopyDebug {
14+
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
15+
f.write_str("With great power comes great electricity bills")
16+
}
17+
}
18+
19+
#[test]
20+
fn test() {
21+
let _copy_debug = CopyDebug(1);
22+
assert!(_copy_debug == CopyDebug(3));
23+
}
24+
25+
fn main() {
26+
}

0 commit comments

Comments
 (0)