diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 87db08ef5b510..7901a5046abad 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -583,10 +583,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let err = FnMutError { span: *span, ty_err: match output_ty.kind() { - ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span }, ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => { FnMutReturnTypeErr::ReturnAsyncBlock { span: *span } } + _ if output_ty.contains_closure() => { + FnMutReturnTypeErr::ReturnClosure { span: *span } + } _ => FnMutReturnTypeErr::ReturnRef { span: *span }, }, }; @@ -997,7 +999,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) { let map = self.infcx.tcx.hir(); let body_id = map.body_owned_by(self.mir_def_id()); - let expr = &map.body(body_id).value; + let expr = &map.body(body_id).value.peel_blocks(); let mut closure_span = None::; match expr.kind { hir::ExprKind::MethodCall(.., args, _) => { @@ -1012,20 +1014,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } } - hir::ExprKind::Block(blk, _) => { - if let Some(expr) = blk.expr { - // only when the block is a closure - if let hir::ExprKind::Closure(hir::Closure { - capture_clause: hir::CaptureBy::Ref, - body, - .. - }) = expr.kind - { - let body = map.body(*body); - if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) { - closure_span = Some(expr.span.shrink_to_lo()); - } - } + hir::ExprKind::Closure(hir::Closure { + capture_clause: hir::CaptureBy::Ref, + body, + .. + }) => { + let body = map.body(*body); + if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) { + closure_span = Some(expr.span.shrink_to_lo()); } } _ => {} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 060d864389cb0..98d6b68356368 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2043,6 +2043,28 @@ impl<'tcx> Ty<'tcx> { cf.is_break() } + /// Checks whether a type recursively contains any closure + /// + /// Example: `Option<[closure@file.rs:4:20]>` returns true + pub fn contains_closure(self) -> bool { + struct ContainsClosureVisitor; + + impl<'tcx> TypeVisitor<'tcx> for ContainsClosureVisitor { + type BreakTy = (); + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if let ty::Closure(_, _) = t.kind() { + ControlFlow::Break(()) + } else { + t.super_visit_with(self) + } + } + } + + let cf = self.visit_with(&mut ContainsClosureVisitor); + cf.is_break() + } + /// Returns the type and mutability of `*ty`. /// /// The parameter `explicit` indicates if this is an *explicit* dereference. diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 16d5edfd303a3..cd9d85b1d919c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2405,26 +2405,42 @@ impl<'a> Parser<'a> { if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) { + let mut snapshot_type = self.create_snapshot_for_diagnostic(); + snapshot_type.bump(); // `:` + match snapshot_type.parse_ty() { + Err(inner_err) => { + inner_err.cancel(); + } + Ok(ty) => { + let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else { + return first_pat; + }; + err.span_label(ty.span, "specifying the type of a pattern isn't supported"); + self.restore_snapshot(snapshot_type); + let span = first_pat.span.to(ty.span); + first_pat = self.mk_pat(span, PatKind::Wild); + err.emit(); + } + } return first_pat; } // The pattern looks like it might be a path with a `::` -> `:` typo: // `match foo { bar:baz => {} }` - let span = self.token.span; + let colon_span = self.token.span; // We only emit "unexpected `:`" error here if we can successfully parse the // whole pattern correctly in that case. - let snapshot = self.create_snapshot_for_diagnostic(); + let mut snapshot_pat = self.create_snapshot_for_diagnostic(); + let mut snapshot_type = self.create_snapshot_for_diagnostic(); // Create error for "unexpected `:`". match self.expected_one_of_not_found(&[], &[]) { Err(mut err) => { - self.bump(); // Skip the `:`. - match self.parse_pat_no_top_alt(expected) { + // Skip the `:`. + snapshot_pat.bump(); + snapshot_type.bump(); + match snapshot_pat.parse_pat_no_top_alt(expected) { Err(inner_err) => { - // Carry on as if we had not done anything, callers will emit a - // reasonable error. inner_err.cancel(); - err.cancel(); - self.restore_snapshot(snapshot); } Ok(mut pat) => { // We've parsed the rest of the pattern. @@ -2488,8 +2504,8 @@ impl<'a> Parser<'a> { _ => {} } if show_sugg { - err.span_suggestion( - span, + err.span_suggestion_verbose( + colon_span.until(self.look_ahead(1, |t| t.span)), "maybe write a path separator here", "::", Applicability::MaybeIncorrect, @@ -2497,13 +2513,24 @@ impl<'a> Parser<'a> { } else { first_pat = self.mk_pat(new_span, PatKind::Wild); } - err.emit(); + self.restore_snapshot(snapshot_pat); } } + match snapshot_type.parse_ty() { + Err(inner_err) => { + inner_err.cancel(); + } + Ok(ty) => { + err.span_label(ty.span, "specifying the type of a pattern isn't supported"); + self.restore_snapshot(snapshot_type); + let new_span = first_pat.span.to(ty.span); + first_pat = self.mk_pat(new_span, PatKind::Wild); + } + } + err.emit(); } _ => { // Carry on as if we had not done anything. This should be unreachable. - self.restore_snapshot(snapshot); } }; first_pat diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index a6dfcd2976247..088a87ca57104 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -273,7 +273,13 @@ impl<'a> Iterator for Parser<'a> { ); } } else { - self.suggest_positional_arg_instead_of_captured_arg(arg); + if let Some(&(_, maybe)) = self.cur.peek() { + if maybe == '?' { + self.suggest_format(); + } else { + self.suggest_positional_arg_instead_of_captured_arg(arg); + } + } } Some(NextArgument(Box::new(arg))) } @@ -832,6 +838,27 @@ impl<'a> Parser<'a> { if found { Some(cur) } else { None } } + fn suggest_format(&mut self) { + if let (Some(pos), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) { + let word = self.word(); + let _end = self.current_pos(); + let pos = self.to_span_index(pos); + self.errors.insert( + 0, + ParseError { + description: "expected format parameter to occur after `:`".to_owned(), + note: Some( + format!("`?` comes after `:`, try `{}:{}` instead", word, "?").to_owned(), + ), + label: "expected `?` to occur after `:`".to_owned(), + span: pos.to(pos), + secondary_label: None, + should_be_replaced_with_positional_argument: false, + }, + ); + } + } + fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) { if let Some(end) = self.consume_pos('.') { let byte_pos = self.to_span_index(end); diff --git a/library/core/benches/char/methods.rs b/library/core/benches/char/methods.rs index 9408f83c32f7c..5d4df1ac8bd58 100644 --- a/library/core/benches/char/methods.rs +++ b/library/core/benches/char/methods.rs @@ -1,26 +1,26 @@ -use test::Bencher; +use test::{black_box, Bencher}; const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9']; const RADIX: [u32; 5] = [2, 8, 10, 16, 32]; #[bench] fn bench_to_digit_radix_2(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(2)).min()) } #[bench] fn bench_to_digit_radix_10(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(10)).min()) } #[bench] fn bench_to_digit_radix_16(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(16)).min()) } #[bench] fn bench_to_digit_radix_36(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(36)).min()) } #[bench] @@ -31,47 +31,59 @@ fn bench_to_digit_radix_var(b: &mut Bencher) { .cycle() .zip(RADIX.iter().cycle()) .take(10_000) - .map(|(c, radix)| c.to_digit(*radix)) + .map(|(c, radix)| black_box(c).to_digit(*radix)) .min() }) } #[bench] fn bench_to_ascii_uppercase(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_uppercase()).min()) } #[bench] fn bench_to_ascii_lowercase(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_lowercase()).min()) } #[bench] fn bench_ascii_mix_to_uppercase(b: &mut Bencher) { - b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count()) + b.iter(|| { + (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + }) } #[bench] fn bench_ascii_mix_to_lowercase(b: &mut Bencher) { - b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count()) + b.iter(|| { + (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + }) } #[bench] fn bench_ascii_char_to_uppercase(b: &mut Bencher) { - b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count()) + b.iter(|| { + (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + }) } #[bench] fn bench_ascii_char_to_lowercase(b: &mut Bencher) { - b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count()) + b.iter(|| { + (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + }) } #[bench] fn bench_non_ascii_char_to_uppercase(b: &mut Bencher) { - b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count()) + b.iter(|| { + (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + }) } #[bench] fn bench_non_ascii_char_to_lowercase(b: &mut Bencher) { - b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count()) + b.iter(|| { + (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + }) } diff --git a/library/core/benches/num/flt2dec/strategy/dragon.rs b/library/core/benches/num/flt2dec/strategy/dragon.rs index 319b9773e49fe..377c99effd03c 100644 --- a/library/core/benches/num/flt2dec/strategy/dragon.rs +++ b/library/core/benches/num/flt2dec/strategy/dragon.rs @@ -1,14 +1,14 @@ use super::super::*; use core::num::flt2dec::strategy::dragon::*; use std::mem::MaybeUninit; -use test::Bencher; +use test::{black_box, Bencher}; #[bench] fn bench_small_shortest(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -17,7 +17,7 @@ fn bench_big_shortest(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -26,7 +26,7 @@ fn bench_small_exact_3(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -35,7 +35,7 @@ fn bench_big_exact_3(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -44,7 +44,7 @@ fn bench_small_exact_12(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -53,7 +53,7 @@ fn bench_big_exact_12(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -62,7 +62,7 @@ fn bench_small_exact_inf(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -71,6 +71,6 @@ fn bench_big_exact_inf(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/core/benches/num/flt2dec/strategy/grisu.rs index 8e47a046cdea5..6bea5e55d37bb 100644 --- a/library/core/benches/num/flt2dec/strategy/grisu.rs +++ b/library/core/benches/num/flt2dec/strategy/grisu.rs @@ -1,7 +1,7 @@ use super::super::*; use core::num::flt2dec::strategy::grisu::*; use std::mem::MaybeUninit; -use test::Bencher; +use test::{black_box, Bencher}; pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { @@ -15,7 +15,7 @@ fn bench_small_shortest(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -24,7 +24,7 @@ fn bench_big_shortest(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -33,7 +33,7 @@ fn bench_small_exact_3(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -42,7 +42,7 @@ fn bench_big_exact_3(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -51,7 +51,7 @@ fn bench_small_exact_12(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -60,7 +60,7 @@ fn bench_big_exact_12(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -69,7 +69,7 @@ fn bench_small_exact_inf(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -78,6 +78,6 @@ fn bench_big_exact_inf(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index c8d1ff9aefb7e..a6d84a3c18a5f 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -19,18 +19,18 @@ import signal import subprocess import sys -from typing import ClassVar, List +from typing import ClassVar, List, Optional @dataclass class TestEnvironment: rust_dir: str sdk_dir: str - target_arch: str - package_server_pid: int = None - emu_addr: str = None - libstd_name: str = None - libtest_name: str = None + target: str + package_server_pid: Optional[int] = None + emu_addr: Optional[str] = None + libstd_name: Optional[str] = None + libtest_name: Optional[str] = None verbose: bool = False @staticmethod @@ -40,6 +40,15 @@ def tmp_dir(): return os.path.abspath(tmp_dir) return os.path.join(os.path.dirname(__file__), "tmp~") + @staticmethod + def triple_to_arch(triple): + if "x86_64" in triple: + return "x64" + elif "aarch64" in triple: + return "arm64" + else: + raise Exception(f"Unrecognized target triple {triple}") + @classmethod def env_file_path(cls): return os.path.join(cls.tmp_dir(), "test_env.json") @@ -49,7 +58,7 @@ def from_args(cls, args): return cls( os.path.abspath(args.rust), os.path.abspath(args.sdk), - args.target_arch, + args.target, verbose=args.verbose, ) @@ -60,7 +69,7 @@ def read_from_file(cls): return cls( test_env["rust_dir"], test_env["sdk_dir"], - test_env["target_arch"], + test_env["target"], libstd_name=test_env["libstd_name"], libtest_name=test_env["libtest_name"], emu_addr=test_env["emu_addr"], @@ -68,13 +77,6 @@ def read_from_file(cls): verbose=test_env["verbose"], ) - def image_name(self): - if self.target_arch == "x64": - return "qemu-x64" - if self.target_arch == "arm64": - return "qemu-arm64" - raise Exception(f"Unrecognized target architecture {self.target_arch}") - def write_to_file(self): with open(self.env_file_path(), "w", encoding="utf-8") as f: f.write(json.dumps(self.__dict__)) @@ -108,13 +110,6 @@ def output_dir(self): def repo_dir(self): return os.path.join(self.tmp_dir(), self.TEST_REPO_NAME) - def rustlib_dir(self): - if self.target_arch == "x64": - return "x86_64-unknown-fuchsia" - if self.target_arch == "arm64": - return "aarch64-unknown-fuchsia" - raise Exception(f"Unrecognized target architecture {self.target_arch}") - def libs_dir(self): return os.path.join( self.rust_dir, @@ -125,7 +120,7 @@ def rustlibs_dir(self): return os.path.join( self.libs_dir(), "rustlib", - self.rustlib_dir(), + self.target, "lib", ) @@ -384,7 +379,7 @@ def start(self): "--emulator-log", self.emulator_log_path(), "--image-name", - self.image_name(), + "qemu-" + self.triple_to_arch(self.target), ], stdout=self.subprocess_output(), stderr=self.subprocess_output(), @@ -642,11 +637,11 @@ def log(msg): package_dir=package_dir, package_name=package_name, rust_dir=self.rust_dir, - rustlib_dir=self.rustlib_dir(), + rustlib_dir=self.target, sdk_dir=self.sdk_dir, libstd_name=self.libstd_name, libtest_name=self.libtest_name, - target_arch=self.target_arch, + target_arch=self.triple_to_arch(self.target), ) ) for shared_lib in shared_libs: @@ -969,8 +964,8 @@ def print_help(args): action="store_true", ) start_parser.add_argument( - "--target-arch", - help="the architecture of the image to test", + "--target", + help="the target platform to test", required=True, ) start_parser.set_defaults(func=start) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 29e70129a62ed..0f165b268ba3b 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -697,7 +697,7 @@ test environment with: src/ci/docker/scripts/fuchsia-test-runner.py start --rust ${RUST_SRC_PATH}/install --sdk ${SDK_PATH} - --target-arch {x64,arm64} + --target-triple {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} ``` Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and diff --git a/tests/ui/async-await/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs new file mode 100644 index 0000000000000..93c69b05254dc --- /dev/null +++ b/tests/ui/async-await/future-sizes/future-as-arg.rs @@ -0,0 +1,16 @@ +// edition: 2021 +// run-pass + +async fn test(_arg: [u8; 16]) {} + +async fn use_future(fut: impl std::future::Future) { + fut.await +} + +fn main() { + let actual = std::mem::size_of_val( + &use_future(use_future(use_future(use_future(use_future(test([0; 16]))))))); + // Not using an exact number in case it slightly changes over different commits + let expected = 550; + assert!(actual > expected, "expected: >{expected}, actual: {actual}"); +} diff --git a/tests/ui/async-await/future-sizes/large-arg.rs b/tests/ui/async-await/future-sizes/large-arg.rs new file mode 100644 index 0000000000000..7e7ff9d8d00e8 --- /dev/null +++ b/tests/ui/async-await/future-sizes/large-arg.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// edition: 2021 +// build-pass +// ignore-pass + +pub async fn test() { + let _ = a([0u8; 1024]).await; +} + +pub async fn a(t: T) -> T { + b(t).await +} +async fn b(t: T) -> T { + c(t).await +} +async fn c(t: T) -> T { + t +} diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout new file mode 100644 index 0000000000000..c206d79317075 --- /dev/null +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -0,0 +1,60 @@ +print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 3075 bytes +print-type-size local `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Unresumed`: 0 bytes +print-type-size variant `Returned`: 0 bytes +print-type-size variant `Panicked`: 0 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 3074 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size local `.__awaitee`: 2050 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size field `.value`: 3075 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 3075 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 3075 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 2049 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size local `.__awaitee`: 1025 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size field `.value`: 2050 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 2050 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 2050 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size field `.value`: 1025 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 1025 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 1025 bytes +print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Ready`: 1024 bytes +print-type-size field `.0`: 1024 bytes +print-type-size variant `Pending`: 0 bytes diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed new file mode 100644 index 0000000000000..1a08470064cd7 --- /dev/null +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed @@ -0,0 +1,26 @@ +// run-rustfix +#![allow(dead_code, path_statements)] +fn foo1(s: &str) -> impl Iterator + '_ { + None.into_iter() + .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s))) + //~^ ERROR captured variable cannot escape `FnMut` closure body + //~| HELP consider adding 'move' keyword before the nested closure +} + +fn foo2(s: &str) -> impl Sized + '_ { + move |()| s.chars().map(move |c| format!("{}{}", c, s)) + //~^ ERROR lifetime may not live long enough + //~| HELP consider adding 'move' keyword before the nested closure +} + +pub struct X; +pub fn foo3<'a>( + bar: &'a X, +) -> impl Iterator + 'a { + Some(()).iter().flat_map(move |()| { + Some(()).iter().map(move |()| { bar; }) //~ ERROR captured variable cannot escape + //~^ HELP consider adding 'move' keyword before the nested closure + }) +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs index 95847d8d301a6..b93292e3589d3 100644 --- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(dead_code, path_statements)] fn foo1(s: &str) -> impl Iterator + '_ { None.into_iter() .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s))) @@ -11,4 +13,14 @@ fn foo2(s: &str) -> impl Sized + '_ { //~| HELP consider adding 'move' keyword before the nested closure } +pub struct X; +pub fn foo3<'a>( + bar: &'a X, +) -> impl Iterator + 'a { + Some(()).iter().flat_map(move |()| { + Some(()).iter().map(|()| { bar; }) //~ ERROR captured variable cannot escape + //~^ HELP consider adding 'move' keyword before the nested closure + }) +} + fn main() {} diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr index 2eae614a2f598..776c338deacf4 100644 --- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr @@ -1,5 +1,5 @@ error: captured variable cannot escape `FnMut` closure body - --> $DIR/issue-95079-missing-move-in-nested-closure.rs:3:29 + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:5:29 | LL | fn foo1(s: &str) -> impl Iterator + '_ { | - variable defined here @@ -7,7 +7,7 @@ LL | None.into_iter() LL | .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s))) | - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | - | | returns a reference to a captured variable which escapes the closure body + | | returns a closure that contains a reference to a captured variable, which then escapes the closure body | | variable captured here | inferred to be a `FnMut` closure | @@ -19,12 +19,12 @@ LL | .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s))) | ++++ error: lifetime may not live long enough - --> $DIR/issue-95079-missing-move-in-nested-closure.rs:9:15 + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:11:15 | LL | move |()| s.chars().map(|c| format!("{}{}", c, s)) | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` | | | - | | return type of closure `Map, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:9:29: 9:32]>` contains a lifetime `'2` + | | return type of closure `Map, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32]>` contains a lifetime `'2` | lifetime `'1` represents this closure's body | = note: closure implements `Fn`, so references to captured variables can't escape the closure @@ -33,5 +33,26 @@ help: consider adding 'move' keyword before the nested closure LL | move |()| s.chars().map(move |c| format!("{}{}", c, s)) | ++++ -error: aborting due to 2 previous errors +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:21:9 + | +LL | bar: &'a X, + | --- variable defined here +LL | ) -> impl Iterator + 'a { +LL | Some(()).iter().flat_map(move |()| { + | - inferred to be a `FnMut` closure +LL | Some(()).iter().map(|()| { bar; }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^^ + | | | + | | variable captured here + | returns a closure that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape +help: consider adding 'move' keyword before the nested closure + | +LL | Some(()).iter().map(move |()| { bar; }) + | ++++ + +error: aborting due to 3 previous errors diff --git a/tests/ui/fmt/format-string-wrong-order.rs b/tests/ui/fmt/format-string-wrong-order.rs new file mode 100644 index 0000000000000..0bad54023965f --- /dev/null +++ b/tests/ui/fmt/format-string-wrong-order.rs @@ -0,0 +1,15 @@ +fn main() { + let bar = 3; + format!("{?:}", bar); + //~^ ERROR invalid format string: expected format parameter to occur after `:` + format!("{?:bar}"); + //~^ ERROR invalid format string: expected format parameter to occur after `:` + format!("{?:?}", bar); + //~^ ERROR invalid format string: expected format parameter to occur after `:` + format!("{??}", bar); + //~^ ERROR invalid format string: expected `'}'`, found `'?'` + format!("{?;bar}"); + //~^ ERROR invalid format string: expected `'}'`, found `'?'` + format!("{?:#?}", bar); + //~^ ERROR invalid format string: expected format parameter to occur after `:` +} diff --git a/tests/ui/fmt/format-string-wrong-order.stderr b/tests/ui/fmt/format-string-wrong-order.stderr new file mode 100644 index 0000000000000..461af354a4e15 --- /dev/null +++ b/tests/ui/fmt/format-string-wrong-order.stderr @@ -0,0 +1,54 @@ +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:3:15 + | +LL | format!("{?:}", bar); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `:?` instead + +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:5:15 + | +LL | format!("{?:bar}"); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `bar:?` instead + +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:7:15 + | +LL | format!("{?:?}", bar); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `:?` instead + +error: invalid format string: expected `'}'`, found `'?'` + --> $DIR/format-string-wrong-order.rs:9:15 + | +LL | format!("{??}", bar); + | -^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'?'` + --> $DIR/format-string-wrong-order.rs:11:15 + | +LL | format!("{?;bar}"); + | -^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:13:15 + | +LL | format!("{?:#?}", bar); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `:?` instead + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs index 0b7b67496d6f3..e1ea38f2795df 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -68,7 +68,6 @@ fn main() { Foo:Bar::Baz => {} //~^ ERROR: expected one of //~| HELP: maybe write a path separator here - //~| ERROR: failed to resolve: `Bar` is a variant, not a module } match myfoo { Foo::Bar => {} diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr index 2050a16beb349..63b072ac4cdc6 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -2,89 +2,118 @@ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:17:12 | LL | Foo:Bar => {} - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | Foo::Bar => {} + | ~~ error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:23:17 | LL | qux::Foo:Bar => {} - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of 8 possible tokens - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Bar => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:29:12 | LL | qux:Foo::Baz => {} - | ^ + | ^-------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:35:12 | LL | qux: Foo::Baz if true => {} - | ^ + | ^ -------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Baz if true => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:40:15 | LL | if let Foo:Bar = f() { - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | if let Foo::Bar = f() { + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:48:16 | LL | ref qux: Foo::Baz => {} - | ^ + | ^ -------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | ref qux::Foo::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:57:16 | LL | mut qux: Foo::Baz => {} - | ^ + | ^ -------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | mut qux::Foo::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:68:12 | LL | Foo:Bar::Baz => {} - | ^ + | ^-------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | Foo::Bar::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:75:12 + --> $DIR/issue-87086-colon-path-sep.rs:74:12 | LL | Foo:Bar => {} - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` - -error[E0433]: failed to resolve: `Bar` is a variant, not a module - --> $DIR/issue-87086-colon-path-sep.rs:68:13 | -LL | Foo:Bar::Baz => {} - | ^^^ `Bar` is a variant, not a module +help: maybe write a path separator here + | +LL | Foo::Bar => {} + | ~~ -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/parser/type-ascription-in-pattern.rs b/tests/ui/parser/type-ascription-in-pattern.rs new file mode 100644 index 0000000000000..fec168afba1dd --- /dev/null +++ b/tests/ui/parser/type-ascription-in-pattern.rs @@ -0,0 +1,16 @@ +fn foo(x: bool) -> i32 { + match x { + x: i32 => x, //~ ERROR expected + //~^ ERROR mismatched types + true => 42., + false => 0.333, + } +} + +fn main() { + match foo(true) { + 42: i32 => (), //~ ERROR expected + _: f64 => (), //~ ERROR expected + x: i32 => (), //~ ERROR expected + } +} diff --git a/tests/ui/parser/type-ascription-in-pattern.stderr b/tests/ui/parser/type-ascription-in-pattern.stderr new file mode 100644 index 0000000000000..0919075499368 --- /dev/null +++ b/tests/ui/parser/type-ascription-in-pattern.stderr @@ -0,0 +1,54 @@ +error: expected one of `@` or `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:3:10 + | +LL | x: i32 => x, + | ^ --- specifying the type of a pattern isn't supported + | | + | expected one of `@` or `|` + | +help: maybe write a path separator here + | +LL | x::i32 => x, + | ~~ + +error: expected one of `...`, `..=`, `..`, or `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:12:11 + | +LL | 42: i32 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected one of `...`, `..=`, `..`, or `|` + +error: expected `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:13:10 + | +LL | _: f64 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected `|` + +error: expected one of `@` or `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:14:10 + | +LL | x: i32 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected one of `@` or `|` + | +help: maybe write a path separator here + | +LL | x::i32 => (), + | ~~ + +error[E0308]: mismatched types + --> $DIR/type-ascription-in-pattern.rs:3:19 + | +LL | fn foo(x: bool) -> i32 { + | --- expected `i32` because of return type +LL | match x { +LL | x: i32 => x, + | ^ expected `i32`, found `bool` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`.