diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index e60efdbefd92a..6d97dfa3a4d41 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -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); } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d077900587e9c..9d8130661b04d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -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=` flag; + // the alignment from a `#[repr(align())]` 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 diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d6a7bfc446a41..9c6d4ee096f1a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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, ); diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e7f17bb6f996d..97bade2d31e22 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -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 diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f3ed798eba4e1..370eb3f402d93 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2146,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 { + let check_expr = |expr: P| { + 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(); @@ -2159,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, .. }, @@ -2170,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, } diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index d3d1eebc22753..2ee25969289fc 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -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; diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index dceb30177e668..69882d13c177f 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -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; diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index c97dbfb63ae17..7e056a6c1f3fa 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -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; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 91affdb3794b0..b9ebbb1d76497 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -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. diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 3b04ec50db30e..92bb809d90c24 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -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 { 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 { // Our minimum required musl supports this function, so we can just use it. Some(libc::posix_spawn_file_actions_addchdir_np) diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs index df28e8129ddd9..677738bac8f98 100644 --- a/library/std/tests/floats/f128.rs +++ b/library/std/tests/floats/f128.rs @@ -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] diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs index 1a90f00aecceb..0fc4df8115a24 100644 --- a/library/std/tests/floats/f16.rs +++ b/library/std/tests/floats/f16.rs @@ -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] diff --git a/library/std/tests/floats/f32.rs b/library/std/tests/floats/f32.rs index d99b03cb255f7..9af23afc5bbfc 100644 --- a/library/std/tests/floats/f32.rs +++ b/library/std/tests/floats/f32.rs @@ -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] diff --git a/library/std/tests/floats/f64.rs b/library/std/tests/floats/f64.rs index 611670751bb52..de9c27eb33d39 100644 --- a/library/std/tests/floats/f64.rs +++ b/library/std/tests/floats/f64.rs @@ -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] diff --git a/src/doc/nomicon b/src/doc/nomicon index 0c10c30cc5473..c76a20f0d9871 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 0c10c30cc54736c5c194ce98c50e2de84eeb6e79 +Subproject commit c76a20f0d987145dcedf05c5c073ce8d91f2e82a diff --git a/src/doc/reference b/src/doc/reference index 3340922df189b..3bf3402aea982 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3340922df189bddcbaad17dc3927d51a76bcd5ed +Subproject commit 3bf3402aea982b876eb56c87da17b0685c6461d5 diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index 0c173d476affa..990be56ce0c5e 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -57,9 +57,11 @@ pub(crate) fn run_tests(config: &Config, tests: Vec) -> 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(); diff --git a/src/tools/compiletest/src/executor/deadline.rs b/src/tools/compiletest/src/executor/deadline.rs index 83b8591a41642..3536eff2fd80d 100644 --- a/src/tools/compiletest/src/executor/deadline.rs +++ b/src/tools/compiletest/src/executor/deadline.rs @@ -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( &mut self, rx: &mpsc::Receiver, + is_running: impl Fn(TestId) -> bool, mut on_deadline_passed: impl FnMut(TestId, &CollectedTest), ) -> Result { 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> { - 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 } } diff --git a/src/tools/miri/tests/pass/fn_align.rs b/src/tools/miri/tests/pass/fn_align.rs new file mode 100644 index 0000000000000..550bb1cb4d718 --- /dev/null +++ b/src/tools/miri/tests/pass/fn_align.rs @@ -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)); +} diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff/autodiff_forward.pp similarity index 100% rename from tests/pretty/autodiff_forward.pp rename to tests/pretty/autodiff/autodiff_forward.pp diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff/autodiff_forward.rs similarity index 100% rename from tests/pretty/autodiff_forward.rs rename to tests/pretty/autodiff/autodiff_forward.rs diff --git a/tests/pretty/autodiff_reverse.pp b/tests/pretty/autodiff/autodiff_reverse.pp similarity index 100% rename from tests/pretty/autodiff_reverse.pp rename to tests/pretty/autodiff/autodiff_reverse.pp diff --git a/tests/pretty/autodiff_reverse.rs b/tests/pretty/autodiff/autodiff_reverse.rs similarity index 100% rename from tests/pretty/autodiff_reverse.rs rename to tests/pretty/autodiff/autodiff_reverse.rs diff --git a/tests/pretty/autodiff/inherent_impl.pp b/tests/pretty/autodiff/inherent_impl.pp new file mode 100644 index 0000000000000..97ac766b6b99e --- /dev/null +++ b/tests/pretty/autodiff/inherent_impl.pp @@ -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())) + } +} diff --git a/tests/pretty/autodiff/inherent_impl.rs b/tests/pretty/autodiff/inherent_impl.rs new file mode 100644 index 0000000000000..59de93f7e0ffd --- /dev/null +++ b/tests/pretty/autodiff/inherent_impl.rs @@ -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()) + } +} diff --git a/tests/ui/macros/reparse-expr-issue-139495.rs b/tests/ui/macros/reparse-expr-issue-139495.rs index 38d24573a5338..89734cae0a61d 100644 --- a/tests/ui/macros/reparse-expr-issue-139495.rs +++ b/tests/ui/macros/reparse-expr-issue-139495.rs @@ -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) } diff --git a/tests/ui/macros/reparse-expr-issue-139495.stderr b/tests/ui/macros/reparse-expr-issue-139495.stderr index 73a8ed87ba058..e2e05d67ecc22 100644 --- a/tests/ui/macros/reparse-expr-issue-139495.stderr +++ b/tests/ui/macros/reparse-expr-issue-139495.stderr @@ -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 diff --git a/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.rs b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.rs new file mode 100644 index 0000000000000..0ce5e233930e0 --- /dev/null +++ b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.rs @@ -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() {} diff --git a/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.stderr b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.stderr new file mode 100644 index 0000000000000..45f3c5549f7ef --- /dev/null +++ b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.stderr @@ -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`. diff --git a/tests/ui/parser/expr-rarrow-call.fixed b/tests/ui/parser/expr-rarrow-call.fixed index 9a05e20092dd8..c97284c4b01e7 100644 --- a/tests/ui/parser/expr-rarrow-call.fixed +++ b/tests/ui/parser/expr-rarrow-call.fixed @@ -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() {} diff --git a/tests/ui/parser/expr-rarrow-call.rs b/tests/ui/parser/expr-rarrow-call.rs index 760b0f6f345b9..78cd72b12ec85 100644 --- a/tests/ui/parser/expr-rarrow-call.rs +++ b/tests/ui/parser/expr-rarrow-call.rs @@ -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() {} diff --git a/tests/ui/parser/expr-rarrow-call.stderr b/tests/ui/parser/expr-rarrow-call.stderr index 2e168ca26fecc..0b105273861f8 100644 --- a/tests/ui/parser/expr-rarrow-call.stderr +++ b/tests/ui/parser/expr-rarrow-call.stderr @@ -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(); diff --git a/tests/ui/parser/issues/issue-118530-ice.rs b/tests/ui/parser/issues/issue-118530-ice.rs index cf14eebec2b76..8930eb86c6b24 100644 --- a/tests/ui/parser/issues/issue-118530-ice.rs +++ b/tests/ui/parser/issues/issue-118530-ice.rs @@ -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::() #[attr] diff --git a/tests/ui/parser/issues/issue-118530-ice.stderr b/tests/ui/parser/issues/issue-118530-ice.stderr index 72c0397e9c95b..ef891d1dc2906 100644 --- a/tests/ui/parser/issues/issue-118530-ice.stderr +++ b/tests/ui/parser/issues/issue-118530-ice.stderr @@ -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 {