Skip to content

Commit

Permalink
Accept T in assert! where <T as Not<Output = bool> in <=2021 ed…
Browse files Browse the repository at this point in the history
…itions
  • Loading branch information
estebank committed Mar 18, 2024
1 parent 0d358fd commit 07a5b21
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 40 deletions.
76 changes: 43 additions & 33 deletions compiler/rustc_builtin_macros/src/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_parse::parser::Parser;
use rustc_span::edition::Edition;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use thin_vec::thin_vec;
Expand Down Expand Up @@ -172,45 +173,54 @@ fn expand_cond(cx: &ExtCtxt<'_>, parser: Parser<'_>, cond_expr: P<Expr>) -> P<Ex
// talk about traits, we'll just state the appropriate type error.
// `let assert_macro: bool = $expr;`
let ident = Ident::new(sym::assert_macro, DUMMY_SP);
let local = P(ast::Local {
ty: Some(P(ast::Ty {
kind: ast::TyKind::Path(None, ast::Path::from_ident(Ident::new(sym::bool, DUMMY_SP))),
id: ast::DUMMY_NODE_ID,
span: DUMMY_SP,
tokens: None,
})),
pat: parser.mk_pat_ident(DUMMY_SP, ast::BindingAnnotation::NONE, ident),
kind: ast::LocalKind::Init(cond_expr),
id: ast::DUMMY_NODE_ID,
span,
colon_sp: None,
attrs: Default::default(),
tokens: None,
});
// `{ let assert_macro: bool = $expr; assert_macro }`
parser.mk_expr(
span,
ast::ExprKind::Block(
parser.mk_block(
thin_vec![
parser.mk_stmt(span, ast::StmtKind::Let(local)),
parser.mk_stmt(
span,
ast::StmtKind::Expr(parser.mk_expr(
span,
ast::ExprKind::Path(None, ast::Path::from_ident(ident))
)),
),
],
ast::BlockCheckMode::Default,
span,

let expr = if use_assert_2024(span) {
// `{ let assert_macro: bool = $expr; assert_macro }`
cond_expr
} else {
// In <=2021, we allow anything that can be negated to `bool`, not just `bool`s. We use the
// "double not" trick to coerce the expression to `bool`. We still assign it to a new `bool`
// binding so that in the case of a type that implements `Not` but doesn't return `bool`,
// like `i32`, we still point at the condition and not at the whole macro.
// `{ let assert_macro: bool = !!$expr; assert_macro }`
let not = |expr| parser.mk_expr(span, ast::ExprKind::Unary(ast::UnOp::Not, expr));
not(not(cond_expr))
};
let block = thin_vec![
cx.stmt_let_ty(
DUMMY_SP,
false,
ident,
Some(cx.ty_ident(span, Ident::new(sym::bool, DUMMY_SP))),
expr,
),
parser.mk_stmt(
span,
ast::StmtKind::Expr(
parser.mk_expr(span, ast::ExprKind::Path(None, ast::Path::from_ident(ident)))
),
None,
),
];
parser.mk_expr(
span,
ast::ExprKind::Block(parser.mk_block(block, ast::BlockCheckMode::Default, span), None),
)
}

fn parse_custom_message(parser: &mut Parser<'_>) -> Option<TokenStream> {
let ts = parser.parse_tokens();
if !ts.is_empty() { Some(ts) } else { None }
}

pub fn use_assert_2024(mut span: Span) -> bool {
// To determine the edition, we check the first span up the expansion
// stack that isn't internal.
loop {
let expn = span.ctxt().outer_expn_data();
if let Some(_features) = expn.allow_internal_unstable {
span = expn.call_site;
continue;
}
break expn.edition >= Edition::Edition2024;
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
match (self.tcx.parent_hir_node(expr.hir_id), error) {
(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. }), _)
if init.hir_id == expr.hir_id && !ty.span.is_dummy() =>
if init.hir_id == expr.hir_id && !ty.span.source_equal(init.span) =>
{
// Point at `let` assignment type.
err.span_label(ty.span, "expected due to this");
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/codemap_tests/issue-28308.edition2021.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0600]: cannot apply unary operator `!` to type `&'static str`
--> $DIR/issue-28308.rs:6:13
|
LL | assert!("foo");
| ^^^^^ cannot apply unary operator `!`
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0600`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/issue-28308.rs:2:13
--> $DIR/issue-28308.rs:6:13
|
LL | assert!("foo");
| ^^^^^ expected `bool`, found `&str`
Expand Down
7 changes: 6 additions & 1 deletion tests/ui/codemap_tests/issue-28308.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
//@revisions: edition2024 edition2021
//@[edition2024] edition:2024
//@[edition2024] compile-flags: -Z unstable-options
//@[edition2021] edition:2021
fn main() {
assert!("foo");
//~^ ERROR mismatched types
//[edition2024]~^ ERROR mismatched types
//[edition2021]~^^ ERROR cannot apply unary operator `!` to type `&'static str`
}
2 changes: 1 addition & 1 deletion tests/ui/issues/issue-14091-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ fn main() {
let x = BytePos(1);

assert!(x, x);
//~^ ERROR mismatched types
//~^ ERROR cannot apply unary operator `!` to type `BytePos`
}
15 changes: 12 additions & 3 deletions tests/ui/issues/issue-14091-2.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
error[E0308]: mismatched types
error[E0600]: cannot apply unary operator `!` to type `BytePos`
--> $DIR/issue-14091-2.rs:15:13
|
LL | assert!(x, x);
| ^ expected `bool`, found `BytePos`
| ^ cannot apply unary operator `!`
|
note: an implementation of `Not` might be missing for `BytePos`
--> $DIR/issue-14091-2.rs:6:1
|
LL | pub struct BytePos(pub u32);
| ^^^^^^^^^^^^^^^^^^ must implement `Not`
note: the trait `Not` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0600`.
2 changes: 2 additions & 0 deletions tests/ui/issues/issue-14091.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ error[E0308]: mismatched types
|
LL | assert!(1,1);
| ^ expected `bool`, found integer
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

Expand Down

0 comments on commit 07a5b21

Please sign in to comment.