Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-04-23 05:01:15 +00:00
commit f356f2f203
83 changed files with 852 additions and 270 deletions

View file

@ -217,14 +217,12 @@ mod llvm_enzyme {
ast::StmtKind::Item(iitem) => extract_item_info(iitem),
_ => None,
},
Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => {
match &assoc_item.kind {
ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
Some((assoc_item.vis.clone(), sig.clone(), ident.clone()))
}
_ => None,
Annotatable::AssocItem(assoc_item, Impl { .. }) => match &assoc_item.kind {
ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
Some((assoc_item.vis.clone(), sig.clone(), ident.clone()))
}
}
_ => None,
},
_ => None,
}) else {
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
@ -365,7 +363,7 @@ mod llvm_enzyme {
}
Annotatable::Item(iitem.clone())
}
Annotatable::AssocItem(ref mut assoc_item, i @ Impl { of_trait: false }) => {
Annotatable::AssocItem(ref mut assoc_item, i @ Impl { .. }) => {
if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) {
assoc_item.attrs.push(attr);
}

View file

@ -872,8 +872,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// # Function pointers
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
if self.get_fn_alloc(id).is_some() {
return AllocInfo::new(Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not);
if let Some(fn_val) = self.get_fn_alloc(id) {
let align = match fn_val {
FnVal::Instance(instance) => {
// Function alignment can be set globally with the `-Zmin-function-alignment=<n>` flag;
// the alignment from a `#[repr(align(<n>))]` is used if it specifies a higher alignment.
let fn_align = self.tcx.codegen_fn_attrs(instance.def_id()).alignment;
let global_align = self.tcx.sess.opts.unstable_opts.min_function_alignment;
Ord::max(global_align, fn_align).unwrap_or(Align::ONE)
}
// Machine-specific extra functions currently do not support alignment restrictions.
FnVal::Other(_) => Align::ONE,
};
return AllocInfo::new(Size::ZERO, align, AllocKind::Function, Mutability::Not);
}
// # Global allocations

View file

@ -3289,8 +3289,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.multipart_suggestion(
format!("{val} is a raw pointer; try dereferencing it"),
vec![
(base.span.shrink_to_lo(), "(*".to_string()),
(base.span.shrink_to_hi(), ")".to_string()),
(base.span.shrink_to_lo(), "(*".into()),
(base.span.between(field.span), format!(").")),
],
Applicability::MaybeIncorrect,
);

View file

@ -246,9 +246,9 @@ parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$tok
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
parse_expr_rarrow_call = `->` used for field access or method call
parse_expr_rarrow_call = `->` is not valid syntax for field accesses and method calls
.suggestion = try using `.` instead
.help = the `.` operator will dereference the value if needed
.help = the `.` operator will automatically dereference the value, except if the value is a raw pointer
parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
.label = dash-separated idents are not valid

View file

@ -26,6 +26,7 @@ use rustc_macros::Subdiagnostic;
use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error};
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_span::edition::Edition;
use rustc_span::source_map::{self, Spanned};
use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Symbol, kw, sym};
use thin_vec::{ThinVec, thin_vec};
@ -2145,6 +2146,17 @@ impl<'a> Parser<'a> {
/// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
/// `Lit::from_token` (excluding unary negation).
fn eat_token_lit(&mut self) -> Option<token::Lit> {
let check_expr = |expr: P<Expr>| {
if let ast::ExprKind::Lit(token_lit) = expr.kind {
Some(token_lit)
} else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
&& let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
{
None
} else {
panic!("unexpected reparsed expr/literal: {:?}", expr.kind);
}
};
match self.token.uninterpolate().kind {
token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => {
self.bump();
@ -2158,10 +2170,7 @@ impl<'a> Parser<'a> {
let lit = self
.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
.expect("metavar seq literal");
let ast::ExprKind::Lit(token_lit) = lit.kind else {
panic!("didn't reparse a literal");
};
Some(token_lit)
check_expr(lit)
}
token::OpenInvisible(InvisibleOrigin::MetaVar(
mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. },
@ -2169,15 +2178,7 @@ impl<'a> Parser<'a> {
let expr = self
.eat_metavar_seq(mv_kind, |this| this.parse_expr())
.expect("metavar seq expr");
if let ast::ExprKind::Lit(token_lit) = expr.kind {
Some(token_lit)
} else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
&& let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
{
None
} else {
panic!("unexpected reparsed expr: {:?}", expr.kind);
}
check_expr(expr)
}
_ => None,
}
@ -2602,7 +2603,10 @@ impl<'a> Parser<'a> {
/// Parses an `if` expression (`if` token already eaten).
fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let cond = self.parse_expr_cond()?;
// Scoping code checks the top level edition of the `if`; let's match it here.
// The `CondChecker` also checks the edition of the `let` itself, just to make sure.
let let_chains_policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() };
let cond = self.parse_expr_cond(let_chains_policy)?;
self.parse_if_after_cond(lo, cond)
}
@ -2711,18 +2715,17 @@ impl<'a> Parser<'a> {
}
/// Parses the condition of a `if` or `while` expression.
///
/// The specified `edition` in `let_chains_policy` should be that of the whole `if` construct,
/// i.e. the same span we use to later decide whether the drop behaviour should be that of
/// edition `..=2021` or that of `2024..`.
// Public because it is used in rustfmt forks such as https://github.com/tucant/rustfmt/blob/30c83df9e1db10007bdd16dafce8a86b404329b2/src/parse/macros/html.rs#L57 for custom if expressions.
pub fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
pub fn parse_expr_cond(&mut self, let_chains_policy: LetChainsPolicy) -> PResult<'a, P<Expr>> {
let attrs = self.parse_outer_attributes()?;
let (mut cond, _) =
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?;
CondChecker::new(self).visit_expr(&mut cond);
if let ExprKind::Let(_, _, _, Recovered::No) = cond.kind {
// Remove the last feature gating of a `let` expression since it's stable.
self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
}
CondChecker::new(self, let_chains_policy).visit_expr(&mut cond);
Ok(cond)
}
@ -3017,7 +3020,8 @@ impl<'a> Parser<'a> {
/// Parses a `while` or `while let` expression (`while` token already eaten).
fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
let cond = self.parse_expr_cond().map_err(|mut err| {
let policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() };
let cond = self.parse_expr_cond(policy).map_err(|mut err| {
err.span_label(lo, "while parsing the condition of this `while` expression");
err
})?;
@ -3401,17 +3405,17 @@ impl<'a> Parser<'a> {
}
fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<P<Expr>>> {
// Used to check the `let_chains` and `if_let_guard` features mostly by scanning
// Used to check the `if_let_guard` feature mostly by scanning
// `&&` tokens.
fn check_let_expr(expr: &Expr) -> (bool, bool) {
fn has_let_expr(expr: &Expr) -> bool {
match &expr.kind {
ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => {
let lhs_rslt = check_let_expr(lhs);
let rhs_rslt = check_let_expr(rhs);
(lhs_rslt.0 || rhs_rslt.0, false)
let lhs_rslt = has_let_expr(lhs);
let rhs_rslt = has_let_expr(rhs);
lhs_rslt || rhs_rslt
}
ExprKind::Let(..) => (true, true),
_ => (false, true),
ExprKind::Let(..) => true,
_ => false,
}
}
if !self.eat_keyword(exp!(If)) {
@ -3422,14 +3426,9 @@ impl<'a> Parser<'a> {
let if_span = self.prev_token.span;
let mut cond = self.parse_match_guard_condition()?;
CondChecker::new(self).visit_expr(&mut cond);
CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond);
if has_let_expr {
if does_not_have_bin_op {
// Remove the last feature gating of a `let` expression since it's stable.
self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
}
if has_let_expr(&cond) {
let span = if_span.to(cond.span);
self.psess.gated_spans.gate(sym::if_let_guard, span);
}
@ -3456,7 +3455,7 @@ impl<'a> Parser<'a> {
unreachable!()
};
self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
CondChecker::new(self).visit_expr(&mut cond);
CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
let right = self.prev_token.span;
self.dcx().emit_err(errors::ParenthesesInMatchPat {
span: vec![left, right],
@ -4027,7 +4026,14 @@ pub(crate) enum ForbiddenLetReason {
NotSupportedParentheses(#[primary_span] Span),
}
/// Visitor to check for invalid/unstable use of `ExprKind::Let` that can't
/// Whether let chains are allowed on all editions, or it's edition dependent (allowed only on
/// 2024 and later). In case of edition dependence, specify the currently present edition.
pub enum LetChainsPolicy {
AlwaysAllowed,
EditionDependent { current_edition: Edition },
}
/// Visitor to check for invalid use of `ExprKind::Let` that can't
/// easily be caught in parsing. For example:
///
/// ```rust,ignore (example)
@ -4038,19 +4044,29 @@ pub(crate) enum ForbiddenLetReason {
/// ```
struct CondChecker<'a> {
parser: &'a Parser<'a>,
let_chains_policy: LetChainsPolicy,
depth: u32,
forbid_let_reason: Option<ForbiddenLetReason>,
missing_let: Option<errors::MaybeMissingLet>,
comparison: Option<errors::MaybeComparison>,
}
impl<'a> CondChecker<'a> {
fn new(parser: &'a Parser<'a>) -> Self {
CondChecker { parser, forbid_let_reason: None, missing_let: None, comparison: None }
fn new(parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy) -> Self {
CondChecker {
parser,
forbid_let_reason: None,
missing_let: None,
comparison: None,
let_chains_policy,
depth: 0,
}
}
}
impl MutVisitor for CondChecker<'_> {
fn visit_expr(&mut self, e: &mut P<Expr>) {
self.depth += 1;
use ForbiddenLetReason::*;
let span = e.span;
@ -4065,8 +4081,16 @@ impl MutVisitor for CondChecker<'_> {
comparison: self.comparison,
},
));
} else {
self.parser.psess.gated_spans.gate(sym::let_chains, span);
} else if self.depth > 1 {
// Top level `let` is always allowed; only gate chains
match self.let_chains_policy {
LetChainsPolicy::AlwaysAllowed => (),
LetChainsPolicy::EditionDependent { current_edition } => {
if !current_edition.at_least_rust_2024() || !span.at_least_rust_2024() {
self.parser.psess.gated_spans.gate(sym::let_chains, span);
}
}
}
}
}
ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => {
@ -4168,5 +4192,6 @@ impl MutVisitor for CondChecker<'_> {
// These would forbid any let expressions they contain already.
}
}
self.depth -= 1;
}
}

View file

@ -145,6 +145,9 @@ impl f128 {
pub const RADIX: u32 = 2;
/// Number of significant digits in base 2.
///
/// Note that the size of the mantissa in the bitwise representation is one
/// smaller than this since the leading 1 is not stored explicitly.
#[unstable(feature = "f128", issue = "116909")]
pub const MANTISSA_DIGITS: u32 = 113;

View file

@ -140,6 +140,9 @@ impl f16 {
pub const RADIX: u32 = 2;
/// Number of significant digits in base 2.
///
/// Note that the size of the mantissa in the bitwise representation is one
/// smaller than this since the leading 1 is not stored explicitly.
#[unstable(feature = "f16", issue = "116909")]
pub const MANTISSA_DIGITS: u32 = 11;

View file

@ -390,6 +390,9 @@ impl f32 {
pub const RADIX: u32 = 2;
/// Number of significant digits in base 2.
///
/// Note that the size of the mantissa in the bitwise representation is one
/// smaller than this since the leading 1 is not stored explicitly.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MANTISSA_DIGITS: u32 = 24;

View file

@ -390,6 +390,9 @@ impl f64 {
pub const RADIX: u32 = 2;
/// Number of significant digits in base 2.
///
/// Note that the size of the mantissa in the bitwise representation is one
/// smaller than this since the leading 1 is not stored explicitly.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MANTISSA_DIGITS: u32 = 53;
/// Approximate number of significant digits in base 10.

View file

@ -415,6 +415,7 @@ impl Command {
all(target_os = "linux", target_env = "musl"),
target_os = "nto",
target_vendor = "apple",
target_os = "cygwin",
)))]
fn posix_spawn(
&mut self,
@ -433,6 +434,7 @@ impl Command {
all(target_os = "linux", target_env = "musl"),
target_os = "nto",
target_vendor = "apple",
target_os = "cygwin",
))]
fn posix_spawn(
&mut self,
@ -584,7 +586,7 @@ impl Command {
/// Some platforms can set a new working directory for a spawned process in the
/// `posix_spawn` path. This function looks up the function pointer for adding
/// such an action to a `posix_spawn_file_actions_t` struct.
#[cfg(not(all(target_os = "linux", target_env = "musl")))]
#[cfg(not(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")))]
fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
use crate::sys::weak::weak;
@ -618,7 +620,9 @@ impl Command {
/// Weak symbol lookup doesn't work with statically linked libcs, so in cases
/// where static linking is possible we need to either check for the presence
/// of the symbol at compile time or know about it upfront.
#[cfg(all(target_os = "linux", target_env = "musl"))]
///
/// Cygwin doesn't support weak symbol, so just link it.
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin"))]
fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
// Our minimum required musl supports this function, so we can just use it.
Some(libc::posix_spawn_file_actions_addchdir_np)

View file

@ -112,6 +112,8 @@ fn test_nan() {
assert!(!nan.is_sign_negative());
assert!(!nan.is_normal());
assert_eq!(Fp::Nan, nan.classify());
// Ensure the quiet bit is set.
assert!(nan.to_bits() & (1 << (f128::MANTISSA_DIGITS - 2)) != 0);
}
#[test]

View file

@ -95,6 +95,8 @@ fn test_nan() {
assert!(!nan.is_sign_negative());
assert!(!nan.is_normal());
assert_eq!(Fp::Nan, nan.classify());
// Ensure the quiet bit is set.
assert!(nan.to_bits() & (1 << (f16::MANTISSA_DIGITS - 2)) != 0);
}
#[test]

View file

@ -72,6 +72,8 @@ fn test_nan() {
assert!(nan.is_sign_positive());
assert!(!nan.is_sign_negative());
assert_eq!(Fp::Nan, nan.classify());
// Ensure the quiet bit is set.
assert!(nan.to_bits() & (1 << (f32::MANTISSA_DIGITS - 2)) != 0);
}
#[test]

View file

@ -60,6 +60,8 @@ fn test_nan() {
assert!(nan.is_sign_positive());
assert!(!nan.is_sign_negative());
assert_eq!(Fp::Nan, nan.classify());
// Ensure the quiet bit is set.
assert!(nan.to_bits() & (1 << (f64::MANTISSA_DIGITS - 2)) != 0);
}
#[test]

@ -1 +1 @@
Subproject commit 0c10c30cc54736c5c194ce98c50e2de84eeb6e79
Subproject commit c76a20f0d987145dcedf05c5c073ce8d91f2e82a

@ -1 +1 @@
Subproject commit 3340922df189bddcbaad17dc3927d51a76bcd5ed
Subproject commit 3bf3402aea982b876eb56c87da17b0685c6461d5

View file

@ -57,9 +57,11 @@ pub(crate) fn run_tests(config: &Config, tests: Vec<CollectedTest>) -> bool {
}
let completion = deadline_queue
.read_channel_while_checking_deadlines(&completion_rx, |_id, test| {
listener.test_timed_out(test);
})
.read_channel_while_checking_deadlines(
&completion_rx,
|id| running_tests.contains_key(&id),
|_id, test| listener.test_timed_out(test),
)
.expect("receive channel should never be closed early");
let RunningTest { test, join_handle } = running_tests.remove(&completion.id).unwrap();

View file

@ -21,16 +21,26 @@ impl<'a> DeadlineQueue<'a> {
Self { queue: VecDeque::with_capacity(capacity) }
}
/// All calls to [`Instant::now`] go through this wrapper method.
/// This makes it easier to find all places that read the current time.
fn now(&self) -> Instant {
Instant::now()
}
pub(crate) fn push(&mut self, id: TestId, test: &'a CollectedTest) {
let deadline = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
let deadline = self.now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
if let Some(back) = self.queue.back() {
assert!(back.deadline <= deadline);
}
self.queue.push_back(DeadlineEntry { id, test, deadline });
}
/// Equivalent to `rx.read()`, except that if any test exceeds its deadline
/// Equivalent to `rx.recv()`, except that if a test exceeds its deadline
/// during the wait, the given callback will also be called for that test.
pub(crate) fn read_channel_while_checking_deadlines<T>(
&mut self,
rx: &mpsc::Receiver<T>,
is_running: impl Fn(TestId) -> bool,
mut on_deadline_passed: impl FnMut(TestId, &CollectedTest),
) -> Result<T, RecvError> {
loop {
@ -39,18 +49,18 @@ impl<'a> DeadlineQueue<'a> {
// deadline, so do a normal receive.
return rx.recv();
};
let wait_duration = next_deadline.saturating_duration_since(Instant::now());
let next_deadline_timeout = next_deadline.saturating_duration_since(self.now());
let recv_result = rx.recv_timeout(next_deadline_timeout);
// Process deadlines after every receive attempt, regardless of
// outcome, so that we don't build up an unbounded backlog of stale
// entries due to a constant stream of tests finishing.
self.for_each_entry_past_deadline(&is_running, &mut on_deadline_passed);
let recv_result = rx.recv_timeout(wait_duration);
match recv_result {
Ok(value) => return Ok(value),
Err(RecvTimeoutError::Timeout) => {
// Notify the callback of tests that have exceeded their
// deadline, then loop and do annother channel read.
for DeadlineEntry { id, test, .. } in self.remove_tests_past_deadline() {
on_deadline_passed(id, test);
}
}
// Deadlines have already been processed, so loop and do another receive.
Err(RecvTimeoutError::Timeout) => {}
Err(RecvTimeoutError::Disconnected) => return Err(RecvError),
}
}
@ -60,14 +70,28 @@ impl<'a> DeadlineQueue<'a> {
Some(self.queue.front()?.deadline)
}
fn remove_tests_past_deadline(&mut self) -> Vec<DeadlineEntry<'a>> {
let now = Instant::now();
let mut timed_out = vec![];
while let Some(deadline_entry) = pop_front_if(&mut self.queue, |entry| now < entry.deadline)
{
timed_out.push(deadline_entry);
fn for_each_entry_past_deadline(
&mut self,
is_running: impl Fn(TestId) -> bool,
mut on_deadline_passed: impl FnMut(TestId, &CollectedTest),
) {
let now = self.now();
// Clear out entries that are past their deadline, but only invoke the
// callback for tests that are still considered running.
while let Some(entry) = pop_front_if(&mut self.queue, |entry| entry.deadline <= now) {
if is_running(entry.id) {
on_deadline_passed(entry.id, entry.test);
}
}
// Also clear out any leading entries that are no longer running, even
// if their deadline hasn't been reached.
while let Some(_) = pop_front_if(&mut self.queue, |entry| !is_running(entry.id)) {}
if let Some(front) = self.queue.front() {
assert!(now < front.deadline);
}
timed_out
}
}

View file

@ -0,0 +1,21 @@
//@compile-flags: -Zmin-function-alignment=8
#![feature(fn_align)]
// When a function uses `repr(align(N))`, the function address should be a multiple of `N`.
#[repr(align(256))]
fn foo() {}
#[repr(align(16))]
fn bar() {}
#[repr(align(4))]
fn baz() {}
fn main() {
assert!((foo as usize).is_multiple_of(256));
assert!((bar as usize).is_multiple_of(16));
// The maximum of `repr(align(N))` and `-Zmin-function-alignment=N` is used.
assert!((baz as usize).is_multiple_of(8));
}

View file

@ -1,6 +1,6 @@
// skip-filecheck
//@ compile-flags: -Z validate-mir
#![feature(let_chains)]
//@ edition: 2024
struct Droppy(u8);
impl Drop for Droppy {
fn drop(&mut self) {

View file

@ -19,7 +19,7 @@ fn test_complex() -> () {
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = E::f() -> [return: bb1, unwind: bb34];
_2 = E::f() -> [return: bb1, unwind: bb35];
}
bb1: {
@ -42,7 +42,7 @@ fn test_complex() -> () {
bb5: {
StorageLive(_4);
_4 = always_true() -> [return: bb6, unwind: bb34];
_4 = always_true() -> [return: bb6, unwind: bb35];
}
bb6: {
@ -64,7 +64,7 @@ fn test_complex() -> () {
}
bb9: {
drop(_7) -> [return: bb11, unwind: bb34];
drop(_7) -> [return: bb11, unwind: bb35];
}
bb10: {
@ -78,7 +78,7 @@ fn test_complex() -> () {
}
bb12: {
drop(_7) -> [return: bb13, unwind: bb34];
drop(_7) -> [return: bb13, unwind: bb35];
}
bb13: {
@ -98,7 +98,7 @@ fn test_complex() -> () {
}
bb15: {
drop(_10) -> [return: bb17, unwind: bb34];
drop(_10) -> [return: bb17, unwind: bb35];
}
bb16: {
@ -113,11 +113,12 @@ fn test_complex() -> () {
bb18: {
_1 = const ();
StorageDead(_2);
goto -> bb22;
}
bb19: {
drop(_10) -> [return: bb20, unwind: bb34];
drop(_10) -> [return: bb20, unwind: bb35];
}
bb20: {
@ -127,6 +128,7 @@ fn test_complex() -> () {
}
bb21: {
StorageDead(_2);
_1 = const ();
goto -> bb22;
}
@ -135,10 +137,9 @@ fn test_complex() -> () {
StorageDead(_8);
StorageDead(_5);
StorageDead(_4);
StorageDead(_2);
StorageDead(_1);
StorageLive(_11);
_11 = always_true() -> [return: bb23, unwind: bb34];
_11 = always_true() -> [return: bb23, unwind: bb35];
}
bb23: {
@ -146,7 +147,7 @@ fn test_complex() -> () {
}
bb24: {
goto -> bb32;
goto -> bb33;
}
bb25: {
@ -155,7 +156,7 @@ fn test_complex() -> () {
bb26: {
StorageLive(_12);
_12 = E::f() -> [return: bb27, unwind: bb34];
_12 = E::f() -> [return: bb27, unwind: bb35];
}
bb27: {
@ -178,21 +179,26 @@ fn test_complex() -> () {
bb31: {
_0 = const ();
goto -> bb33;
StorageDead(_12);
goto -> bb34;
}
bb32: {
_0 = const ();
StorageDead(_12);
goto -> bb33;
}
bb33: {
_0 = const ();
goto -> bb34;
}
bb34: {
StorageDead(_11);
StorageDead(_12);
return;
}
bb34 (cleanup): {
bb35 (cleanup): {
resume;
}
}

View file

@ -0,0 +1,41 @@
#![feature(prelude_import)]
#![no_std]
//@ needs-enzyme
#![feature(autodiff)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
//@ pretty-mode:expanded
//@ pretty-compare-only
//@ pp-exact:inherent_impl.pp
use std::autodiff::autodiff;
struct Foo {
a: f64,
}
trait MyTrait {
fn f(&self, x: f64)
-> f64;
fn df(&self, x: f64, seed: f64)
-> (f64, f64);
}
impl MyTrait for Foo {
#[rustc_autodiff]
#[inline(never)]
fn f(&self, x: f64) -> f64 {
self.a * 0.25 * (x * x - 1.0 - 2.0 * x.ln())
}
#[rustc_autodiff(Reverse, 1, Const, Active, Active)]
#[inline(never)]
fn df(&self, x: f64, dret: f64) -> (f64, f64) {
unsafe { asm!("NOP", options(pure, nomem)); };
::core::hint::black_box(self.f(x));
::core::hint::black_box((dret,));
::core::hint::black_box((self.f(x), f64::default()))
}
}

View file

@ -0,0 +1,24 @@
//@ needs-enzyme
#![feature(autodiff)]
//@ pretty-mode:expanded
//@ pretty-compare-only
//@ pp-exact:inherent_impl.pp
use std::autodiff::autodiff;
struct Foo {
a: f64,
}
trait MyTrait {
fn f(&self, x: f64) -> f64;
fn df(&self, x: f64, seed: f64) -> (f64, f64);
}
impl MyTrait for Foo {
#[autodiff(df, Reverse, Const, Active, Active)]
fn f(&self, x: f64) -> f64 {
self.a * 0.25 * (x * x - 1.0 - 2.0 * x.ln())
}
}

View file

@ -23,7 +23,11 @@ fn main() {
if path.is_file()
&& path.extension().is_some_and(|ext| ext == expected_extension)
&& path.file_name().and_then(|name| name.to_str()).is_some_and(|name| {
name.ends_with(".so") || name.ends_with(".dll") || name.ends_with(".dylib")
if cfg!(target_os = "aix") {
name.ends_with(".a")
} else {
name.ends_with(".so") || name.ends_with(".dll") || name.ends_with(".dylib")
}
})
{
rfs::remove_file(path);

View file

@ -0,0 +1,54 @@
// This test is a reduced version of a bug introduced during work on type-tests for Polonius.
// The underlying problem is that the 'static bound is lost for a type parameter that is
// threaded deeply enough, causing an error.
// The bug was first observed in exr-1.4.1/src/image/read/mod.rs:124:5 during perf test.
//@ check-pass
use std::marker::PhantomData;
struct ReadAllLayers<ReadChannels> {
px: PhantomData<ReadChannels>,
}
trait ReadLayers<'s> {}
impl<'s, C> ReadLayers<'s> for ReadAllLayers<C> where C: ReadChannels<'s> {}
fn make_builder<A, Set, Pixels>(
_: Set,
) -> ReadAllLayers<CollectPixels<A, Pixels, Set>>
where
Set: Fn(&mut Pixels),
{
todo!()
}
struct CollectPixels<Pixel, PixelStorage, SetPixel> {
px: PhantomData<(SetPixel, Pixel, PixelStorage)>,
}
impl<'s, PixelStorage, SetPixel: 's> ReadChannels<'s>
for CollectPixels<usize, PixelStorage, SetPixel>
where
SetPixel: Fn(&mut PixelStorage),
{
}
trait ReadChannels<'s> {}
fn from_file<L>(_: L)
where
for<'s> L: ReadLayers<'s>,
{
}
pub fn read_all_rgba_layers_from_file<Set: 'static, Pixels: 'static>(
set_pixel: Set,
) where
Set: Fn(&mut Pixels),
{
from_file(make_builder(set_pixel)); // Error triggered.
}
pub fn main() {}

View file

@ -1,4 +1,4 @@
#![feature(let_chains)]
//@ edition: 2024
extern crate proc_macro;

View file

@ -24,7 +24,7 @@
//@ [e2024] edition: 2024
//@ run-pass
#![feature(let_chains)]
#![cfg_attr(e2021, feature(let_chains))]
#![cfg_attr(e2021, warn(rust_2024_compatibility))]
fn t_bindings() {

View file

@ -24,7 +24,7 @@
//@ [e2024] edition: 2024
//@ run-pass
#![feature(let_chains)]
#![cfg_attr(e2021, feature(let_chains))]
#![cfg_attr(e2021, warn(rust_2024_compatibility))]
fn t_bindings() {

View file

@ -2,9 +2,10 @@
//@ compile-flags: -Z validate-mir
//@ revisions: edition2021 edition2024
//@ [edition2021] edition: 2021
//@ [edition2024] compile-flags: -Z lint-mir
//@ [edition2024] edition: 2024
#![feature(let_chains)]
#![cfg_attr(edition2021, feature(let_chains))]
use std::cell::RefCell;
use std::convert::TryInto;

View file

@ -1,8 +1,6 @@
//@ run-pass
//@ edition:2024
//@ compile-flags: -Z validate-mir
#![feature(let_chains)]
//@ compile-flags: -Z validate-mir -Z lint-mir
use std::cell::RefCell;
use std::convert::TryInto;

View file

@ -1,6 +1,11 @@
//@ check-pass
//@ compile-flags: -Z validate-mir
#![feature(let_chains)]
//@ revisions: edition2021 edition2024
//@ [edition2021] edition: 2021
//@ [edition2024] compile-flags: -Z lint-mir
//@ [edition2024] edition: 2024
#![cfg_attr(edition2021, feature(let_chains))]
fn let_chains(entry: std::io::Result<std::fs::DirEntry>) {
if let Ok(entry) = entry

View file

@ -1,6 +1,5 @@
//@ check-pass
#![feature(let_chains)]
//@ edition:2024
#[cfg(false)]
fn foo() {

View file

@ -1,6 +1,6 @@
//@ check-pass
//@ edition:2024
#![feature(let_chains)]
#![allow(irrefutable_let_patterns)]
fn main() {
let _a = 0..1;

View file

@ -1,7 +1,15 @@
macro_rules! m {
($abi : expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
macro_rules! m1 {
($abi: literal) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
}
macro_rules! m2 {
($abi: expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
}
fn main() {
m!(-2)
m1!(-2)
}
fn f() {
m2!(-2)
}

View file

@ -1,13 +1,24 @@
error: expected expression, found keyword `extern`
--> $DIR/reparse-expr-issue-139495.rs:2:22
--> $DIR/reparse-expr-issue-139495.rs:2:24
|
LL | ($abi : expr) => { extern $abi }
| ^^^^^^ expected expression
LL | ($abi: literal) => { extern $abi }
| ^^^^^^ expected expression
...
LL | m!(-2)
| ------ in this macro invocation
LL | m1!(-2)
| ------- in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
error: expected expression, found keyword `extern`
--> $DIR/reparse-expr-issue-139495.rs:6:21
|
LL | ($abi: expr) => { extern $abi }
| ^^^^^^ expected expression
...
LL | m2!(-2)
| ------- in this macro invocation
|
= note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View file

@ -1,6 +1,6 @@
//@ check-pass
//@ compile-flags: -Z validate-mir
#![feature(let_chains)]
//@ edition: 2024
fn lambda<T, U>() -> U
where

View file

@ -6,7 +6,7 @@
// See `mir_drop_order.rs` for more information
#![feature(let_chains)]
#![cfg_attr(edition2021, feature(let_chains))]
#![allow(irrefutable_let_patterns)]
use std::cell::RefCell;

View file

@ -0,0 +1,31 @@
// Test that we correctly handle some cases of placeholder leaks.
//
//@ compile-flags:-Zno-leak-check
struct Co<'a>(&'a ());
struct Inv<'a>(*mut &'a ());
struct Contra<'a>(fn(&'a ()));
// `exists<'e> forall<'p> 'p: 'e` -> ERROR
fn p_outlives_e(
x: for<'e> fn(for<'p> fn(fn(fn(Contra<'e>, Co<'p>)))),
) -> fn(fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) {
x //~ ERROR mismatched types [E0308]
}
// `exists<'e> forall<'p> 'e: 'p` -> Ok, 'e: 'static
fn e_outlives_p_static(
x: for<'e> fn(Inv<'e>, for<'p> fn(fn(fn(Contra<'p>, Co<'e>)))),
) -> fn(Inv<'static>, fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) {
x
}
// `exists<'e> forall<'p> 'e: 'p` -> Ok, 'e: 'static -> ERROR
fn e_outlives_p_static_err<'not_static>(
x: for<'e> fn(Inv<'e>, for<'p> fn(fn(fn(Contra<'p>, Co<'e>)))),
) -> fn(Inv<'not_static>, fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) {
x //~ ERROR lifetime may not live long enough
}
fn main() {}

View file

@ -0,0 +1,25 @@
error[E0308]: mismatched types
--> $DIR/placeholder-outlives-existential.rs:14:5
|
LL | x
| ^ one type is more general than the other
|
= note: expected fn pointer `fn(fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>))))`
found fn pointer `for<'e> fn(for<'e, 'p> fn(for<'e, 'p> fn(for<'e, 'p> fn(Contra<'e>, Co<'p>))))`
error: lifetime may not live long enough
--> $DIR/placeholder-outlives-existential.rs:28:5
|
LL | fn e_outlives_p_static_err<'not_static>(
| ----------- lifetime `'not_static` defined here
...
LL | x
| ^ returning this value requires that `'not_static` must outlive `'static`
|
= note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant
= note: the struct `Inv<'a>` is invariant over the parameter `'a`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,6 +1,6 @@
// issue #117766
//@ edition: 2024
#![feature(let_chains)]
fn main() {
if let () = ()
&& let () = () {

View file

@ -1,4 +1,4 @@
#![feature(let_chains)]
//@ edition: 2024
trait Demo {}
impl dyn Demo {

View file

@ -0,0 +1,22 @@
#![allow(
dead_code,
unused_must_use
)]
struct Named {
foo: usize,
}
struct Unnamed(usize);
unsafe fn named_struct_field_access(named: *mut Named) {
named->foo += 1; //~ ERROR `->` is not valid syntax for field accesses and method calls
//~^ ERROR no field `foo` on type `*mut Named`
}
unsafe fn unnamed_struct_field_access(unnamed: *mut Unnamed) {
unnamed->0 += 1; //~ ERROR `->` is not valid syntax for field accesses and method calls
//~^ ERROR no field `0` on type `*mut Unnamed`
}
fn main() {}

View file

@ -0,0 +1,53 @@
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:13:10
|
LL | named->foo += 1;
| ^^
|
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - named->foo += 1;
LL + named.foo += 1;
|
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:18:12
|
LL | unnamed->0 += 1;
| ^^
|
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - unnamed->0 += 1;
LL + unnamed.0 += 1;
|
error[E0609]: no field `foo` on type `*mut Named`
--> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:13:12
|
LL | named->foo += 1;
| ^^^ unknown field
|
help: `named` is a raw pointer; try dereferencing it
|
LL - named->foo += 1;
LL + (*named).foo += 1;
|
error[E0609]: no field `0` on type `*mut Unnamed`
--> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:18:14
|
LL | unnamed->0 += 1;
| ^ unknown field
|
help: `unnamed` is a raw pointer; try dereferencing it
|
LL - unnamed->0 += 1;
LL + (*unnamed).0 += 1;
|
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0609`.

View file

@ -11,23 +11,23 @@ struct Named {
struct Unnamed(usize);
fn named_struct_field_access(named: &Named) {
named.foo; //~ ERROR `->` used for field access or method call
named.foo; //~ ERROR `->` is not valid syntax for field accesses and method calls
}
fn unnamed_struct_field_access(unnamed: &Unnamed) {
unnamed.0; //~ ERROR `->` used for field access or method call
unnamed.0; //~ ERROR `->` is not valid syntax for field accesses and method calls
}
fn tuple_field_access(t: &(u8, u8)) {
t.0; //~ ERROR `->` used for field access or method call
t.1; //~ ERROR `->` used for field access or method call
t.0; //~ ERROR `->` is not valid syntax for field accesses and method calls
t.1; //~ ERROR `->` is not valid syntax for field accesses and method calls
}
#[derive(Clone)]
struct Foo;
fn method_call(foo: &Foo) {
foo.clone(); //~ ERROR `->` used for field access or method call
foo.clone(); //~ ERROR `->` is not valid syntax for field accesses and method calls
}
fn main() {}

View file

@ -11,23 +11,23 @@ struct Named {
struct Unnamed(usize);
fn named_struct_field_access(named: &Named) {
named->foo; //~ ERROR `->` used for field access or method call
named->foo; //~ ERROR `->` is not valid syntax for field accesses and method calls
}
fn unnamed_struct_field_access(unnamed: &Unnamed) {
unnamed->0; //~ ERROR `->` used for field access or method call
unnamed->0; //~ ERROR `->` is not valid syntax for field accesses and method calls
}
fn tuple_field_access(t: &(u8, u8)) {
t->0; //~ ERROR `->` used for field access or method call
t->1; //~ ERROR `->` used for field access or method call
t->0; //~ ERROR `->` is not valid syntax for field accesses and method calls
t->1; //~ ERROR `->` is not valid syntax for field accesses and method calls
}
#[derive(Clone)]
struct Foo;
fn method_call(foo: &Foo) {
foo->clone(); //~ ERROR `->` used for field access or method call
foo->clone(); //~ ERROR `->` is not valid syntax for field accesses and method calls
}
fn main() {}

View file

@ -1,62 +1,62 @@
error: `->` used for field access or method call
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/expr-rarrow-call.rs:14:10
|
LL | named->foo;
| ^^
|
= help: the `.` operator will dereference the value if needed
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - named->foo;
LL + named.foo;
|
error: `->` used for field access or method call
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/expr-rarrow-call.rs:18:12
|
LL | unnamed->0;
| ^^
|
= help: the `.` operator will dereference the value if needed
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - unnamed->0;
LL + unnamed.0;
|
error: `->` used for field access or method call
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/expr-rarrow-call.rs:22:6
|
LL | t->0;
| ^^
|
= help: the `.` operator will dereference the value if needed
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - t->0;
LL + t.0;
|
error: `->` used for field access or method call
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/expr-rarrow-call.rs:23:6
|
LL | t->1;
| ^^
|
= help: the `.` operator will dereference the value if needed
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - t->1;
LL + t.1;
|
error: `->` used for field access or method call
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/expr-rarrow-call.rs:30:8
|
LL | foo->clone();
| ^^
|
= help: the `.` operator will dereference the value if needed
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - foo->clone();

View file

@ -1,6 +1,6 @@
//@ edition: 2024
//@ run-rustfix
#![feature(let_chains)]
#![allow(unused_variables)]
#![allow(dead_code)]
#![allow(irrefutable_let_patterns)]

View file

@ -1,6 +1,6 @@
//@ edition: 2024
//@ run-rustfix
#![feature(let_chains)]
#![allow(unused_variables)]
#![allow(dead_code)]
#![allow(irrefutable_let_patterns)]

View file

@ -5,7 +5,7 @@ fn bar() -> String {
attr::fn bar() -> String { //~ ERROR expected identifier, found keyword `fn`
//~^ ERROR expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
//~| ERROR expected `;`, found `bar`
//~| ERROR `->` used for field access or method call
//~| ERROR `->` is not valid syntax for field accesses and method calls
#[attr]
[1, 2, 3].iter().map().collect::<String>()
#[attr]

View file

@ -33,13 +33,13 @@ LL | attr::fn bar() -> String {
| |
| help: add `;` here
error: `->` used for field access or method call
error: `->` is not valid syntax for field accesses and method calls
--> $DIR/issue-118530-ice.rs:5:20
|
LL | attr::fn bar() -> String {
| ^^
|
= help: the `.` operator will dereference the value if needed
= help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
help: try using `.` instead
|
LL - attr::fn bar() -> String {

View file

@ -1,6 +1,5 @@
// Issue #117720
#![feature(let_chains)]
//@ edition: 2024
fn main() {
if let () = ()

View file

@ -1,11 +1,11 @@
error: expected `{`, found `;`
--> $DIR/semi-in-let-chain.rs:7:23
--> $DIR/semi-in-let-chain.rs:6:23
|
LL | && let () = ();
| ^ expected `{`
|
note: you likely meant to continue parsing the let-chain starting here
--> $DIR/semi-in-let-chain.rs:8:9
--> $DIR/semi-in-let-chain.rs:7:9
|
LL | && let () = ()
| ^^^^^^
@ -16,13 +16,13 @@ LL + && let () = ()
|
error: expected `{`, found `;`
--> $DIR/semi-in-let-chain.rs:15:20
--> $DIR/semi-in-let-chain.rs:14:20
|
LL | && () == ();
| ^ expected `{`
|
note: the `if` expression is missing a block after this condition
--> $DIR/semi-in-let-chain.rs:14:8
--> $DIR/semi-in-let-chain.rs:13:8
|
LL | if let () = ()
| ________^
@ -30,13 +30,13 @@ LL | | && () == ();
| |___________________^
error: expected `{`, found `;`
--> $DIR/semi-in-let-chain.rs:23:20
--> $DIR/semi-in-let-chain.rs:22:20
|
LL | && () == ();
| ^ expected `{`
|
note: you likely meant to continue parsing the let-chain starting here
--> $DIR/semi-in-let-chain.rs:24:9
--> $DIR/semi-in-let-chain.rs:23:9
|
LL | && let () = ()
| ^^^^^^

View file

@ -1,5 +1,5 @@
//@ edition: 2024
#![feature(never_patterns)]
#![feature(let_chains)]
#![allow(incomplete_features)]
#![deny(unreachable_patterns)]

View file

@ -15,11 +15,9 @@ fn _if_let_guard() {
() if true && let 0 = 1 => {}
//~^ ERROR `if let` guards are experimental
//~| ERROR `let` expressions in this position are unstable
() if let 0 = 1 && true => {}
//~^ ERROR `if let` guards are experimental
//~| ERROR `let` expressions in this position are unstable
() if (let 0 = 1) && true => {}
//~^ ERROR expected expression, found `let` statement
@ -33,8 +31,6 @@ fn _if_let_guard() {
() if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
//~^ ERROR `if let` guards are experimental
//~| ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
@ -42,7 +38,6 @@ fn _if_let_guard() {
() if let Range { start: _, end: _ } = (true..true) && false => {}
//~^ ERROR `if let` guards are experimental
//~| ERROR `let` expressions in this position are unstable
_ => {}
}

View file

@ -25,98 +25,98 @@ LL | () if (((let 0 = 1))) => {}
| ^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:24:16
--> $DIR/feature-gate.rs:22:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
note: `let`s wrapped in parentheses are not supported in a context with let chains
--> $DIR/feature-gate.rs:24:16
--> $DIR/feature-gate.rs:22:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:27:24
--> $DIR/feature-gate.rs:25:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
note: `let`s wrapped in parentheses are not supported in a context with let chains
--> $DIR/feature-gate.rs:27:24
--> $DIR/feature-gate.rs:25:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:30:16
--> $DIR/feature-gate.rs:28:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
note: `let`s wrapped in parentheses are not supported in a context with let chains
--> $DIR/feature-gate.rs:30:16
--> $DIR/feature-gate.rs:28:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:30:31
--> $DIR/feature-gate.rs:28:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
note: `let`s wrapped in parentheses are not supported in a context with let chains
--> $DIR/feature-gate.rs:30:31
--> $DIR/feature-gate.rs:28:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:34:42
--> $DIR/feature-gate.rs:32:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
note: `let`s wrapped in parentheses are not supported in a context with let chains
--> $DIR/feature-gate.rs:34:42
--> $DIR/feature-gate.rs:32:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:34:55
--> $DIR/feature-gate.rs:32:55
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
note: `let`s wrapped in parentheses are not supported in a context with let chains
--> $DIR/feature-gate.rs:34:42
--> $DIR/feature-gate.rs:32:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:34:68
--> $DIR/feature-gate.rs:32:68
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
note: `let`s wrapped in parentheses are not supported in a context with let chains
--> $DIR/feature-gate.rs:34:42
--> $DIR/feature-gate.rs:32:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:60:16
--> $DIR/feature-gate.rs:55:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^
@ -124,7 +124,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0));
= note: only supported directly in conditions of `if` and `while` expressions
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:60:16
--> $DIR/feature-gate.rs:55:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^
@ -133,7 +133,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0));
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:63:16
--> $DIR/feature-gate.rs:58:16
|
LL | use_expr!((let 0 = 1));
| ^^^
@ -141,7 +141,7 @@ LL | use_expr!((let 0 = 1));
= note: only supported directly in conditions of `if` and `while` expressions
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:63:16
--> $DIR/feature-gate.rs:58:16
|
LL | use_expr!((let 0 = 1));
| ^^^
@ -150,7 +150,7 @@ LL | use_expr!((let 0 = 1));
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: no rules expected keyword `let`
--> $DIR/feature-gate.rs:72:15
--> $DIR/feature-gate.rs:67:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
@ -159,7 +159,7 @@ LL | use_expr!(let 0 = 1);
| ^^^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$e:expr`
--> $DIR/feature-gate.rs:53:10
--> $DIR/feature-gate.rs:48:10
|
LL | ($e:expr) => {
| ^^^^^^^
@ -187,7 +187,7 @@ LL | () if true && let 0 = 1 => {}
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:20:12
--> $DIR/feature-gate.rs:19:12
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^^^^^^^^^^^^
@ -198,7 +198,7 @@ LL | () if let 0 = 1 && true => {}
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:34:12
--> $DIR/feature-gate.rs:32:12
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -209,7 +209,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:43:12
--> $DIR/feature-gate.rs:39:12
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -220,7 +220,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:68:12
--> $DIR/feature-gate.rs:63:12
|
LL | () if let 0 = 1 => {}
| ^^^^^^^^^^^^
@ -230,56 +230,6 @@ LL | () if let 0 = 1 => {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:16:23
|
LL | () if true && let 0 = 1 => {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:20:15
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:34:15
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:34:28
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:43:15
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 25 previous errors
error: aborting due to 20 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,7 +1,6 @@
// Expression macros can't expand to a let match guard.
#![feature(if_let_guard)]
#![feature(let_chains)]
macro_rules! m {
($e:expr) => { let Some(x) = $e }

View file

@ -1,5 +1,5 @@
error: expected expression, found `let` statement
--> $DIR/macro-expanded.rs:7:20
--> $DIR/macro-expanded.rs:6:20
|
LL | ($e:expr) => { let Some(x) = $e }
| ^^^

View file

@ -1,5 +1,5 @@
//@ edition: 2024
#![feature(if_let_guard)]
#![feature(let_chains)]
#![allow(irrefutable_let_patterns)]
fn same_pattern(c: bool) {

View file

@ -1,7 +1,7 @@
//@ edition: 2024
// Parenthesised let "expressions" are not allowed in guards
#![feature(if_let_guard)]
#![feature(let_chains)]
#[cfg(false)]
fn un_cfged() {

View file

@ -1,8 +1,8 @@
// Check shadowing in if let guards works as expected.
//@ check-pass
//@ edition: 2024
#![feature(if_let_guard)]
#![feature(let_chains)]
fn main() {
let x: Option<Option<i32>> = Some(Some(6));

View file

@ -1,6 +1,6 @@
//@ run-pass
//@ edition: 2024
#![feature(let_chains)]
#![allow(irrefutable_let_patterns)]
fn main() {

View file

@ -1,4 +1,4 @@
#![feature(let_chains)]
//@ edition: 2024
fn let_or_guard(x: Result<Option<i32>, ()>) {
match x {

View file

@ -0,0 +1,26 @@
//@ edition: 2021
#[macro_export]
macro_rules! make_if {
(($($tt:tt)*) { $body:expr } { $else:expr }) => {{
if $($tt)* {
$body
} else {
$else
}
}};
(let ($expr:expr) { $body:expr } { $else:expr }) => {{
if let None = $expr {
$body
} else {
$else
}
}};
(let ($expr:expr) let ($expr2:expr) { $body:expr } { $else:expr }) => {{
if let None = $expr && let None = $expr2 {
$body
} else {
$else
}
}};
}

View file

@ -0,0 +1,26 @@
//@ edition: 2024
#[macro_export]
macro_rules! make_if {
(($($tt:tt)*) { $body:expr } { $else:expr }) => {{
if $($tt)* {
$body
} else {
$else
}
}};
(let ($expr:expr) { $body:expr } { $else:expr }) => {{
if let None = $expr {
$body
} else {
$else
}
}};
(let ($expr:expr) let ($expr2:expr) { $body:expr } { $else:expr }) => {{
if let None = $expr && let None = $expr2 {
$body
} else {
$else
}
}};
}

View file

@ -0,0 +1,65 @@
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:19:30
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:19:52
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:26:30
|
LL | macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:26:52
|
LL | macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,45 @@
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:19:30
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:19:52
|
LL | macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `let` expressions in this position are unstable
--> $DIR/edition-gate-macro-error.rs:22:5
|
LL | macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: this error originates in the macro `macro_in_2021::make_if` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,30 @@
//@ revisions: edition2021 edition2024
//@ compile-flags: -Z lint-mir -Z validate-mir
//@ [edition2021] edition: 2021
//@ [edition2024] edition: 2024
//@ aux-build:macro-in-2021.rs
//@ aux-build:macro-in-2024.rs
use std::unreachable as never;
// Compiletest doesn't specify the needed --extern flags to make `extern crate` unneccessary
extern crate macro_in_2021;
extern crate macro_in_2024;
fn main() {
// Gated on both 2021 and 2024 if the `if` comes from a 2021 macro
// Gated only on 2021 if the `if` comes from a 2024 macro
// No gating if both the `if` and the chain are from a 2024 macro
macro_in_2021::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
macro_in_2021::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
macro_in_2024::make_if!((let Some(0) = None && let Some(0) = None) { never!() } { never!() });
//[edition2021]~^ ERROR `let` expressions in this position are unstable
//[edition2021]~| ERROR `let` expressions in this position are unstable
macro_in_2024::make_if!(let (Some(0)) let (Some(0)) { never!() } { never!() });
}

View file

@ -0,0 +1,76 @@
//@ revisions: edition2021 edition2024
//@ compile-flags: -Z lint-mir -Z validate-mir
//@ [edition2021] edition: 2021
//@ [edition2024] edition: 2024
//@ aux-build:macro-in-2021.rs
//@ aux-build:macro-in-2024.rs
//@ run-pass
#![allow(dead_code)]
use std::unreachable as never;
use std::cell::RefCell;
use std::convert::TryInto;
// Compiletest doesn't specify the needed --extern flags to make `extern crate` unneccessary
extern crate macro_in_2021;
extern crate macro_in_2024;
#[derive(Default)]
struct DropOrderCollector(RefCell<Vec<u32>>);
struct LoudDrop<'a>(&'a DropOrderCollector, u32);
impl Drop for LoudDrop<'_> {
fn drop(&mut self) {
println!("{}", self.1);
self.0.0.borrow_mut().push(self.1);
}
}
impl DropOrderCollector {
fn print(&self, n: u32) {
println!("{n}");
self.0.borrow_mut().push(n)
}
fn some_loud(&self, n: u32) -> Option<LoudDrop> {
Some(LoudDrop(self, n))
}
#[track_caller]
fn validate(self) {
assert!(
self.0
.into_inner()
.into_iter()
.enumerate()
.all(|(idx, item)| idx + 1 == item.try_into().unwrap())
);
}
fn with_macro_2021(self) {
// Edition 2021 drop behaviour
macro_in_2021::make_if!((let None = self.some_loud(2)) { never!() } {self.print(1) });
macro_in_2021::make_if!(let (self.some_loud(4)) { never!() } { self.print(3) });
self.validate();
}
fn with_macro_2024(self) {
// Edition 2024 drop behaviour
macro_in_2024::make_if!((let None = self.some_loud(1)) { never!() } { self.print(2) });
macro_in_2024::make_if!(let (self.some_loud(3)) { never!() } { self.print(4) });
self.validate();
}
}
fn main() {
// 2021 drop order if it's a 2021 macro creating the `if`
// 2024 drop order if it's a 2024 macro creating the `if`
// Compare this with edition-gate-macro-error.rs: We want to avoid exposing 2021 drop order,
// because it can create bad MIR (issue #104843)
// This test doesn't contain any let chains at all: it should be understood
// in combination with `edition-gate-macro-error.rs`
DropOrderCollector::default().with_macro_2021();
DropOrderCollector::default().with_macro_2024();
}

View file

@ -1,4 +1,4 @@
#![feature(let_chains)]
//@ edition: 2024
fn main() {
let opt = Some(1i32);

View file

@ -1,6 +1,5 @@
//@ check-pass
#![feature(let_chains)]
//@ edition: 2024
fn main() {
let x = Some(vec!["test"]);

View file

@ -1,6 +1,5 @@
//@ check-pass
#![feature(let_chains)]
//@ edition:2024
fn main() {
let opt = Some("foo bar");

View file

@ -2,7 +2,6 @@ fn main() {
match true {
_ if let true = true && true => {}
//~^ ERROR `if let` guards are
//~| ERROR `let` expressions in this
_ => {}
}
}

View file

@ -9,16 +9,6 @@ LL | _ if let true = true && true => {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `let` expressions in this position are unstable
--> $DIR/issue-93150.rs:3:14
|
LL | _ if let true = true && true => {}
| ^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 2 previous errors
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,6 +1,7 @@
//@ compile-flags: -Zvalidate-mir -C opt-level=3
//@ build-pass
#![feature(let_chains)]
//@ edition: 2024
struct TupleIter<T, I: Iterator<Item = T>> {
inner: I,
}

View file

@ -3,7 +3,6 @@
//@ edition: 2024
//@ check-pass
#![feature(let_chains)]
#![allow(irrefutable_let_patterns)]
struct Pd;

View file

@ -12,7 +12,6 @@
#![feature(dyn_star)]
#![feature(explicit_tail_calls)]
#![feature(gen_blocks)]
#![feature(let_chains)]
#![feature(more_qualified_paths)]
#![feature(never_patterns)]
#![feature(never_type)]

View file

@ -13,7 +13,6 @@
#![feature(dyn_star)]
#![feature(explicit_tail_calls)]
#![feature(gen_blocks)]
#![feature(let_chains)]
#![feature(more_qualified_paths)]
#![feature(never_patterns)]
#![feature(never_type)]

View file

@ -1,6 +1,6 @@
//@ compile-flags: -Zunpretty=expanded
//@ edition:2024
//@ check-pass
//@ edition: 2015
// This test covers the AST pretty-printer's insertion of parentheses in some
// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in
@ -8,7 +8,6 @@
// Rust syntax. We also test negative cases: the pretty-printer should not be
// synthesizing parentheses indiscriminately; only where necessary.
#![feature(let_chains)]
#![feature(if_let_guard)]
macro_rules! expr {

View file

@ -1,8 +1,7 @@
#![feature(prelude_import)]
#![no_std]
//@ compile-flags: -Zunpretty=expanded
//@ edition:2024
//@ check-pass
//@ edition: 2015
// This test covers the AST pretty-printer's insertion of parentheses in some
// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in
@ -10,10 +9,9 @@
// Rust syntax. We also test negative cases: the pretty-printer should not be
// synthesizing parentheses indiscriminately; only where necessary.
#![feature(let_chains)]
#![feature(if_let_guard)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
use std::prelude::rust_2024::*;
#[macro_use]
extern crate std;