Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
605c64a9
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
605c64a9
编写于
6月 15, 2022
作者:
C
Caio
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[RFC 2011] Minimal initial implementation
上级
389352c4
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
668 addition
and
41 deletion
+668
-41
compiler/rustc_builtin_macros/src/assert/context.rs
compiler/rustc_builtin_macros/src/assert/context.rs
+281
-26
compiler/rustc_builtin_macros/src/lib.rs
compiler/rustc_builtin_macros/src/lib.rs
+1
-0
compiler/rustc_span/src/symbol.rs
compiler/rustc_span/src/symbol.rs
+7
-0
src/test/ui/macros/assert-trailing-junk.rs
src/test/ui/macros/assert-trailing-junk.rs
+3
-0
src/test/ui/macros/assert-trailing-junk.with-generic-asset.stderr
.../ui/macros/assert-trailing-junk.with-generic-asset.stderr
+7
-7
src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr
.../macros/assert-trailing-junk.without-generic-asset.stderr
+54
-0
src/test/ui/macros/assert.rs
src/test/ui/macros/assert.rs
+3
-0
src/test/ui/macros/assert.with-generic-asset.stderr
src/test/ui/macros/assert.with-generic-asset.stderr
+4
-4
src/test/ui/macros/assert.without-generic-asset.stderr
src/test/ui/macros/assert.without-generic-asset.stderr
+28
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
...i/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
+143
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
...rfc-2011-nicer-assert-messages/all-not-available-cases.rs
+43
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
...rt-with-custom-errors-does-not-create-unnecessary-code.rs
+13
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
...sert-without-captures-does-not-create-unnecessary-code.rs
+14
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
...macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
+25
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
+9
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
...t/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
+29
-0
src/test/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
...2011-nicer-assert-messages/feature-gate-generic_assert.rs
+4
-4
未找到文件。
compiler/rustc_builtin_macros/src/assert/context.rs
浏览文件 @
605c64a9
use
rustc_ast
::{
ptr
::
P
,
Expr
,
Path
};
use
crate
::
assert
::
expr_if_not
;
use
rustc_ast
::{
attr
,
ptr
::
P
,
token
,
tokenstream
::{
DelimSpan
,
TokenStream
,
TokenTree
},
BorrowKind
,
Expr
,
ExprKind
,
ItemKind
,
MacArgs
,
MacCall
,
MacDelimiter
,
Mutability
,
Path
,
PathSegment
,
Stmt
,
UseTree
,
UseTreeKind
,
DUMMY_NODE_ID
,
};
use
rustc_ast_pretty
::
pprust
;
use
rustc_data_structures
::
fx
::
FxHashSet
;
use
rustc_expand
::
base
::
ExtCtxt
;
use
rustc_expand
::
base
::
ExtCtxt
;
use
rustc_span
::
Span
;
use
rustc_span
::{
symbol
::{
sym
,
Ident
,
Symbol
},
Span
,
};
pub
(
super
)
struct
Context
<
'cx
,
'a
>
{
pub
(
super
)
struct
Context
<
'cx
,
'a
>
{
// Top-level `let captureN = Capture::new()` statements
capture_decls
:
Vec
<
Capture
>
,
cx
:
&
'cx
ExtCtxt
<
'a
>
,
cx
:
&
'cx
ExtCtxt
<
'a
>
,
// Formatting string used for debugging
fmt_string
:
String
,
// Top-level `let __local_bindN = &expr` statements
local_bind_decls
:
Vec
<
Stmt
>
,
// Used to avoid capturing duplicated paths
//
// ```rust
// let a = 1i32;
// assert!(add(a, a) == 3);
// ```
paths
:
FxHashSet
<
Ident
>
,
span
:
Span
,
span
:
Span
,
}
}
impl
<
'cx
,
'a
>
Context
<
'cx
,
'a
>
{
impl
<
'cx
,
'a
>
Context
<
'cx
,
'a
>
{
pub
(
super
)
fn
new
(
cx
:
&
'cx
ExtCtxt
<
'a
>
,
span
:
Span
)
->
Self
{
pub
(
super
)
fn
new
(
cx
:
&
'cx
ExtCtxt
<
'a
>
,
span
:
Span
)
->
Self
{
Self
{
cx
,
span
}
Self
{
capture_decls
:
<
_
>
::
default
(),
cx
,
fmt_string
:
<
_
>
::
default
(),
local_bind_decls
:
<
_
>
::
default
(),
paths
:
<
_
>
::
default
(),
span
,
}
}
}
/// Builds the whole `assert!` expression.
/// Builds the whole `assert!` expression.
For example, `let elem = 1; assert!(elem == 1);` expands to:
///
///
/// ```rust
/// let elem = 1;
/// {
/// {
/// use ::core::asserting::{ ... };
/// #[allow(unused_imports)]
/// use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
/// let mut __capture0 = ::core::asserting::Capture::new();
/// let __local_bind0 = &elem;
/// if !(
/// *{
/// (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
/// __local_bind0
/// } == 1
/// ) {
/// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {}", __capture0)
/// }
/// }
/// ```
pub
(
super
)
fn
build
(
mut
self
,
mut
cond_expr
:
P
<
Expr
>
,
panic_path
:
Path
)
->
P
<
Expr
>
{
let
expr_str
=
pprust
::
expr_to_string
(
&
cond_expr
);
self
.manage_cond_expr
(
&
mut
cond_expr
);
let
initial_imports
=
self
.build_initial_imports
();
let
panic
=
self
.build_panic
(
&
expr_str
,
panic_path
);
let
Self
{
capture_decls
,
cx
,
local_bind_decls
,
span
,
..
}
=
self
;
let
mut
stmts
=
Vec
::
with_capacity
(
4
);
stmts
.push
(
initial_imports
);
stmts
.extend
(
capture_decls
.into_iter
()
.map
(|
c
|
c
.decl
));
stmts
.extend
(
local_bind_decls
);
stmts
.push
(
cx
.stmt_expr
(
expr_if_not
(
cx
,
span
,
cond_expr
,
panic
,
None
)));
cx
.expr_block
(
cx
.block
(
span
,
stmts
))
}
/// Initial **trait** imports
///
/// use ::core::asserting::{ ... };
fn
build_initial_imports
(
&
self
)
->
Stmt
{
let
nested_tree
=
|
this
:
&
Self
,
sym
|
{
(
UseTree
{
prefix
:
this
.cx
.path
(
this
.span
,
vec!
[
Ident
::
with_dummy_span
(
sym
)]),
kind
:
UseTreeKind
::
Simple
(
None
,
DUMMY_NODE_ID
,
DUMMY_NODE_ID
),
span
:
this
.span
,
},
DUMMY_NODE_ID
,
)
};
self
.cx
.stmt_item
(
self
.span
,
self
.cx
.item
(
self
.span
,
Ident
::
empty
(),
vec!
[
self
.cx
.attribute
(
attr
::
mk_list_item
(
Ident
::
new
(
sym
::
allow
,
self
.span
),
vec!
[
attr
::
mk_nested_word_item
(
Ident
::
new
(
sym
::
unused_imports
,
self
.span
))],
))],
ItemKind
::
Use
(
UseTree
{
prefix
:
self
.cx
.path
(
self
.span
,
self
.cx
.std_path
(
&
[
sym
::
asserting
])),
kind
:
UseTreeKind
::
Nested
(
vec!
[
nested_tree
(
self
,
sym
::
TryCaptureGeneric
),
nested_tree
(
self
,
sym
::
TryCapturePrintable
),
]),
span
:
self
.span
,
}),
),
)
}
/// The necessary custom `panic!(...)` expression.
///
/// panic!(
/// "Assertion failed: ... \n With expansion: ...",
/// __capture0,
/// ...
/// );
fn
build_panic
(
&
self
,
expr_str
:
&
str
,
panic_path
:
Path
)
->
P
<
Expr
>
{
let
escaped_expr_str
=
escape_to_fmt
(
expr_str
);
let
initial
=
[
TokenTree
::
token
(
token
::
Literal
(
token
::
Lit
{
kind
:
token
::
LitKind
::
Str
,
symbol
:
Symbol
::
intern
(
&
if
self
.fmt_string
.is_empty
()
{
format!
(
"Assertion failed: {escaped_expr_str}"
)
}
else
{
format!
(
"Assertion failed: {escaped_expr_str}
\n
With captures:
\n
{}"
,
&
self
.fmt_string
)
}),
suffix
:
None
,
}),
self
.span
,
),
TokenTree
::
token
(
token
::
Comma
,
self
.span
),
];
let
captures
=
self
.capture_decls
.iter
()
.flat_map
(|
cap
|
{
[
TokenTree
::
token
(
token
::
Ident
(
cap
.ident.name
,
false
),
cap
.ident.span
),
TokenTree
::
token
(
token
::
Comma
,
self
.span
),
]
});
self
.cx
.expr
(
self
.span
,
ExprKind
::
MacCall
(
MacCall
{
path
:
panic_path
,
args
:
P
(
MacArgs
::
Delimited
(
DelimSpan
::
from_single
(
self
.span
),
MacDelimiter
::
Parenthesis
,
initial
.into_iter
()
.chain
(
captures
)
.collect
::
<
TokenStream
>
(),
)),
prior_type_ascription
:
None
,
}),
)
}
/// Recursive function called until `cond_expr` and `fmt_str` are fully modified.
///
/// See [Self::manage_initial_capture] and [Self::manage_try_capture]
fn
manage_cond_expr
(
&
mut
self
,
expr
:
&
mut
P
<
Expr
>
)
{
match
(
*
expr
)
.kind
{
ExprKind
::
Binary
(
_
,
ref
mut
lhs
,
ref
mut
rhs
)
=>
{
self
.manage_cond_expr
(
lhs
);
self
.manage_cond_expr
(
rhs
);
}
ExprKind
::
Path
(
_
,
Path
{
ref
segments
,
..
})
if
let
&
[
ref
path_segment
]
=
&
segments
[
..
]
=>
{
let
path_ident
=
path_segment
.ident
;
self
.manage_initial_capture
(
expr
,
path_ident
);
}
_
=>
{}
}
}
/// Pushes the top-level declarations and modifies `expr` to try capturing variables.
///
///
/// let mut __capture0 = Capture::new();
/// `fmt_str`, the formatting string used for debugging, is constructed to show possible
/// ...
/// captured variables.
/// ...
fn
manage_initial_capture
(
&
mut
self
,
expr
:
&
mut
P
<
Expr
>
,
path_ident
:
Ident
)
{
/// ...
if
self
.paths
.contains
(
&
path_ident
)
{
return
;
}
else
{
self
.fmt_string
.push_str
(
" "
);
self
.fmt_string
.push_str
(
path_ident
.as_str
());
self
.fmt_string
.push_str
(
" = {:?}
\n
"
);
let
_
=
self
.paths
.insert
(
path_ident
);
}
let
curr_capture_idx
=
self
.capture_decls
.len
();
let
capture_string
=
format!
(
"__capture{curr_capture_idx}"
);
let
ident
=
Ident
::
new
(
Symbol
::
intern
(
&
capture_string
),
self
.span
);
let
init_std_path
=
self
.cx
.std_path
(
&
[
sym
::
asserting
,
sym
::
Capture
,
sym
::
new
]);
let
init
=
self
.cx
.expr_call
(
self
.span
,
self
.cx
.expr_path
(
self
.cx
.path
(
self
.span
,
init_std_path
)),
vec!
[],
);
let
capture
=
Capture
{
decl
:
self
.cx
.stmt_let
(
self
.span
,
true
,
ident
,
init
),
ident
};
self
.capture_decls
.push
(
capture
);
self
.manage_try_capture
(
ident
,
curr_capture_idx
,
expr
);
}
/// Tries to copy `__local_bindN` into `__captureN`.
///
///
/// if !{
/// *{
/// ...
/// (&Wrapper(__local_bindN)).try_capture(&mut __captureN);
/// ...
/// __local_bindN
/// ...
/// } {
/// panic!(
/// "Assertion failed: ... \n With expansion: ...",
/// __capture0,
/// ...
/// ...
/// ...
/// );
/// }
/// }
/// }
pub
(
super
)
fn
build
(
self
,
_
cond_expr
:
P
<
Expr
>
,
_
panic_path
:
Path
)
->
P
<
Expr
>
{
fn
manage_try_capture
(
&
mut
self
,
capture
:
Ident
,
curr_capture_idx
:
usize
,
expr
:
&
mut
P
<
Expr
>
)
{
let
Self
{
cx
,
span
,
..
}
=
self
;
let
local_bind_string
=
format!
(
"__local_bind{curr_capture_idx}"
);
let
stmts
=
Vec
::
new
();
let
local_bind
=
Ident
::
new
(
Symbol
::
intern
(
&
local_bind_string
),
self
.span
);
cx
.expr_block
(
cx
.block
(
span
,
stmts
))
self
.local_bind_decls
.push
(
self
.cx
.stmt_let
(
self
.span
,
false
,
local_bind
,
self
.cx
.expr_addr_of
(
self
.span
,
expr
.clone
()),
));
let
wrapper
=
self
.cx
.expr_call
(
self
.span
,
self
.cx
.expr_path
(
self
.cx
.path
(
self
.span
,
self
.cx
.std_path
(
&
[
sym
::
asserting
,
sym
::
Wrapper
])),
),
vec!
[
self
.cx
.expr_path
(
Path
::
from_ident
(
local_bind
))],
);
let
try_capture_call
=
self
.cx
.stmt_expr
(
expr_method_call
(
self
.cx
,
PathSegment
{
args
:
None
,
id
:
DUMMY_NODE_ID
,
ident
:
Ident
::
new
(
sym
::
try_capture
,
self
.span
),
},
vec!
[
expr_paren
(
self
.cx
,
self
.span
,
self
.cx
.expr_addr_of
(
self
.span
,
wrapper
)),
expr_addr_of_mut
(
self
.cx
,
self
.span
,
self
.cx
.expr_path
(
Path
::
from_ident
(
capture
)),
),
],
self
.span
,
))
.add_trailing_semicolon
();
let
local_bind_path
=
self
.cx
.expr_path
(
Path
::
from_ident
(
local_bind
));
let
ret
=
self
.cx
.stmt_expr
(
local_bind_path
);
let
block
=
self
.cx
.expr_block
(
self
.cx
.block
(
self
.span
,
vec!
[
try_capture_call
,
ret
]));
*
expr
=
self
.cx
.expr_deref
(
self
.span
,
block
);
}
}
/// Information about a captured element.
#[derive(Debug)]
struct
Capture
{
// Generated indexed `Capture` statement.
//
// `let __capture{} = Capture::new();`
decl
:
Stmt
,
// The name of the generated indexed `Capture` variable.
//
// `__capture{}`
ident
:
Ident
,
}
/// Escapes to use as a formatting string.
fn
escape_to_fmt
(
s
:
&
str
)
->
String
{
let
mut
rslt
=
String
::
with_capacity
(
s
.len
());
for
c
in
s
.chars
()
{
rslt
.extend
(
c
.escape_debug
());
match
c
{
'{'
|
'}'
=>
rslt
.push
(
c
),
_
=>
{}
}
}
}
rslt
}
fn
expr_addr_of_mut
(
cx
:
&
ExtCtxt
<
'_
>
,
sp
:
Span
,
e
:
P
<
Expr
>
)
->
P
<
Expr
>
{
cx
.expr
(
sp
,
ExprKind
::
AddrOf
(
BorrowKind
::
Ref
,
Mutability
::
Mut
,
e
))
}
fn
expr_method_call
(
cx
:
&
ExtCtxt
<
'_
>
,
path
:
PathSegment
,
args
:
Vec
<
P
<
Expr
>>
,
span
:
Span
,
)
->
P
<
Expr
>
{
cx
.expr
(
span
,
ExprKind
::
MethodCall
(
path
,
args
,
span
))
}
fn
expr_paren
(
cx
:
&
ExtCtxt
<
'_
>
,
sp
:
Span
,
e
:
P
<
Expr
>
)
->
P
<
Expr
>
{
cx
.expr
(
sp
,
ExprKind
::
Paren
(
e
))
}
}
compiler/rustc_builtin_macros/src/lib.rs
浏览文件 @
605c64a9
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
#![feature(array_windows)]
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
#![feature(is_sorted)]
#![feature(is_sorted)]
#![feature(let_chains)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(let_else)]
...
...
compiler/rustc_span/src/symbol.rs
浏览文件 @
605c64a9
...
@@ -157,6 +157,7 @@
...
@@ -157,6 +157,7 @@
C
,
C
,
CStr
,
CStr
,
CString
,
CString
,
Capture
,
Center
,
Center
,
Clone
,
Clone
,
Continue
,
Continue
,
...
@@ -267,6 +268,8 @@
...
@@ -267,6 +268,8 @@
ToOwned
,
ToOwned
,
ToString
,
ToString
,
Try
,
Try
,
TryCaptureGeneric
,
TryCapturePrintable
,
TryFrom
,
TryFrom
,
TryInto
,
TryInto
,
Ty
,
Ty
,
...
@@ -276,6 +279,7 @@
...
@@ -276,6 +279,7 @@
UnsafeArg
,
UnsafeArg
,
Vec
,
Vec
,
VecDeque
,
VecDeque
,
Wrapper
,
Yield
,
Yield
,
_
DECLS
,
_
DECLS
,
_
Self
,
_
Self
,
...
@@ -358,6 +362,7 @@
...
@@ -358,6 +362,7 @@
assert_receiver_is_total_eq
,
assert_receiver_is_total_eq
,
assert_uninit_valid
,
assert_uninit_valid
,
assert_zero_valid
,
assert_zero_valid
,
asserting
,
associated_const_equality
,
associated_const_equality
,
associated_consts
,
associated_consts
,
associated_type_bounds
,
associated_type_bounds
,
...
@@ -1437,6 +1442,7 @@
...
@@ -1437,6 +1442,7 @@
truncf32
,
truncf32
,
truncf64
,
truncf64
,
try_blocks
,
try_blocks
,
try_capture
,
try_from
,
try_from
,
try_into
,
try_into
,
try_trait_v2
,
try_trait_v2
,
...
@@ -1499,6 +1505,7 @@
...
@@ -1499,6 +1505,7 @@
unsized_tuple_coercion
,
unsized_tuple_coercion
,
unstable
,
unstable
,
untagged_unions
,
untagged_unions
,
unused_imports
,
unused_qualifications
,
unused_qualifications
,
unwind
,
unwind
,
unwind_attributes
,
unwind_attributes
,
...
...
src/test/ui/macros/assert-trailing-junk.rs
浏览文件 @
605c64a9
// revisions: with-generic-asset without-generic-asset
// [with-generic-asset] compile-flags: --cfg feature="generic_assert"
// Ensure assert macro does not ignore trailing garbage.
// Ensure assert macro does not ignore trailing garbage.
//
//
// See https://github.com/rust-lang/rust/issues/60024 for details.
// See https://github.com/rust-lang/rust/issues/60024 for details.
...
...
src/test/ui/macros/assert-trailing-junk.stderr
→
src/test/ui/macros/assert-trailing-junk.
with-generic-asset.
stderr
浏览文件 @
605c64a9
error: expected one of `,`, `.`, `?`, or an operator, found `some`
error: expected one of `,`, `.`, `?`, or an operator, found `some`
--> $DIR/assert-trailing-junk.rs:
6
:18
--> $DIR/assert-trailing-junk.rs:
9
:18
|
|
LL | assert!(true some extra junk, "whatever");
LL | assert!(true some extra junk, "whatever");
| ^^^^ expected one of `,`, `.`, `?`, or an operator
| ^^^^ expected one of `,`, `.`, `?`, or an operator
error: expected one of `,`, `.`, `?`, or an operator, found `some`
error: expected one of `,`, `.`, `?`, or an operator, found `some`
--> $DIR/assert-trailing-junk.rs:
9
:18
--> $DIR/assert-trailing-junk.rs:
12
:18
|
|
LL | assert!(true some extra junk);
LL | assert!(true some extra junk);
| ^^^^ expected one of `,`, `.`, `?`, or an operator
| ^^^^ expected one of `,`, `.`, `?`, or an operator
error: no rules expected the token `blah`
error: no rules expected the token `blah`
--> $DIR/assert-trailing-junk.rs:1
2
:30
--> $DIR/assert-trailing-junk.rs:1
5
:30
|
|
LL | assert!(true, "whatever" blah);
LL | assert!(true, "whatever" blah);
| -^^^^ no rules expected this token in macro call
| -^^^^ no rules expected this token in macro call
...
@@ -19,7 +19,7 @@ LL | assert!(true, "whatever" blah);
...
@@ -19,7 +19,7 @@ LL | assert!(true, "whatever" blah);
| help: missing comma here
| help: missing comma here
error: unexpected string literal
error: unexpected string literal
--> $DIR/assert-trailing-junk.rs:1
5
:18
--> $DIR/assert-trailing-junk.rs:1
8
:18
|
|
LL | assert!(true "whatever" blah);
LL | assert!(true "whatever" blah);
| -^^^^^^^^^^
| -^^^^^^^^^^
...
@@ -27,7 +27,7 @@ LL | assert!(true "whatever" blah);
...
@@ -27,7 +27,7 @@ LL | assert!(true "whatever" blah);
| help: try adding a comma
| help: try adding a comma
error: no rules expected the token `blah`
error: no rules expected the token `blah`
--> $DIR/assert-trailing-junk.rs:1
5
:29
--> $DIR/assert-trailing-junk.rs:1
8
:29
|
|
LL | assert!(true "whatever" blah);
LL | assert!(true "whatever" blah);
| -^^^^ no rules expected this token in macro call
| -^^^^ no rules expected this token in macro call
...
@@ -35,7 +35,7 @@ LL | assert!(true "whatever" blah);
...
@@ -35,7 +35,7 @@ LL | assert!(true "whatever" blah);
| help: missing comma here
| help: missing comma here
error: macro requires an expression as an argument
error: macro requires an expression as an argument
--> $DIR/assert-trailing-junk.rs:
19
:5
--> $DIR/assert-trailing-junk.rs:
22
:5
|
|
LL | assert!(true;);
LL | assert!(true;);
| ^^^^^^^^^^^^-^
| ^^^^^^^^^^^^-^
...
@@ -43,7 +43,7 @@ LL | assert!(true;);
...
@@ -43,7 +43,7 @@ LL | assert!(true;);
| help: try removing semicolon
| help: try removing semicolon
error: unexpected string literal
error: unexpected string literal
--> $DIR/assert-trailing-junk.rs:2
2
:27
--> $DIR/assert-trailing-junk.rs:2
5
:27
|
|
LL | assert!(false || true "error message");
LL | assert!(false || true "error message");
| -^^^^^^^^^^^^^^^
| -^^^^^^^^^^^^^^^
...
...
src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr
0 → 100644
浏览文件 @
605c64a9
error: expected one of `,`, `.`, `?`, or an operator, found `some`
--> $DIR/assert-trailing-junk.rs:9:18
|
LL | assert!(true some extra junk, "whatever");
| ^^^^ expected one of `,`, `.`, `?`, or an operator
error: expected one of `,`, `.`, `?`, or an operator, found `some`
--> $DIR/assert-trailing-junk.rs:12:18
|
LL | assert!(true some extra junk);
| ^^^^ expected one of `,`, `.`, `?`, or an operator
error: no rules expected the token `blah`
--> $DIR/assert-trailing-junk.rs:15:30
|
LL | assert!(true, "whatever" blah);
| -^^^^ no rules expected this token in macro call
| |
| help: missing comma here
error: unexpected string literal
--> $DIR/assert-trailing-junk.rs:18:18
|
LL | assert!(true "whatever" blah);
| -^^^^^^^^^^
| |
| help: try adding a comma
error: no rules expected the token `blah`
--> $DIR/assert-trailing-junk.rs:18:29
|
LL | assert!(true "whatever" blah);
| -^^^^ no rules expected this token in macro call
| |
| help: missing comma here
error: macro requires an expression as an argument
--> $DIR/assert-trailing-junk.rs:22:5
|
LL | assert!(true;);
| ^^^^^^^^^^^^-^
| |
| help: try removing semicolon
error: unexpected string literal
--> $DIR/assert-trailing-junk.rs:25:27
|
LL | assert!(false || true "error message");
| -^^^^^^^^^^^^^^^
| |
| help: try adding a comma
error: aborting due to 7 previous errors
src/test/ui/macros/assert.rs
浏览文件 @
605c64a9
// revisions: with-generic-asset without-generic-asset
// [with-generic-asset] compile-flags: --cfg feature="generic_assert"
fn
main
()
{
fn
main
()
{
assert
!
();
//~ ERROR requires a boolean expression
assert
!
();
//~ ERROR requires a boolean expression
assert
!
(
struct
);
//~ ERROR expected expression
assert
!
(
struct
);
//~ ERROR expected expression
...
...
src/test/ui/macros/assert.stderr
→
src/test/ui/macros/assert.
with-generic-asset.
stderr
浏览文件 @
605c64a9
error: macro requires a boolean expression as an argument
error: macro requires a boolean expression as an argument
--> $DIR/assert.rs:
2
:5
--> $DIR/assert.rs:
5
:5
|
|
LL | assert!();
LL | assert!();
| ^^^^^^^^^ boolean expression required
| ^^^^^^^^^ boolean expression required
error: expected expression, found keyword `struct`
error: expected expression, found keyword `struct`
--> $DIR/assert.rs:
3
:13
--> $DIR/assert.rs:
6
:13
|
|
LL | assert!(struct);
LL | assert!(struct);
| ^^^^^^ expected expression
| ^^^^^^ expected expression
error: macro requires a boolean expression as an argument
error: macro requires a boolean expression as an argument
--> $DIR/assert.rs:
4
:5
--> $DIR/assert.rs:
7
:5
|
|
LL | debug_assert!();
LL | debug_assert!();
| ^^^^^^^^^^^^^^^ boolean expression required
| ^^^^^^^^^^^^^^^ boolean expression required
...
@@ -19,7 +19,7 @@ LL | debug_assert!();
...
@@ -19,7 +19,7 @@ LL | debug_assert!();
= note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found keyword `struct`
error: expected expression, found keyword `struct`
--> $DIR/assert.rs:
5
:19
--> $DIR/assert.rs:
8
:19
|
|
LL | debug_assert!(struct);
LL | debug_assert!(struct);
| ^^^^^^ expected expression
| ^^^^^^ expected expression
...
...
src/test/ui/macros/assert.without-generic-asset.stderr
0 → 100644
浏览文件 @
605c64a9
error: macro requires a boolean expression as an argument
--> $DIR/assert.rs:5:5
|
LL | assert!();
| ^^^^^^^^^ boolean expression required
error: expected expression, found keyword `struct`
--> $DIR/assert.rs:6:13
|
LL | assert!(struct);
| ^^^^^^ expected expression
error: macro requires a boolean expression as an argument
--> $DIR/assert.rs:7:5
|
LL | debug_assert!();
| ^^^^^^^^^^^^^^^ boolean expression required
|
= note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found keyword `struct`
--> $DIR/assert.rs:8:19
|
LL | debug_assert!(struct);
| ^^^^^^ expected expression
error: aborting due to 4 previous errors
src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
0 → 100644
浏览文件 @
605c64a9
// edition:2021
// ignore-tidy-linelength
// only-x86_64
// run-pass
#![allow(path_statements,
unused_allocation)]
#![feature(box_syntax,
core_intrinsics,
generic_assert,
generic_assert_internals)]
macro_rules!
test
{
(
let
mut
$elem_ident:ident
=
$elem_expr:expr
;
[
$
(
$assert:tt
)
*
]
=>
$msg:literal
)
=>
{
{
#[allow(unused_assignments,
unused_mut,
unused_variables)]
let
rslt
=
std
::
panic
::
catch_unwind
(||
{
let
mut
$elem_ident
=
$elem_expr
;
assert!
(
$
(
$assert
)
*
);
});
let
err
=
rslt
.unwrap_err
();
if
let
Some
(
elem
)
=
err
.downcast_ref
::
<
String
>
()
{
assert_eq!
(
elem
,
&
$msg
);
}
else
if
let
Some
(
elem
)
=
err
.downcast_ref
::
<&
str
>
()
{
assert_eq!
(
elem
,
&
$msg
);
}
else
{
panic!
(
"assert!( ... ) should return a string"
);
}
}
}
}
macro_rules!
tests
{
(
let
mut
$elem_ident:ident
=
$elem_expr:expr
;
$
(
[
$
(
$elem_assert:tt
)
*
]
=>
$elem_msg:literal
)
+
)
=>
{
$
(
test!
(
let
mut
$elem_ident
=
$elem_expr
;
[
$
(
$elem_assert
)
*
]
=>
$elem_msg
);
)
+
}
}
const
FOO
:
Foo
=
Foo
{
bar
:
1
};
#[derive(Clone,
Copy,
Debug,
PartialEq)]
struct
Foo
{
bar
:
i32
}
fn
main
()
{
// ***** Allowed *****
tests!
(
let
mut
elem
=
1i32
;
// binary
[
elem
+
1
==
3
]
=>
"Assertion failed: elem + 1 == 3
\n
With captures:
\n
elem = 1
\n
"
);
// ***** Disallowed *****
tests!
(
let
mut
elem
=
1i32
;
// assign
[
{
let
local
=
elem
;
local
}
==
3
]
=>
"Assertion failed: { let local = elem; local } == 3"
// assign op
[
{
elem
+=
1
;
elem
}
==
3
]
=>
"Assertion failed: { elem += 1; elem } == 3"
// async
[
{
let
_
=
async
{
elem
};
elem
}
==
3
]
=>
"Assertion failed: { let _ = async { elem }; elem } == 3"
// await
// block
[
{
elem
}
==
3
]
=>
"Assertion failed: { elem } == 3"
// box
[
box
elem
==
box
3
]
=>
"Assertion failed: box elem == box 3"
// break
[
loop
{
break
elem
;
}
==
3
]
=>
"Assertion failed: loop { break elem; } == 3"
// closure
[(||
elem
)()
==
3
]
=>
"Assertion failed: (|| elem)() == 3"
// const block
// continue
// err
// field
[
FOO
.bar
==
3
]
=>
"Assertion failed: FOO.bar == 3"
// for loop
[
{
for
_
in
0
..
elem
{
elem
;
}
elem
}
==
3
]
=>
"Assertion failed: { for _ in 0..elem { elem; } elem } == 3"
// if
[
if
true
{
elem
}
else
{
elem
}
==
3
]
=>
"Assertion failed: if true { elem } else { elem } == 3"
// inline asm
// let
[
if
let
true
=
true
{
elem
}
else
{
elem
}
==
3
]
=>
"Assertion failed: if let true = true { elem } else { elem } == 3"
// lit
// loop
[
loop
{
elem
;
break
elem
;
}
==
3
]
=>
"Assertion failed: loop { elem; break elem; } == 3"
// mac call
// match
[
match
elem
{
_
=>
elem
}
==
3
]
=>
"Assertion failed: match elem { _ => elem, } == 3"
// ret
[
(||
{
return
elem
;
})()
==
3
]
=>
"Assertion failed: (|| { return elem; })() == 3"
// try
[
(||
{
Some
(
Some
(
elem
)
?
)
})()
==
Some
(
3
)
]
=>
"Assertion failed: (|| { Some(Some(elem)?) })() == Some(3)"
// try block
// underscore
// while
[
{
while
false
{
elem
;
break
;
}
elem
}
==
3
]
=>
"Assertion failed: { while false { elem; break; } elem } == 3"
// yeet
// yield
);
}
src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
0 → 100644
浏览文件 @
605c64a9
// aux-build:common.rs
// ignore-tidy-linelength
// only-x86_64
// run-pass
#![feature(core_intrinsics,
generic_assert,
generic_assert_internals)]
extern
crate
common
;
#[derive(Clone,
Copy,
PartialEq)]
struct
CopyNoDebug
(
i32
);
#[derive(Debug,
PartialEq)]
struct
NoCopyDebug
(
i32
);
#[derive(PartialEq)]
struct
NoCopyNoDebug
(
i32
);
fn
main
()
{
// Has Copy but does not have Debug
common
::
test!
(
let
mut
copy_no_debug
=
CopyNoDebug
(
1
);
[
copy_no_debug
==
CopyNoDebug
(
3
)
]
=>
"Assertion failed: copy_no_debug == CopyNoDebug(3)
\n
With captures:
\n
copy_no_debug = N/A
\n
"
);
// Does not have Copy but has Debug
common
::
test!
(
let
mut
no_copy_debug
=
NoCopyDebug
(
1
);
[
no_copy_debug
==
NoCopyDebug
(
3
)
]
=>
"Assertion failed: no_copy_debug == NoCopyDebug(3)
\n
With captures:
\n
no_copy_debug = N/A
\n
"
);
// Does not have Copy and does not have Debug
common
::
test!
(
let
mut
no_copy_no_debug
=
NoCopyNoDebug
(
1
);
[
no_copy_no_debug
==
NoCopyNoDebug
(
3
)
]
=>
"Assertion failed: no_copy_no_debug == NoCopyNoDebug(3)
\n
With captures:
\n
no_copy_no_debug = N/A
\n
"
);
// Unevaluated (Expression short-circuited)
common
::
test!
(
let
mut
elem
=
true
;
[
false
&&
elem
]
=>
"Assertion failed: false && elem
\n
With captures:
\n
elem = N/A
\n
"
);
}
src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
0 → 100644
浏览文件 @
605c64a9
// compile-flags: --test
// run-pass
#![feature(core_intrinsics,
generic_assert,
generic_assert_internals)]
#[should_panic(expected
=
"Custom user message"
)]
#[test]
fn
test
()
{
assert
!
(
1
==
3
,
"Custom user message"
);
}
fn
main
()
{
}
src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
0 → 100644
浏览文件 @
605c64a9
// aux-build:common.rs
// only-x86_64
// run-pass
#![feature(core_intrinsics,
generic_assert,
generic_assert_internals)]
extern
crate
common
;
fn
main
()
{
common
::
test!
(
let
mut
_
nothing
=
();
[
1
==
3
]
=>
"Assertion failed: 1 == 3"
);
}
src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
0 → 100644
浏览文件 @
605c64a9
#[macro_export]
macro_rules!
test
{
(
let
mut
$elem_ident:ident
=
$elem_expr:expr
;
[
$
(
$assert:tt
)
*
]
=>
$msg:literal
)
=>
{
{
#[allow(unused_assignments,
unused_mut,
unused_variables)]
let
rslt
=
std
::
panic
::
catch_unwind
(||
{
let
mut
$elem_ident
=
$elem_expr
;
assert!
(
$
(
$assert
)
*
);
});
let
err
=
rslt
.unwrap_err
();
if
let
Some
(
elem
)
=
err
.downcast_ref
::
<
String
>
()
{
assert_eq!
(
elem
,
&
$msg
);
}
else
if
let
Some
(
elem
)
=
err
.downcast_ref
::
<&
str
>
()
{
assert_eq!
(
elem
,
&
$msg
);
}
else
{
panic!
(
"assert!( ... ) should return a string"
);
}
}
}
}
src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
0 → 100644
浏览文件 @
605c64a9
// check-pass
// compile-flags: -Z unpretty=expanded
#![feature(core_intrinsics,
generic_assert,
generic_assert_internals)]
fn
main
()
{
let
elem
=
1i32
;
assert
!
(
elem
==
1
);
}
src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
0 → 100644
浏览文件 @
605c64a9
#![feature(prelude_import)]
#![no_std]
// check-pass
// compile-flags: -Z unpretty=expanded
#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
fn main() {
let elem = 1i32;
{
#[allow(unused_imports)]
use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
let mut __capture0 = ::core::asserting::Capture::new();
let __local_bind0 = &elem;
if !(*{
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
__local_bind0
} == 1) {
{
::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ",
"\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
}
}
};
}
src/test/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
浏览文件 @
605c64a9
// compile-flags: --test
// compile-flags: --test
// ignore-tidy-linelength
// run-pass
// run-pass
// `generic_assert` is completely unimplemented and doesn't generate any logic, thus the
// reason why this test currently passes
#![feature(core_intrinsics,
generic_assert,
generic_assert_internals)]
#![feature(core_intrinsics,
generic_assert,
generic_assert_internals)]
use
std
::
fmt
::{
Debug
,
Formatter
};
use
std
::
fmt
::{
Debug
,
Formatter
};
...
@@ -16,10 +15,11 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
...
@@ -16,10 +15,11 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
}
}
}
}
#[should_panic(expected
=
"Assertion failed: copy_debug == CopyDebug(3)
\n
With captures:
\n
copy_debug = With great power comes great electricity bills
\n
"
)]
#[test]
#[test]
fn
test
()
{
fn
test
()
{
let
_
copy_debug
=
CopyDebug
(
1
);
let
copy_debug
=
CopyDebug
(
1
);
assert
!
(
_
copy_debug
==
CopyDebug
(
3
));
assert
!
(
copy_debug
==
CopyDebug
(
3
));
}
}
fn
main
()
{
fn
main
()
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录