From e3b499fd655083dcbe02a3504cddf1b913327418 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Jun 2023 03:47:56 +0000 Subject: [PATCH 01/12] Instantiate closure synthetic substs in root universe --- compiler/rustc_hir_typeck/src/closure.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 ++++ tests/ui/traits/new-solver/closure-substs-ambiguity.rs | 7 +++++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/new-solver/closure-substs-ambiguity.rs diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 9659a0ec13d40..dce426ca2db6a 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -98,7 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), ); - let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { + let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::ClosureSynthetic, span: self.tcx.def_span(expr_def_id), }); @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Create a type variable (for now) to represent the closure kind. // It will be unified during the upvar inference phase (`upvar.rs`) - None => self.next_ty_var(TypeVariableOrigin { + None => self.next_root_ty_var(TypeVariableOrigin { // FIXME(eddyb) distinguish closure kind inference variables from the rest. kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 67f45f9aa3f0d..630878bbf0c60 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -189,6 +189,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn errors_reported_since_creation(&self) -> bool { self.tcx.sess.err_count() > self.err_count_on_creation } + + pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { + self.tcx.mk_ty_var(self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT)) + } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { diff --git a/tests/ui/traits/new-solver/closure-substs-ambiguity.rs b/tests/ui/traits/new-solver/closure-substs-ambiguity.rs new file mode 100644 index 0000000000000..48432f4020f87 --- /dev/null +++ b/tests/ui/traits/new-solver/closure-substs-ambiguity.rs @@ -0,0 +1,7 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +fn main() { + let mut x: Vec<_> = vec![]; + x.extend(Some(1i32).into_iter().map(|x| x)); +} From 3b9b4e5e3d6b45be6d355f0685eb70d99c3ab50a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Jun 2023 22:15:46 +0200 Subject: [PATCH 02/12] reorder attributes to make miri-test-libstd work again --- library/alloc/src/lib.rs | 10 +++++----- library/std/src/lib.rs | 13 +++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 59fa91c1066dc..967ad3a0e6901 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -56,6 +56,11 @@ //! [`Rc`]: rc //! [`RefCell`]: core::cell +// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] +// #![allow(unused_attributes)] #![stable(feature = "alloc", since = "1.36.0")] #![doc( @@ -75,11 +80,6 @@ ))] #![no_std] #![needs_allocator] -// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be -// able to "empty" this crate. See . -// rustc itself never sets the feature, so this line has no affect there. -#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] -// // Lints: #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d53f1a2b2fff1..da08c018d0e36 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -188,6 +188,13 @@ //! [array]: prim@array //! [slice]: prim@slice +// To run std tests without x.py without ending up with two copies of std, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] +// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies. +#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))] +// #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))] #![doc( @@ -202,12 +209,6 @@ no_global_oom_handling, not(no_global_oom_handling) ))] -// To run std tests without x.py without ending up with two copies of std, Miri needs to be -// able to "empty" this crate. See . -// rustc itself never sets the feature, so this line has no affect there. -#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] -// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies. -#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))] // Don't link to std. We are std. #![no_std] // Tell the compiler to link to either panic_abort or panic_unwind From 513f28db0a540725bc41f080a0f52973af67c3db Mon Sep 17 00:00:00 2001 From: MikaelUrankar Date: Tue, 13 Jun 2023 13:14:06 +0200 Subject: [PATCH 03/12] Fix building the documentation on FreeBSD. It fixes the following error: error[E0412]: cannot find type `sockcred2` in module `libc` --> library/std/src/os/unix/net/ancillary.rs:211:29 | 211 | pub struct SocketCred(libc::sockcred2); | ^^^^^^^^^ not found in `libc` --- library/std/src/os/unix/net/ancillary.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 7565fbc0d099c..814f1c7c2838e 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -17,6 +17,7 @@ mod libc { pub use libc::c_int; pub struct ucred; pub struct cmsghdr; + pub struct sockcred2; pub type pid_t = i32; pub type gid_t = u32; pub type uid_t = u32; From 01377e8064a5b3d987b177c16e18da4bffec03a4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 13 Jun 2023 22:10:51 +0000 Subject: [PATCH 04/12] opportunistically resolve regions --- compiler/rustc_middle/src/infer/canonical.rs | 41 +++++++++++++++---- .../src/solve/canonicalize.rs | 21 +++++++++- .../src/solve/eval_ctxt.rs | 5 ++- .../opportunistic-region-resolve.rs | 19 +++++++++ 4 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 tests/ui/traits/new-solver/opportunistic-region-resolve.rs diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 29dae67bfca72..1b19ed9ad148b 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -82,15 +82,40 @@ impl CanonicalVarValues<'_> { } pub fn is_identity_modulo_regions(&self) -> bool { - self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { - ty::GenericArgKind::Lifetime(_) => true, - ty::GenericArgKind::Type(ty) => { - matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) - } - ty::GenericArgKind::Const(ct) => { - matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv) + let mut var = ty::BoundVar::from_u32(0); + for arg in self.var_values { + match arg.unpack() { + ty::GenericArgKind::Lifetime(r) => { + if let ty::ReLateBound(ty::INNERMOST, br) = *r + && var == br.var + { + var = var + 1; + } else { + // It's ok if this region var isn't unique + } + }, + ty::GenericArgKind::Type(ty) => { + if let ty::Bound(ty::INNERMOST, bt) = *ty.kind() + && var == bt.var + { + var = var + 1; + } else { + return false; + } + } + ty::GenericArgKind::Const(ct) => { + if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind() + && var == bc + { + var = var + 1; + } else { + return false; + } + } } - }) + } + + true } } diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 29bdb5ff67da8..05248cb9d1782 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -208,8 +208,25 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - let r = self.infcx.shallow_resolve(r); + fn fold_region(&mut self, mut r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match self.canonicalize_mode { + CanonicalizeMode::Input => { + // Don't resolve infer vars in input, since it affects + // caching and may cause trait selection bugs which rely + // on regions to be equal. + } + CanonicalizeMode::Response { .. } => { + if let ty::ReVar(vid) = *r { + r = self + .infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(self.infcx.tcx, vid); + } + } + } + let kind = match *r { ty::ReLateBound(..) => return r, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index e01187bcd3c2a..35fe38c5317d7 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -263,7 +263,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let (_orig_values, canonical_goal) = self.canonicalize_goal(goal); let new_canonical_response = EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?; - if !new_canonical_response.value.var_values.is_identity() { + // We only check for modulo regions as we convert all regions in + // the input to new existentials, even if they're expected to be + // `'static` or a placeholder region. + if !new_canonical_response.value.var_values.is_identity_modulo_regions() { bug!( "unstable result: re-canonicalized goal={canonical_goal:#?} \ first_response={canonical_response:#?} \ diff --git a/tests/ui/traits/new-solver/opportunistic-region-resolve.rs b/tests/ui/traits/new-solver/opportunistic-region-resolve.rs new file mode 100644 index 0000000000000..2610789cd485a --- /dev/null +++ b/tests/ui/traits/new-solver/opportunistic-region-resolve.rs @@ -0,0 +1,19 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(rustc_attrs)] + +#[rustc_coinductive] +trait Trait {} + +#[rustc_coinductive] +trait Indirect {} +impl Indirect for T {} + +impl<'a> Trait for &'a () where &'a (): Indirect {} + +fn impls_trait() {} + +fn main() { + impls_trait::<&'static ()>(); +} From 9d7295f0be2c90a98b6a7ce5f24ddef96dea10b7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 09:37:36 +1000 Subject: [PATCH 05/12] Move dead CGU marking code out of `partition`. The other major steps in `partition` have their own function, so it's nice for this one to be likewise. --- .../rustc_monomorphize/src/partitioning.rs | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index ebcc3b0399973..2a314727744f8 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -197,34 +197,8 @@ where let instrument_dead_code = tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions(); - if instrument_dead_code { - assert!( - codegen_units.len() > 0, - "There must be at least one CGU that code coverage data can be generated in." - ); - - // Find the smallest CGU that has exported symbols and put the dead - // function stubs in that CGU. We look for exported symbols to increase - // the likelihood the linker won't throw away the dead functions. - // FIXME(#92165): In order to truly resolve this, we need to make sure - // the object file (CGU) containing the dead function stubs is included - // in the final binary. This will probably require forcing these - // function symbols to be included via `-u` or `/include` linker args. - let mut cgus: Vec<_> = codegen_units.iter_mut().collect(); - cgus.sort_by_key(|cgu| cgu.size_estimate()); - - let dead_code_cgu = - if let Some(cgu) = cgus.into_iter().rev().find(|cgu| { - cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External) - }) { - cgu - } else { - // If there are no CGUs that have externally linked items, - // then we just pick the first CGU as a fallback. - &mut codegen_units[0] - }; - dead_code_cgu.make_code_coverage_dead_code_cgu(); + mark_code_coverage_dead_code_cgu(&mut codegen_units); } // Ensure CGUs are sorted by name, so that we get deterministic results. @@ -545,6 +519,33 @@ fn internalize_symbols<'tcx>( } } +fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx>]) { + assert!(!codegen_units.is_empty()); + + // Find the smallest CGU that has exported symbols and put the dead + // function stubs in that CGU. We look for exported symbols to increase + // the likelihood the linker won't throw away the dead functions. + // FIXME(#92165): In order to truly resolve this, we need to make sure + // the object file (CGU) containing the dead function stubs is included + // in the final binary. This will probably require forcing these + // function symbols to be included via `-u` or `/include` linker args. + let mut cgus: Vec<&mut CodegenUnit<'tcx>> = codegen_units.iter_mut().collect(); + cgus.sort_by_key(|cgu| cgu.size_estimate()); + + let dead_code_cgu = if let Some(cgu) = cgus + .into_iter() + .rev() + .find(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) + { + cgu + } else { + // If there are no CGUs that have externally linked items, + // then we just pick the first CGU as a fallback. + &mut codegen_units[0] + }; + dead_code_cgu.make_code_coverage_dead_code_cgu(); +} + fn characteristic_def_id_of_mono_item<'tcx>( tcx: TyCtxt<'tcx>, mono_item: MonoItem<'tcx>, From 57a7c8f577abd12ef4bb404448c42d794a76c690 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 09:50:48 +1000 Subject: [PATCH 06/12] Fix bug in `mark_code_coverage_dead_code_cgus`. The comment says "Find the smallest CGU that has exported symbols and put the dead function stubs in that CGU". But the code sorts the CGUs by size (smallest first) and then searches them in reverse order, which means it will find the *largest* CGU that has exported symbols. The erroneous code was introduced in #92142. This commit changes it to use a simpler search, avoiding the sort, and fixes the bug in the process. --- .../rustc_monomorphize/src/partitioning.rs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 2a314727744f8..de57992beac33 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -529,20 +529,15 @@ fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx> // the object file (CGU) containing the dead function stubs is included // in the final binary. This will probably require forcing these // function symbols to be included via `-u` or `/include` linker args. - let mut cgus: Vec<&mut CodegenUnit<'tcx>> = codegen_units.iter_mut().collect(); - cgus.sort_by_key(|cgu| cgu.size_estimate()); + let dead_code_cgu = codegen_units + .iter_mut() + .filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) + .min_by_key(|cgu| cgu.size_estimate()); + + // If there are no CGUs that have externally linked items, then we just + // pick the first CGU as a fallback. + let dead_code_cgu = if let Some(cgu) = dead_code_cgu { cgu } else { &mut codegen_units[0] }; - let dead_code_cgu = if let Some(cgu) = cgus - .into_iter() - .rev() - .find(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) - { - cgu - } else { - // If there are no CGUs that have externally linked items, - // then we just pick the first CGU as a fallback. - &mut codegen_units[0] - }; dead_code_cgu.make_code_coverage_dead_code_cgu(); } From e414d25e94b8cfc29ee2ad44af10e2fd6644d36b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 10:00:55 +1000 Subject: [PATCH 07/12] Make `partition` more consistent. Always put the `create_size_estimate` calls and `debug_dump` calls within a timed scopes. This makes the four main steps look more similar to each other. --- .../rustc_monomorphize/src/partitioning.rs | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index de57992beac33..a74ba8e4a4be9 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -155,14 +155,16 @@ where // functions and statics defined in the local crate. let PlacedRootMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); - place_root_mono_items(cx, mono_items) - }; + let mut placed = place_root_mono_items(cx, mono_items); - for cgu in &mut codegen_units { - cgu.create_size_estimate(tcx); - } + for cgu in &mut placed.codegen_units { + cgu.create_size_estimate(tcx); + } - debug_dump(tcx, "ROOTS", &codegen_units, unique_inlined_stats); + debug_dump(tcx, "ROOTS", &placed.codegen_units, placed.unique_inlined_stats); + + placed + }; // Merge until we have at most `max_cgu_count` codegen units. // `merge_codegen_units` is responsible for updating the CGU size @@ -179,22 +181,25 @@ where // local functions the definition of which is marked with `#[inline]`. { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items"); - place_inlined_mono_items(cx, &mut codegen_units) - }; + place_inlined_mono_items(cx, &mut codegen_units); - for cgu in &mut codegen_units { - cgu.create_size_estimate(tcx); - } + for cgu in &mut codegen_units { + cgu.create_size_estimate(tcx); + } - debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats); + debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats); + } // Next we try to make as many symbols "internal" as possible, so LLVM has // more freedom to optimize. if !tcx.sess.link_dead_code() { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); internalize_symbols(cx, &mut codegen_units, internalization_candidates); + + debug_dump(tcx, "INTERNALIZE", &codegen_units, unique_inlined_stats); } + // Mark one CGU for dead code, if necessary. let instrument_dead_code = tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions(); if instrument_dead_code { @@ -204,8 +209,6 @@ where // Ensure CGUs are sorted by name, so that we get deterministic results. assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str())))); - debug_dump(tcx, "FINAL", &codegen_units, unique_inlined_stats); - codegen_units } From 9ef580fa6f2b5019b35e6a9cf979f6f13d21de00 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 01:55:30 +0000 Subject: [PATCH 08/12] Handle interpolated literal errors --- compiler/rustc_parse/src/parser/expr.rs | 9 +++------ tests/ui/parser/lit-err-in-macro.rs | 10 ++++++++++ tests/ui/parser/lit-err-in-macro.stderr | 8 ++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 tests/ui/parser/lit-err-in-macro.rs create mode 100644 tests/ui/parser/lit-err-in-macro.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cea2a71c98821..f00bc54589a7f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2023,17 +2023,14 @@ impl<'a> Parser<'a> { let recovered = self.recover_after_dot(); let token = recovered.as_ref().unwrap_or(&self.token); match token::Lit::from_token(token) { - Some(token_lit) => { - match MetaItemLit::from_token_lit(token_lit, token.span) { + Some(lit) => { + match MetaItemLit::from_token_lit(lit, token.span) { Ok(lit) => { self.bump(); Some(lit) } Err(err) => { - let span = token.span; - let token::Literal(lit) = token.kind else { - unreachable!(); - }; + let span = token.uninterpolated_span(); self.bump(); report_lit_error(&self.sess, err, lit, span); // Pack possible quotes and prefixes from the original literal into diff --git a/tests/ui/parser/lit-err-in-macro.rs b/tests/ui/parser/lit-err-in-macro.rs new file mode 100644 index 0000000000000..cff8ee6b40ca6 --- /dev/null +++ b/tests/ui/parser/lit-err-in-macro.rs @@ -0,0 +1,10 @@ +macro_rules! f { + ($abi:literal) => { + extern $abi fn f() {} + } +} + +f!("Foo"__); +//~^ ERROR suffixes on string literals are invalid + +fn main() {} diff --git a/tests/ui/parser/lit-err-in-macro.stderr b/tests/ui/parser/lit-err-in-macro.stderr new file mode 100644 index 0000000000000..a61fb5c85d492 --- /dev/null +++ b/tests/ui/parser/lit-err-in-macro.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/lit-err-in-macro.rs:7:4 + | +LL | f!("Foo"__); + | ^^^^^^^ invalid suffix `__` + +error: aborting due to previous error + From 2af5f2276d0cc2b34f2304415b1fbd6ccd42bc49 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 18:58:23 +1000 Subject: [PATCH 09/12] Merge CGUs in a nicer way. --- compiler/rustc_monomorphize/src/partitioning.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index a74ba8e4a4be9..531644f0b8490 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -340,9 +340,7 @@ fn merge_codegen_units<'tcx>( // Move the mono-items from `smallest` to `second_smallest` second_smallest.modify_size_estimate(smallest.size_estimate()); - for (k, v) in smallest.items_mut().drain() { - second_smallest.items_mut().insert(k, v); - } + second_smallest.items_mut().extend(smallest.items_mut().drain()); // Record that `second_smallest` now contains all the stuff that was // in `smallest` before. From b4ba7c4f93c1279c55271404937f064a78355e2f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 16:18:38 +0000 Subject: [PATCH 10/12] Make assumption functions in new solver take clause --- compiler/rustc_middle/src/ty/mod.rs | 66 +++++++++++++++++++ .../src/solve/assembly/mod.rs | 40 ++++++----- .../src/solve/project_goals.rs | 8 +-- .../src/solve/trait_goals.rs | 10 +-- 4 files changed, 98 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 72341e656e29e..ff5d99794f1e2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -586,6 +586,24 @@ pub enum Clause<'tcx> { ConstArgHasType(Const<'tcx>, Ty<'tcx>), } +impl<'tcx> Binder<'tcx, Clause<'tcx>> { + pub fn as_trait_clause(self) -> Option>> { + if let ty::Clause::Trait(trait_clause) = self.skip_binder() { + Some(self.rebind(trait_clause)) + } else { + None + } + } + + pub fn as_projection_clause(self) -> Option>> { + if let ty::Clause::Projection(projection_clause) = self.skip_binder() { + Some(self.rebind(projection_clause)) + } else { + None + } + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub enum PredicateKind<'tcx> { @@ -1203,6 +1221,17 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + Binder::dummy(Clause::Trait(TraitPredicate { + trait_ref: self, + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, + })) + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1211,6 +1240,14 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { @@ -1240,6 +1277,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + self.map_bound(|p| Clause::Trait(p)) + } +} + impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) @@ -1258,6 +1301,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + self.map_bound(|p| Clause::Projection(p)) + } +} + impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx) @@ -1327,6 +1376,23 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeWellFormedFromEnv(..) => None, } } + + pub fn as_clause(self) -> Option>> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(clause) => Some(predicate.rebind(clause)), + PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::WellFormed(..) + | PredicateKind::ObjectSafe(..) + | PredicateKind::ClosureKind(..) + | PredicateKind::ConstEvaluatable(..) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous + | PredicateKind::TypeWellFormedFromEnv(..) => None, + } + } } /// Represents the bounds declared on a particular set of type diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 1b749b9c854cd..e6eddf24844cf 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -105,7 +105,7 @@ pub(super) trait GoalKind<'tcx>: fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx>; @@ -115,7 +115,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, requirements: impl IntoIterator>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { @@ -131,7 +131,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_alias_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { ecx.validate_alias_bound_self_from_param_env(goal) @@ -144,7 +144,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_object_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { let tcx = ecx.tcx(); @@ -467,11 +467,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec>, ) { for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - match G::consider_implied_clause(self, goal, assumption, []) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_implied_clause(self, goal, clause, []) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } @@ -517,11 +519,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs) { - match G::consider_alias_bound_candidate(self, goal, assumption) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_alias_bound_candidate(self, goal, clause) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } @@ -675,18 +679,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // projection predicates that we reach by elaborating the principal trait ref, // since that'll cause ambiguity. // - // We can remove this when we have implemented intersections in responses. + // We can remove this when we have implemented lifetime intersections in responses. if assumption.to_opt_poly_projection_pred().is_some() && !own_bounds.contains(&assumption) { continue; } - match G::consider_object_bound_candidate(self, goal, assumption) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_object_bound_candidate(self, goal, clause) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 242f9ba87473f..8303bab4c36f3 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -105,15 +105,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { - if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred() - && poly_projection_pred.projection_def_id() == goal.predicate.def_id() + if let Some(projection_pred) = assumption.as_projection_clause() + && projection_pred.projection_def_id() == goal.predicate.def_id() { ecx.probe(|ecx| { let assumption_projection_pred = - ecx.instantiate_binder_with_infer(poly_projection_pred); + ecx.instantiate_binder_with_infer(projection_pred); ecx.eq( goal.param_env, goal.predicate.projection_ty, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index f722f281314e6..60cf386a289f9 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -81,17 +81,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { - if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() - && poly_trait_pred.def_id() == goal.predicate.def_id() - && poly_trait_pred.polarity() == goal.predicate.polarity + if let Some(trait_clause) = assumption.as_trait_clause() + && trait_clause.def_id() == goal.predicate.def_id() + && trait_clause.polarity() == goal.predicate.polarity { // FIXME: Constness ecx.probe(|ecx| { let assumption_trait_pred = - ecx.instantiate_binder_with_infer(poly_trait_pred); + ecx.instantiate_binder_with_infer(trait_clause); ecx.eq( goal.param_env, goal.predicate.trait_ref, From dabcfff40df5b1edbfca8bd808250f0130c81b7f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 15 Jun 2023 18:02:55 -0400 Subject: [PATCH 11/12] Disable alignment checks on i686-pc-windows-msvc --- .../src/check_alignment.rs | 3 +++ ...ir_alignment_check_i686-pc-windows-msvc.rs | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 1fe8ea0789286..d7141b91bc135 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -14,6 +14,9 @@ pub struct CheckAlignment; impl<'tcx> MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { + if sess.target.llvm_target == "i686-pc-windows-msvc" { + return false; + } sess.opts.debug_assertions } diff --git a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs b/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs new file mode 100644 index 0000000000000..56388c1047e9a --- /dev/null +++ b/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs @@ -0,0 +1,21 @@ +// run-pass +// only-i686-pc-windows-msvc +// compile-flags: -Copt-level=0 -Cdebug-assertions=yes + +// MSVC isn't sure if on 32-bit Windows its u64 type is 8-byte-aligned or 4-byte-aligned. +// So this test ensures that on i686-pc-windows-msvc, we do not insert a runtime check +// that will fail on dereferencing of a pointer to u64 which is not 8-byte-aligned but is +// 4-byte-aligned. + +#![feature(strict_provenance)] + +fn main() { + let mut x = [0u64; 2]; + let ptr: *mut u8 = x.as_mut_ptr().cast::(); + unsafe { + let misaligned = ptr.add(4).cast::(); + assert!(misaligned.addr() % 8 != 0); + assert!(misaligned.addr() % 4 == 0); + *misaligned = 42; + } +} From 55d680b4128007c34a328ffc3e4346ff6ae1d9cd Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 15 Jun 2023 19:48:06 -0400 Subject: [PATCH 12/12] Update compiler/rustc_mir_transform/src/check_alignment.rs --- compiler/rustc_mir_transform/src/check_alignment.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index d7141b91bc135..ea07806887ae8 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -14,6 +14,7 @@ pub struct CheckAlignment; impl<'tcx> MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { + // FIXME(#112480) MSVC and rustc disagree on minimum stack alignment on x86 Windows if sess.target.llvm_target == "i686-pc-windows-msvc" { return false; }