From e3b499fd655083dcbe02a3504cddf1b913327418 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Jun 2023 03:47:56 +0000 Subject: [PATCH 01/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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 b7921981d5c53097329cd5ff77a4721626433fe1 Mon Sep 17 00:00:00 2001 From: bohan Date: Fri, 2 Jun 2023 09:22:57 +0800 Subject: [PATCH 10/10] fix: inline `predicate_may_hold_fatal` --- .../src/traits/coherence.rs | 7 ++++- .../src/traits/select/mod.rs | 13 --------- tests/ui/traits/issue-105231.rs | 9 ++++++ tests/ui/traits/issue-105231.stderr | 29 +++++++++++++++++++ 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 tests/ui/traits/issue-105231.rs create mode 100644 tests/ui/traits/issue-105231.stderr diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 190a78f6a8ecd..3193d00e11b2b 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -292,7 +292,12 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate) }) .chain(obligations) - .find(|o| !selcx.predicate_may_hold_fatal(o)); + .find(|o| { + selcx.evaluate_root_obligation(o).map_or( + false, // Overflow has occurred, and treat the obligation as possibly holding. + |result| !result.may_apply(), + ) + }); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5acd7b573dd9a..4c5a794bc815b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -518,19 +518,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The result is "true" if the obligation *may* hold and "false" if // we can be sure it does not. - /// Evaluates whether the obligation `obligation` can be satisfied (by any means). - pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool { - debug!(?obligation, "predicate_may_hold_fatal"); - - // This fatal query is a stopgap that should only be used in standard mode, - // where we do not expect overflow to be propagated. - assert!(self.query_mode == TraitQueryMode::Standard); - - self.evaluate_root_obligation(obligation) - .expect("Overflow should be caught earlier in standard query mode") - .may_apply() - } - /// Evaluates whether the obligation `obligation` can be satisfied /// and returns an `EvaluationResult`. This is meant for the /// *initial* call. diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs new file mode 100644 index 0000000000000..74c7afd6b9edb --- /dev/null +++ b/tests/ui/traits/issue-105231.rs @@ -0,0 +1,9 @@ +//~ ERROR overflow evaluating the requirement `A>>>>>>: Send` +struct A(B); +//~^ ERROR recursive types `A` and `B` have infinite size +struct B(A>); +trait Foo {} +impl Foo for T where T: Send {} +impl Foo for B {} + +fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr new file mode 100644 index 0000000000000..fe20c47c57a80 --- /dev/null +++ b/tests/ui/traits/issue-105231.stderr @@ -0,0 +1,29 @@ +error[E0072]: recursive types `A` and `B` have infinite size + --> $DIR/issue-105231.rs:2:1 + | +LL | struct A(B); + | ^^^^^^^^^^^ ---- recursive without indirection +LL | +LL | struct B(A>); + | ^^^^^^^^^^^ ------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ struct A(Box>); +LL | +LL ~ struct B(Box>>); + | + +error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) +note: required because it appears within the type `B>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-105231.rs:4:8 + | +LL | struct B(A>); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0072, E0275. +For more information about an error, try `rustc --explain E0072`.