From 7dd5e3c1cd5c150f16261fef6a1efb76e70f022e Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 28 Jul 2023 11:31:31 +0200 Subject: [PATCH 1/6] Add regression test for resolving `--extern libc=test.rlib` I could not find a test for this particular use case. The closest I got was `tests/ui/imports/issue-37887.rs`, but that is a regression test for a different use case. --- tests/ui/imports/resolve-other-libc.rs | 14 ++++++++++++++ tests/ui/imports/resolve-other-libc.stderr | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/ui/imports/resolve-other-libc.rs create mode 100644 tests/ui/imports/resolve-other-libc.stderr diff --git a/tests/ui/imports/resolve-other-libc.rs b/tests/ui/imports/resolve-other-libc.rs new file mode 100644 index 0000000000000..806d854ec8906 --- /dev/null +++ b/tests/ui/imports/resolve-other-libc.rs @@ -0,0 +1,14 @@ +// Regression test for https://github.com/rust-lang/rust/issues/26043 + +// compile-flags: --extern libc=test.rlib + +// The error shall NOT be something similar to the following, because it +// indicates that `libc` was wrongly resolved to `libc` shipped with the +// compiler: +// +// error[E0658]: use of unstable library feature 'rustc_private': \ +// this crate is being loaded from the sysroot +// +extern crate libc; //~ ERROR: extern location for libc does not exist: test.rlib + +fn main() {} diff --git a/tests/ui/imports/resolve-other-libc.stderr b/tests/ui/imports/resolve-other-libc.stderr new file mode 100644 index 0000000000000..e57b88e50c639 --- /dev/null +++ b/tests/ui/imports/resolve-other-libc.stderr @@ -0,0 +1,8 @@ +error: extern location for libc does not exist: test.rlib + --> $DIR/resolve-other-libc.rs:12:1 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 69b02ef4be1004847544c89e6299b2e41b5d275f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Aug 2023 18:22:33 +0200 Subject: [PATCH 2/6] fix and extend ptr_comparison test --- tests/ui/consts/ptr_comparisons.rs | 36 ++++++----------------- tests/ui/consts/ptr_comparisons.stderr | 40 -------------------------- 2 files changed, 8 insertions(+), 68 deletions(-) delete mode 100644 tests/ui/consts/ptr_comparisons.stderr diff --git a/tests/ui/consts/ptr_comparisons.rs b/tests/ui/consts/ptr_comparisons.rs index f442e61383973..a5b6cd9d2d4c1 100644 --- a/tests/ui/consts/ptr_comparisons.rs +++ b/tests/ui/consts/ptr_comparisons.rs @@ -1,8 +1,5 @@ // compile-flags: --crate-type=lib -// normalize-stderr-32bit: "8 bytes" -> "$$TWO_WORDS bytes" -// normalize-stderr-64bit: "16 bytes" -> "$$TWO_WORDS bytes" -// normalize-stderr-32bit: "size 4" -> "size $$WORD" -// normalize-stderr-64bit: "size 8" -> "size $$WORD" +// check-pass #![feature( core_intrinsics, @@ -34,30 +31,13 @@ check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0); // We want pointers to be equal to themselves, but aren't checking this yet because // there are some open questions (e.g. whether function pointers to the same function -// compare equal, they don't necessarily at runtime). -// The case tested here should work eventually, but does not work yet. +// compare equal: they don't necessarily do at runtime). check!(!, FOO as *const _, FOO as *const _); +// aside from 0, these pointers might end up pretty much anywhere. +check!(!, FOO as *const _, 1); // this one could be `ne` by taking into account alignment +check!(!, FOO as *const _, 1024); -/////////////////////////////////////////////////////////////////////////////// -// If any of the below start compiling, make sure to add a `check` test for it. -// These invocations exist as canaries so we don't forget to check that the -// behaviour of `guaranteed_eq` and `guaranteed_ne` is still correct. -// All of these try to obtain an out of bounds pointer in some manner. If we -// can create out of bounds pointers, we can offset a pointer far enough that -// at runtime it would be zero and at compile-time it would not be zero. - -const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - -const _: *const u8 = - unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; -//~^ ERROR evaluation of constant value failed -//~| out-of-bounds - -const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; -//~^ ERROR evaluation of constant value failed -//~| unable to turn pointer into raw bytes - -const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; -//~^ ERROR evaluation of constant value failed -//~| unable to turn pointer into raw bytes +// When pointers go out-of-bounds, they *might* become null, so these comparions cannot work. +check!(!, unsafe { (FOO as *const usize).wrapping_add(2) }, 0); +check!(!, unsafe { (FOO as *const usize).wrapping_sub(1) }, 0); diff --git a/tests/ui/consts/ptr_comparisons.stderr b/tests/ui/consts/ptr_comparisons.stderr deleted file mode 100644 index fea924d12e54e..0000000000000 --- a/tests/ui/consts/ptr_comparisons.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | - = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds - | -note: inside `ptr::const_ptr::::offset` - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL -note: inside `_` - --> $DIR/ptr_comparisons.rs:50:34 - | -LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:53:33 - | -LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds - -error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:57:27 - | -LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes - | - = help: this code performed an operation that depends on the underlying bytes representing a pointer - = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported - -error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:61:27 - | -LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes - | - = help: this code performed an operation that depends on the underlying bytes representing a pointer - = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0080`. From 79709e5d1afdbf9f446378541fa7b9f83ea3f144 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 31 Jul 2023 15:06:56 +0800 Subject: [PATCH 3/6] print more detailed format files and untracked files count --- src/bootstrap/format.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 3f9230aa5d59d..6d11014a7944f 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -152,6 +152,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { .map(|entry| { entry.split(' ').nth(1).expect("every git status entry should list a path") }); + let mut untracked_count = 0; for untracked_path in untracked_paths { println!("skip untracked path {untracked_path} during rustfmt invocations"); // The leading `/` makes it an exact match against the @@ -159,6 +160,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { // have `foo.rs` in the repository root it will also match // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. + untracked_count += 1; ignore_fmt.add(&format!("!/{untracked_path}")).expect(&untracked_path); } // Only check modified files locally to speed up runtime. @@ -167,13 +169,28 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { if !CiEnv::is_ci() && paths.is_empty() { match get_modified_rs_files(build) { Ok(Some(files)) => { + eprintln!("Found {:?} modified files", files); if files.len() <= 10 { for file in &files { println!("formatting modified file {file}"); } - } else { - println!("formatting {} modified files", files.len()); } + let pluralized = |count| if count > 1 { "files" } else { "file" }; + let untracked_msg = if untracked_count == 0 { + "".to_string() + } else { + format!( + ", skipped {} untracked {}", + untracked_count, + pluralized(untracked_count), + ) + }; + println!( + "formatting {} modified {}{}", + files.len(), + pluralized(files.len()), + untracked_msg + ); for file in files { ignore_fmt.add(&format!("/{file}")).expect(&file); } From 58bda4766964f93add4d03d95f0223460cf875bd Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 2 Aug 2023 06:29:32 +0800 Subject: [PATCH 4/6] fmt_override is a better name since we are also adding files to whitelist --- src/bootstrap/format.rs | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 6d11014a7944f..d658be0b8eb1c 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -113,9 +113,9 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { } let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config)); let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); - let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src); + let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { - ignore_fmt.add(&format!("!{ignore}")).expect(&ignore); + fmt_override.add(&format!("!{ignore}")).expect(&ignore); } let git_available = match Command::new("git") .arg("--version") @@ -161,7 +161,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. untracked_count += 1; - ignore_fmt.add(&format!("!/{untracked_path}")).expect(&untracked_path); + fmt_override.add(&format!("!/{untracked_path}")).expect(&untracked_path); } // Only check modified files locally to speed up runtime. // We still check all files in CI to avoid bugs in `get_modified_rs_files` letting regressions slip through; @@ -169,30 +169,30 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { if !CiEnv::is_ci() && paths.is_empty() { match get_modified_rs_files(build) { Ok(Some(files)) => { - eprintln!("Found {:?} modified files", files); if files.len() <= 10 { for file in &files { println!("formatting modified file {file}"); } - } - let pluralized = |count| if count > 1 { "files" } else { "file" }; - let untracked_msg = if untracked_count == 0 { - "".to_string() } else { - format!( - ", skipped {} untracked {}", - untracked_count, - pluralized(untracked_count), - ) - }; - println!( - "formatting {} modified {}{}", - files.len(), - pluralized(files.len()), - untracked_msg - ); + let pluralized = |count| if count > 1 { "files" } else { "file" }; + let untracked_msg = if untracked_count == 0 { + "".to_string() + } else { + format!( + ", skipped {} untracked {}", + untracked_count, + pluralized(untracked_count), + ) + }; + println!( + "formatting {} modified {}{}", + files.len(), + pluralized(files.len()), + untracked_msg + ); + } for file in files { - ignore_fmt.add(&format!("/{file}")).expect(&file); + fmt_override.add(&format!("/{file}")).expect(&file); } } Ok(None) => {} @@ -213,7 +213,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { println!("Could not find usable git. Skipping git-aware format checks"); } - let ignore_fmt = ignore_fmt.build().unwrap(); + let fmt_override = fmt_override.build().unwrap(); let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { eprintln!("./x.py fmt is not supported on this channel"); @@ -269,7 +269,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { None => WalkBuilder::new(src.clone()), } .types(matcher) - .overrides(ignore_fmt) + .overrides(fmt_override) .build_parallel(); // there is a lot of blocking involved in spawning a child process and reading files to format. From 99969d282bd853442d7539b83833816b73e642e1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Jul 2023 23:31:21 +0000 Subject: [PATCH 5/6] Use upvar_tys in more places, make it a list --- .../src/diagnostics/region_name.rs | 1 + .../src/diagnostics/var_name.rs | 4 +-- compiler/rustc_borrowck/src/type_check/mod.rs | 27 ++++++++----------- .../rustc_borrowck/src/universal_regions.rs | 11 +++----- .../src/debuginfo/metadata.rs | 14 +++------- .../src/debuginfo/metadata/enums/mod.rs | 1 + .../src/transform/validate.rs | 5 ++-- .../rustc_infer/src/infer/opaque_types.rs | 8 ++++-- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +-- compiler/rustc_middle/src/ty/sty.rs | 26 +++++++----------- .../rustc_mir_dataflow/src/elaborate_drops.rs | 10 ++----- compiler/rustc_mir_transform/src/generator.rs | 4 +-- .../src/traits/query/dropck_outlives.rs | 6 ++--- .../src/traits/select/mod.rs | 5 ++-- compiler/rustc_ty_utils/src/layout.rs | 8 ++++-- compiler/rustc_ty_utils/src/needs_drop.rs | 8 ++++-- 17 files changed, 66 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 9cad8fa53186c..be6eb2d1d1219 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -886,6 +886,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .universal_regions() .defining_ty .upvar_tys() + .iter() .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region)) { let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 98418e2372f0e..8832d345df2ca 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -43,7 +43,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr: RegionVid, ) -> Option { let upvar_index = - self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { + self.universal_regions().defining_ty.upvar_tys().iter().position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}"); tcx.any_free_region_meets(&upvar_ty, |r| { let r = r.as_var(); @@ -52,7 +52,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) })?; - let upvar_ty = self.universal_regions().defining_ty.upvar_tys().nth(upvar_index); + let upvar_ty = self.universal_regions().defining_ty.upvar_tys().get(upvar_index); debug!( "get_upvar_index_for_region: found {fr:?} in upvar {upvar_index} which has type {upvar_ty:?}", diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index fd4a3ec1a5e3d..abb11ce739689 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -791,25 +791,20 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { (adt_def.variant(FIRST_VARIANT), args) } ty::Closure(_, args) => { - return match args - .as_closure() - .tupled_upvars_ty() - .tuple_fields() - .get(field.index()) - { + return match args.as_closure().upvar_tys().get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), }; } ty::Generator(_, args, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match args.as_generator().prefix_tys().nth(field.index()) { - Some(ty) => Ok(ty), + return match args.as_generator().prefix_tys().get(field.index()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), }; } @@ -1772,10 +1767,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } AggregateKind::Closure(_, args) => { - match args.as_closure().upvar_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + match args.as_closure().upvar_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), } } @@ -1783,10 +1778,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match args.as_generator().prefix_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + match args.as_generator().prefix_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index a751a9732f016..56945f43fcda6 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -12,7 +12,6 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. -use either::Either; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir as hir; @@ -115,14 +114,12 @@ impl<'tcx> DefiningTy<'tcx> { /// not a closure or generator, there are no upvars, and hence it /// will be an empty list. The order of types in this list will /// match up with the upvar order in the HIR, typesystem, and MIR. - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx ty::List> { match self { - DefiningTy::Closure(_, args) => Either::Left(args.as_closure().upvar_tys()), - DefiningTy::Generator(_, args, _) => { - Either::Right(Either::Left(args.as_generator().upvar_tys())) - } + DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), + DefiningTy::Generator(_, args, _) => args.as_generator().upvar_tys(), DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { - Either::Right(Either::Right(iter::empty())) + ty::List::empty() } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 40f0bcfdf58a4..f8cbcbd5ec852 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -990,14 +990,8 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( closure_or_generator_di_node: &'ll DIType, ) -> SmallVec<&'ll DIType> { let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() { - ty::Generator(def_id, args, _) => { - let upvar_tys: SmallVec<_> = args.as_generator().prefix_tys().collect(); - (def_id, upvar_tys) - } - ty::Closure(def_id, args) => { - let upvar_tys: SmallVec<_> = args.as_closure().upvar_tys().collect(); - (def_id, upvar_tys) - } + ty::Generator(def_id, args, _) => (def_id, args.as_generator().prefix_tys()), + ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()), _ => { bug!( "build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}", @@ -1007,9 +1001,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( }; debug_assert!( - up_var_tys - .iter() - .all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) + up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) ); let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index b4beb80ca8b5b..d3239d5c358f5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -379,6 +379,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>( // Fields that are common to all states let common_fields: SmallVec<_> = generator_args .prefix_tys() + .iter() .zip(common_upvar_names) .enumerate() .map(|(index, (upvar_ty, upvar_name))| { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 31effadd2c265..83004492c8bf0 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } ty::Closure(_, args) => { let args = args.as_closure(); - let Some(f_ty) = args.upvar_tys().nth(f.as_usize()) else { + let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else { fail_out_of_bounds(self, location); return; }; @@ -667,7 +667,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { f_ty.ty } else { - let Some(f_ty) = args.as_generator().prefix_tys().nth(f.index()) else { + let Some(&f_ty) = args.as_generator().prefix_tys().get(f.index()) + else { fail_out_of_bounds(self, location); return; }; diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 9c90b7045862f..a6052f52917b3 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -448,7 +448,9 @@ where ty::Closure(_, ref args) => { // Skip lifetime parameters of the enclosing item(s) - args.as_closure().tupled_upvars_ty().visit_with(self); + for upvar in args.as_closure().upvar_tys() { + upvar.visit_with(self); + } args.as_closure().sig_as_fn_ptr_ty().visit_with(self); } @@ -456,7 +458,9 @@ where // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - args.as_generator().tupled_upvars_ty().visit_with(self); + for upvar in args.as_generator().upvar_tys() { + upvar.visit_with(self); + } args.as_generator().return_ty().visit_with(self); args.as_generator().yield_ty().visit_with(self); args.as_generator().resume_ty().visit_with(self); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0f7bed0845ced..df39103bc1979 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -911,7 +911,7 @@ where if i == tag_field { return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } - TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap()) + TyMaybeWithLayout::Ty(args.as_generator().prefix_tys()[i]) } }, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f146f8aa8b414..290c4a48ab0f1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -827,7 +827,7 @@ pub trait PrettyPrinter<'tcx>: if !args.as_generator().is_valid() { p!("unavailable"); } else { - self = self.comma_sep(args.as_generator().upvar_tys())?; + self = self.comma_sep(args.as_generator().upvar_tys().iter())?; } p!(")"); @@ -900,7 +900,7 @@ pub trait PrettyPrinter<'tcx>: print(args.as_closure().sig_as_fn_ptr_ty()) ); p!(" upvar_tys=("); - self = self.comma_sep(args.as_closure().upvar_tys())?; + self = self.comma_sep(args.as_closure().upvar_tys().iter())?; p!(")"); } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3e023ccdead67..1e5f64df9a598 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -296,15 +296,13 @@ impl<'tcx> ClosureArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List> { match self.tupled_upvars_ty().kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } /// Returns the tuple type representing the upvars for this closure. @@ -436,15 +434,13 @@ impl<'tcx> GeneratorArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List> { match self.tupled_upvars_ty().kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } /// Returns the tuple type representing the upvars for this generator. @@ -576,7 +572,7 @@ impl<'tcx> GeneratorArgs<'tcx> { /// This is the types of the fields of a generator which are not stored in a /// variant. #[inline] - pub fn prefix_tys(self) -> impl Iterator> { + pub fn prefix_tys(self) -> &'tcx List> { self.upvar_tys() } } @@ -592,20 +588,18 @@ impl<'tcx> UpvarArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List> { let tupled_tys = match self { UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(), }; match tupled_tys.kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } #[inline] diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 1d7d905c937d4..9e02b027182a5 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -860,20 +860,14 @@ where fn open_drop(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); match ty.kind() { - ty::Closure(_, args) => { - let tys: Vec<_> = args.as_closure().upvar_tys().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Closure(_, args) => self.open_drop_for_tuple(&args.as_closure().upvar_tys()), // Note that `elaborate_drops` only drops the upvars of a generator, // and this is ok because `open_drop` here can only be reached // within that own generator's resume function. // This should only happen for the self argument on the resume function. // It effectively only contains upvars until the generator transformation runs. // See librustc_body/transform/generator.rs for more details. - ty::Generator(_, args, _) => { - let tys: Vec<_> = args.as_generator().upvar_tys().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Generator(_, args, _) => self.open_drop_for_tuple(&args.as_generator().upvar_tys()), ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 669135f80bc51..797a1a86846f6 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -856,7 +856,7 @@ fn sanitize_witness<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, witness: Ty<'tcx>, - upvars: Vec>, + upvars: &'tcx ty::List>, layout: &GeneratorLayout<'tcx>, ) { let did = body.source.def_id(); @@ -1471,7 +1471,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let args = args.as_generator(); ( args.discr_ty(tcx), - args.upvar_tys().collect::>(), + args.upvar_tys(), args.witness(), movability == hir::Movability::Movable, ) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index ef989d8c9d689..9484a50e3a913 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -291,9 +291,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( return Err(NoSolution); } - constraints.outlives.extend( - args.as_generator().upvar_tys().map(|t| -> ty::GenericArg<'tcx> { t.into() }), - ); + constraints + .outlives + .extend(args.as_generator().upvar_tys().iter().map(ty::GenericArg::from)); constraints.outlives.push(args.as_generator().resume_ty().into()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c29696bc817f7..1f3cea351bbf5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2169,7 +2169,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let all = args .as_generator() .upvar_tys() - .chain(iter::once(args.as_generator().witness())) + .iter() + .chain([args.as_generator().witness()]) .collect::>(); Where(obligation.predicate.rebind(all)) } @@ -2210,7 +2211,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Not yet resolved. Ambiguous } else { - Where(obligation.predicate.rebind(args.as_closure().upvar_tys().collect())) + Where(obligation.predicate.rebind(args.as_closure().upvar_tys().to_vec())) } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 3500c2cc37003..6b4273c03e4fa 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -317,7 +317,9 @@ fn layout_of_uncached<'tcx>( ty::Closure(_, ref args) => { let tys = args.as_closure().upvar_tys(); univariant( - &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::>()?, + &tys.iter() + .map(|ty| Ok(cx.layout_of(ty)?.layout)) + .try_collect::>()?, &ReprOptions::default(), StructKind::AlwaysSized, )? @@ -729,7 +731,7 @@ fn generator_layout<'tcx>( // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let tag_index = args.as_generator().prefix_tys().count(); + let tag_index = args.as_generator().prefix_tys().len(); // `info.variant_fields` already accounts for the reserved variants, so no need to add them. let max_discr = (info.variant_fields.len() - 1) as u128; @@ -748,6 +750,7 @@ fn generator_layout<'tcx>( let prefix_layouts = args .as_generator() .prefix_tys() + .iter() .map(|ty| Ok(cx.layout_of(ty)?.layout)) .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) @@ -1062,6 +1065,7 @@ fn variant_info_for_generator<'tcx>( let upvar_fields: Vec<_> = args .as_generator() .upvar_tys() + .iter() .zip(upvar_names) .enumerate() .map(|(field_idx, (_, name))| { diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index f89558a45999f..34fd31e49e10d 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -120,12 +120,16 @@ where _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), ty::Closure(_, args) => { - queue_type(self, args.as_closure().tupled_upvars_ty()); + for upvar in args.as_closure().upvar_tys() { + queue_type(self, upvar); + } } ty::Generator(def_id, args, _) => { let args = args.as_generator(); - queue_type(self, args.tupled_upvars_ty()); + for upvar in args.upvar_tys() { + queue_type(self, upvar); + } let witness = args.witness(); let interior_tys = match witness.kind() { From 90db1132c76f0c7dae0bee33cbadbb1390a5881f Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 2 Aug 2023 16:21:45 +0800 Subject: [PATCH 6/6] get auto traits for parallel rustc Signed-off-by: SparrowLii --- compiler/rustc_ast/src/format.rs | 6 ------ src/librustdoc/clean/utils.rs | 6 ------ 2 files changed, 12 deletions(-) diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index 699946f307b50..805596ff00a98 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -67,12 +67,6 @@ pub struct FormatArguments { names: FxHashMap, } -// FIXME: Rustdoc has trouble proving Send/Sync for this. See #106930. -#[cfg(parallel_compiler)] -unsafe impl Sync for FormatArguments {} -#[cfg(parallel_compiler)] -unsafe impl Send for FormatArguments {} - impl FormatArguments { pub fn new() -> Self { Self { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 5c8db3b87744c..43d8bcae8e2a1 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -480,12 +480,6 @@ pub(crate) fn get_auto_trait_and_blanket_impls( cx: &mut DocContext<'_>, item_def_id: DefId, ) -> impl Iterator { - // FIXME: To be removed once `parallel_compiler` bugs are fixed! - // More information in . - if cfg!(parallel_compiler) { - return vec![].into_iter().chain(vec![].into_iter()); - } - let auto_impls = cx .sess() .prof