From 318be2bee9259852bc95728269916a45f59fa5aa Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 23 Feb 2023 23:29:10 -0500 Subject: [PATCH 01/11] Stabilize atomic_as_ptr --- library/core/src/sync/atomic.rs | 13 +++++++------ library/std/src/lib.rs | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 00bcaf3e18c3d..c79b9801a9d33 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -916,6 +916,7 @@ impl AtomicBool { /// ```ignore (extern-declaration) /// # fn main() { /// use std::sync::atomic::AtomicBool; + /// /// extern "C" { /// fn my_atomic_op(arg: *mut bool); /// } @@ -927,7 +928,8 @@ impl AtomicBool { /// # } /// ``` #[inline] - #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] + #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")] pub const fn as_ptr(&self) -> *mut bool { self.v.get().cast() } @@ -1802,7 +1804,6 @@ impl AtomicPtr { /// # Examples /// /// ```ignore (extern-declaration) - /// #![feature(atomic_mut_ptr)] /// use std::sync::atomic::AtomicPtr; /// /// extern "C" { @@ -1818,7 +1819,8 @@ impl AtomicPtr { /// } /// ``` #[inline] - #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] + #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")] pub const fn as_ptr(&self) -> *mut *mut T { self.p.get() } @@ -2724,9 +2726,8 @@ macro_rules! atomic_int { /// # } /// ``` #[inline] - #[unstable(feature = "atomic_mut_ptr", - reason = "recently added", - issue = "66893")] + #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")] pub const fn as_ptr(&self) -> *mut $int_type { self.v.get() } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 363a266717467..d772b188c7360 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -273,7 +273,6 @@ #![feature(utf8_chunks)] // // Library features (core): -#![feature(atomic_mut_ptr)] #![feature(char_internals)] #![feature(core_intrinsics)] #![feature(duration_constants)] From daf31a113cd24b85e1c8731b0531063477a1f92b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 26 Feb 2023 23:13:58 +0100 Subject: [PATCH 02/11] remove unused imports --- library/std/src/sys/hermit/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index d34a4cfedea78..743e93a2fd4db 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -15,7 +15,6 @@ #![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)] -use crate::intrinsics; use crate::os::raw::c_char; pub mod alloc; From ae27762cebdcb441d85f05a906e6ae2e20c5ec47 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 26 Feb 2023 23:21:19 +0100 Subject: [PATCH 03/11] use `as_ptr` to determine the address of atomics --- library/std/src/sys/hermit/futex.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/hermit/futex.rs b/library/std/src/sys/hermit/futex.rs index b64c174b06c6d..427d8ff6f2e4d 100644 --- a/library/std/src/sys/hermit/futex.rs +++ b/library/std/src/sys/hermit/futex.rs @@ -16,7 +16,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) - let r = unsafe { abi::futex_wait( - futex.as_mut_ptr(), + futex.as_ptr(), expected, timespec.as_ref().map_or(null(), |t| t as *const abi::timespec), abi::FUTEX_RELATIVE_TIMEOUT, @@ -28,12 +28,12 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) - #[inline] pub fn futex_wake(futex: &AtomicU32) -> bool { - unsafe { abi::futex_wake(futex.as_mut_ptr(), 1) > 0 } + unsafe { abi::futex_wake(futex.as_ptr(), 1) > 0 } } #[inline] pub fn futex_wake_all(futex: &AtomicU32) { unsafe { - abi::futex_wake(futex.as_mut_ptr(), i32::MAX); + abi::futex_wake(futex.as_ptr(), i32::MAX); } } From e0d9170485fe388b27ebc45a80b9a1b6b317420a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 10 Mar 2023 13:23:46 -0500 Subject: [PATCH 04/11] Change text -> rust highlighting in sanitizer.md --- src/doc/unstable-book/src/compiler-flags/sanitizer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 262cef3454ad3..3282ff720c478 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -213,7 +213,7 @@ See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. ## Example -```text +```rust #![feature(naked_functions)] use std::arch::asm; From b16d6ccdcd4653f2b1e347901c4fab6c8927e645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 12 Mar 2023 00:00:00 +0000 Subject: [PATCH 05/11] Document BinOp::is_checkable --- compiler/rustc_middle/src/mir/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5215e3db798a2..b34651c3ea797 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1999,6 +1999,9 @@ impl BorrowKind { } impl BinOp { + /// The checkable operators are those whose overflow checking behavior is controlled by + /// -Coverflow-checks option. The remaining operators have either no overflow conditions (e.g., + /// BitAnd, BitOr, BitXor) or are always checked for overflow (e.g., Div, Rem). pub fn is_checkable(self) -> bool { use self::BinOp::*; matches!(self, Add | Sub | Mul | Shl | Shr) From 58c7b670adee30a3fb987297ceb03483756c8f0f Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 12 Mar 2023 22:00:51 +0000 Subject: [PATCH 06/11] create `config::tests::detect_src_and_out` test for bootstrap Signed-off-by: ozkanonur --- src/bootstrap/config/tests.rs | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index 5a105007f21fc..16dc8c63abc96 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -1,5 +1,5 @@ use super::{Config, TomlConfig}; -use std::path::Path; +use std::{env, path::Path}; fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig { |&_| toml::from_str(config).unwrap() @@ -33,4 +33,35 @@ fn download_ci_llvm() { )); } -// FIXME: add test for detecting `src` and `out` +#[test] +fn detect_src_and_out() { + let cfg = parse(""); + + // This will bring absolute form of `src/bootstrap` path + let current_dir = std::env::current_dir().unwrap(); + + // get `src` by moving into project root path + let expected_src = current_dir.ancestors().nth(2).unwrap(); + + assert_eq!(&cfg.src, expected_src); + + // This should bring output path of bootstrap in absolute form + let cargo_target_dir = env::var_os("CARGO_TARGET_DIR") + .expect("CARGO_TARGET_DIR must been provided for the test environment from bootstrap"); + + // Move to `build` from `build/bootstrap` + let expected_out = Path::new(&cargo_target_dir).parent().unwrap(); + assert_eq!(&cfg.out, expected_out); + + let args: Vec = env::args().collect(); + + // Another test for `out` as a sanity check + // + // This will bring something similar to: + // `{config_toml_place}/build/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804` + // `{config_toml_place}` can be anywhere, not just in the rust project directory. + let dep = Path::new(args.first().unwrap()); + let expected_out = dep.ancestors().nth(4).unwrap(); + + assert_eq!(&cfg.out, expected_out); +} From ed8dc5d8177dfa7faa1e65273b2aeed4ea686c8d Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 13 Mar 2023 15:07:16 +0000 Subject: [PATCH 07/11] simd-wide-sum test: adapt for LLVM 17 codegen change After https://github.com/llvm/llvm-project/commit/0d4a709bb876824a0afa5f86e138e8ffdcaf7661 LLVM becomes more clever and turns `@wider_reduce_loop` into an alias: https://buildkite.com/llvm-project/rust-llvm-integrate-prototype/builds/17806#0186da6b-582c-46bf-a227-1565fa0859ac/743-766 This adapts the test to prevent this. --- tests/codegen/simd-wide-sum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs index 04314dc291a6b..db2aa20bde7ab 100644 --- a/tests/codegen/simd-wide-sum.rs +++ b/tests/codegen/simd-wide-sum.rs @@ -1,4 +1,4 @@ -// compile-flags: -C opt-level=3 --edition=2021 +// compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021 // only-x86_64 // ignore-debug: the debug assertions get in the way From c32527fb92218ea999ebf82357838fabf4ee7bc4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 Mar 2023 04:39:17 +0000 Subject: [PATCH 08/11] Treat projections with infer as placeholder during fast reject in new solver --- .../src/coherence/inherent_impls.rs | 13 ++++- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- .../rustc_hir_typeck/src/method/suggest.rs | 20 +++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 +- compiler/rustc_middle/src/ty/fast_reject.rs | 44 +++++++++----- compiler/rustc_middle/src/ty/trait_def.rs | 58 +++++++++++++------ compiler/rustc_middle/src/ty/util.rs | 21 ++++--- .../src/solve/assembly.rs | 4 +- .../src/solve/trait_goals.rs | 8 ++- .../src/traits/error_reporting/mod.rs | 25 +++++--- .../src/traits/select/candidate_assembly.rs | 2 + .../traits/specialize/specialization_graph.rs | 25 ++++++-- .../passes/collect_intra_doc_links.rs | 4 +- .../runaway-impl-candidate-selection.rs | 15 +++++ .../runaway-impl-candidate-selection.stderr | 9 +++ 15 files changed, 186 insertions(+), 68 deletions(-) create mode 100644 tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs create mode 100644 tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 02f3eeee0e7e0..068e5a5eb7739 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -11,7 +11,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; -use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; +use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams, TreatProjections}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -99,7 +99,12 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) { + if let Some(simp) = simplify_type( + self.tcx, + self_ty, + TreatParams::AsInfer, + TreatProjections::DefaultCandidate, + ) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected self type: {:?}", self_ty); @@ -159,7 +164,9 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) { + if let Some(simp) = + simplify_type(self.tcx, ty, TreatParams::AsInfer, TreatProjections::DefaultCandidate) + { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected primitive type: {:?}", ty); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 57805f7c80053..e9d4f9282a3f1 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -15,6 +15,7 @@ use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; @@ -699,7 +700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { - let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) else { + let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer, TreatProjections::DefaultCandidate) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4b15e48bd278e..da0d180987aab 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -25,6 +25,7 @@ use rustc_infer::infer::{ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::DeepRejectCtxt; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths}; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt}; @@ -1516,7 +1517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .any(|info| self.associated_value(info.def_id, item_name).is_some()); let found_assoc = |ty: Ty<'tcx>| { - simplify_type(tcx, ty, TreatParams::AsInfer) + simplify_type(tcx, ty, TreatParams::AsInfer, TreatProjections::DefaultCandidate) .and_then(|simp| { tcx.incoherent_impls(simp) .iter() @@ -2645,9 +2646,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Even though negative bounds are not implemented, we could maybe handle // cases where a positive bound implies a negative impl. (candidates, Vec::new()) - } else if let Some(simp_rcvr_ty) = - simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder) - { + } else if let Some(simp_rcvr_ty) = simplify_type( + self.tcx, + rcvr_ty, + TreatParams::AsPlaceholder, + TreatProjections::DefaultLookup, + ) { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); for candidate in candidates { @@ -2660,8 +2664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .any(|imp_did| { let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity(); - let imp_simp = - simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder); + let imp_simp = simplify_type( + self.tcx, + imp.self_ty(), + TreatParams::AsPlaceholder, + TreatProjections::DefaultLookup, + ); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 16306bef42ea4..ccadb0bada260 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -26,7 +26,7 @@ use rustc_middle::middle::exported_symbols::{ use rustc_middle::mir::interpret; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; -use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_middle::util::common::to_readable_str; @@ -1859,6 +1859,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tcx, trait_ref.self_ty(), TreatParams::AsInfer, + TreatProjections::DefaultCandidate, ); fx_hash_map diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 59deade0a0714..d672c6cc8033c 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -52,16 +52,33 @@ pub enum SimplifiedType { #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum TreatParams { /// Treat parameters as placeholders in the given environment. - /// - /// Note that this also causes us to treat projections as if they were - /// placeholders. This is only correct if the given projection cannot - /// be normalized in the current context. Even if normalization fails, - /// it may still succeed later if the projection contains any inference - /// variables. AsPlaceholder, AsInfer, } +/// During fast-rejection, we have the choice of treating projection types +/// as either simplifyable or not, depending on whether we expect the projection +/// to be normalized/rigid. +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum TreatProjections { + /// In candidates, we may be able to normalize the projection + /// after instantiating the candidate and equating it with a goal. + /// + /// We must assume that the `impl Trait for ::This` + /// can apply to all self types so we don't return a simplified type + /// for `::This`. + DefaultCandidate, + /// In the old solver we don't try to normalize projections + /// when looking up impls and only access them by using the + /// current self type. This means that if the self type is + /// a projection which could later be normalized, we must not + /// treat it as rigid. + DefaultLookup, + /// We can treat projections in the self type as opaque as + /// we separately look up impls for the normalized self type. + NextSolverLookup, +} + /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. /// /// **This function should only be used if you need to store or retrieve the type from some @@ -87,6 +104,7 @@ pub fn simplify_type<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, treat_params: TreatParams, + treat_projections: TreatProjections, ) -> Option { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -118,16 +136,10 @@ pub fn simplify_type<'tcx>( TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), TreatParams::AsInfer => None, }, - ty::Alias(..) => match treat_params { - // When treating `ty::Param` as a placeholder, projections also - // don't unify with anything else as long as they are fully normalized. - // - // We will have to be careful with lazy normalization here. - TreatParams::AsPlaceholder if !ty.has_non_region_infer() => { - debug!("treating `{}` as a placeholder", ty); - Some(PlaceholderSimplifiedType) - } - TreatParams::AsPlaceholder | TreatParams::AsInfer => None, + ty::Alias(..) => match treat_projections { + TreatProjections::DefaultLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType), + TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType), + TreatProjections::DefaultCandidate | TreatProjections::DefaultLookup => None, }, ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 649a58c917073..dec6011fe386e 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,5 +1,5 @@ use crate::traits::specialization_graph; -use crate::ty::fast_reject::{self, SimplifiedType, TreatParams}; +use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{Ident, Ty, TyCtxt}; use hir::def_id::LOCAL_CRATE; @@ -118,16 +118,32 @@ impl<'tcx> TyCtxt<'tcx> { /// Iterate over every impl that could possibly match the self type `self_ty`. /// /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn for_each_relevant_impl( + pub fn for_each_relevant_impl( self, trait_def_id: DefId, self_ty: Ty<'tcx>, - mut f: F, + f: impl FnMut(DefId), ) { - let _: Option<()> = self.find_map_relevant_impl(trait_def_id, self_ty, |did| { - f(did); - None - }); + self.for_each_relevant_impl_treating_projections( + trait_def_id, + self_ty, + TreatProjections::DefaultLookup, + f, + ) + } + + pub fn for_each_relevant_impl_treating_projections( + self, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + treat_projections: TreatProjections, + mut f: impl FnMut(DefId), + ) { + let _: Option<()> = + self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| { + f(did); + None + }); } /// `trait_def_id` MUST BE the `DefId` of a trait. @@ -137,7 +153,12 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, ) -> impl Iterator + 'tcx { let impls = self.trait_impls_of(trait_def_id); - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsInfer) { + if let Some(simp) = fast_reject::simplify_type( + self, + self_ty, + TreatParams::AsInfer, + TreatProjections::DefaultCandidate, + ) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { return impls.iter().copied(); } @@ -150,11 +171,12 @@ impl<'tcx> TyCtxt<'tcx> { /// the first non-none value. /// /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn find_map_relevant_impl Option>( + pub fn find_map_relevant_impl( self, trait_def_id: DefId, self_ty: Ty<'tcx>, - mut f: F, + treat_projections: TreatProjections, + mut f: impl FnMut(DefId) -> Option, ) -> Option { // FIXME: This depends on the set of all impls for the trait. That is // unfortunate wrt. incremental compilation. @@ -169,14 +191,13 @@ impl<'tcx> TyCtxt<'tcx> { } } - // Note that we're using `TreatParams::AsPlaceholder` to query `non_blanket_impls` while using - // `TreatParams::AsInfer` while actually adding them. - // // This way, when searching for some impl for `T: Trait`, we do not look at any impls // whose outer level is not a parameter or projection. Especially for things like // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsPlaceholder) { + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, TreatParams::AsPlaceholder, treat_projections) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { if let result @ Some(_) = f(impl_def_id) { @@ -237,9 +258,12 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait continue; } - if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsInfer) - { + if let Some(simplified_self_ty) = fast_reject::simplify_type( + tcx, + impl_self_ty, + TreatParams::AsInfer, + TreatProjections::DefaultCandidate, + ) { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { impls.blanket_impls.push(impl_def_id); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8b5469743dad6..e3e8a57caf119 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,6 +2,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir; +use crate::ty::fast_reject::TreatProjections; use crate::ty::layout::IntegerExt; use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -363,14 +364,20 @@ impl<'tcx> TyCtxt<'tcx> { self.ensure().coherent_trait(drop_trait); let ty = self.type_of(adt_did).subst_identity(); - let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| { - if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { - if validate(self, impl_did).is_ok() { - return Some((*item_id, self.constness(impl_did))); + let (did, constness) = self.find_map_relevant_impl( + drop_trait, + ty, + // FIXME: This could also be some other mode, like "unexpected" + TreatProjections::DefaultLookup, + |impl_did| { + if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { + if validate(self, impl_did).is_ok() { + return Some((*item_id, self.constness(impl_did))); + } } - } - None - })?; + None + }, + )?; Some(ty::Destructor { did, constness }) } diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 72b1b35e79b15..891ea0cdebe50 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::elaborate_predicates; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult}; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; use std::fmt::Debug; @@ -299,9 +300,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec>, ) { let tcx = self.tcx(); - tcx.for_each_relevant_impl( + tcx.for_each_relevant_impl_treating_projections( goal.predicate.trait_def_id(tcx), goal.predicate.self_ty(), + TreatProjections::NextSolverLookup, |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) { Ok(result) => candidates .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }), diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 0669975d63819..e8696c7d0f5dd 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -8,7 +8,7 @@ use rustc_hir::LangItem; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::supertraits; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; use rustc_span::DUMMY_SP; @@ -135,9 +135,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // currently instead lint patterns which can be used to // exploit this unsoundness on stable, see #93367 for // more details. + // + // Using `TreatProjections::NextSolverLookup` is fine here because + // `instantiate_constituent_tys_for_auto_trait` returns nothing for + // projection types anyways. So it doesn't really matter what we do + // here, and this is faster. if let Some(def_id) = ecx.tcx().find_map_relevant_impl( goal.predicate.def_id(), goal.predicate.self_ty(), + TreatProjections::NextSolverLookup, Some, ) { debug!(?def_id, ?goal, "disqualified auto-trait implementation"); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 704b0d0bd1cec..4ceec0d6a57f9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -32,6 +32,7 @@ use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print}; use rustc_middle::ty::{ @@ -1799,12 +1800,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }) .and_then(|(trait_assoc_item, id)| { let trait_assoc_ident = trait_assoc_item.ident(self.tcx); - self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| { - self.tcx - .associated_items(did) - .in_definition_order() - .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) - }) + self.tcx.find_map_relevant_impl( + id, + proj.projection_ty.self_ty(), + TreatProjections::DefaultLookup, + |did| { + self.tcx + .associated_items(did) + .in_definition_order() + .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) + }, + ) }) .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { Some( @@ -2176,7 +2182,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_ref: &ty::PolyTraitRef<'tcx>, ) -> bool { let get_trait_impl = |trait_def_id| { - self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) + self.tcx.find_map_relevant_impl( + trait_def_id, + trait_ref.skip_binder().self_ty(), + TreatProjections::DefaultLookup, + Some, + ) }; let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); let traits_with_same_path: std::collections::BTreeSet<_> = self diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index e91057356a2dc..4305171aa8066 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -9,6 +9,7 @@ use hir::LangItem; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_target::spec::abi::Abi; @@ -783,6 +784,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let relevant_impl = self.tcx().find_map_relevant_impl( self.tcx().require_lang_item(LangItem::Drop, None), obligation.predicate.skip_binder().trait_ref.self_ty(), + TreatProjections::DefaultLookup, Some, ); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 61ed9ef2ec184..bebaa885cf7c9 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -3,7 +3,7 @@ use super::OverlapError; use crate::traits; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; -use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; pub use rustc_middle::traits::specialization_graph::*; @@ -49,8 +49,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) - { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + TreatParams::AsInfer, + fast_reject::TreatProjections::DefaultCandidate, + ) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { @@ -65,8 +69,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let vec: &mut Vec; - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) - { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + TreatParams::AsInfer, + TreatProjections::DefaultCandidate, + ) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { @@ -302,7 +310,12 @@ impl<'tcx> GraphExt<'tcx> for Graph { let mut parent = trait_def_id; let mut last_lint = None; - let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer); + let simplified = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + TreatParams::AsInfer, + TreatProjections::DefaultCandidate, + ); // Descend the specialization tree, where `parent` is the current parent node. loop { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index bcb69d1a4ca8b..bd5e05770fe72 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -13,7 +13,7 @@ use rustc_hir::def::Namespace::*; use rustc_hir::def::{DefKind, Namespace, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::Mutability; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{fast_reject::TreatProjections, Ty, TyCtxt}; use rustc_middle::{bug, ty}; use rustc_resolve::rustdoc::MalformedGenerics; use rustc_resolve::rustdoc::{prepare_to_doc_link_resolution, strip_generics_from_path}; @@ -735,7 +735,7 @@ fn trait_impls_for<'a>( trace!("considering explicit impl for trait {:?}", trait_); // Look at each trait implementation to see if it's an impl for `did` - tcx.find_map_relevant_impl(trait_, ty, |impl_| { + tcx.find_map_relevant_impl(trait_, ty, TreatProjections::DefaultLookup, |impl_| { let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); // Check if these are the same type. let impl_type = trait_ref.skip_binder().self_ty(); diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs new file mode 100644 index 0000000000000..1dca86d3630b1 --- /dev/null +++ b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs @@ -0,0 +1,15 @@ +// compile-flags: -Ztrait-solver=next + +// In the new solver, we are trying to select `::Item: Debug`, +// which, naively can be unified with every impl of `Debug` if we're not careful. +// This test makes sure that we treat projections with inference var substs as +// placeholders during fast reject. + +fn iter() -> ::Item { + todo!() +} + +fn main() { + println!("{:?}", iter::<_>()); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr new file mode 100644 index 0000000000000..47004821ad7c6 --- /dev/null +++ b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/runaway-impl-candidate-selection.rs:13:22 + | +LL | println!("{:?}", iter::<_>()); + | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `iter` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. From 868aa42f4b1310f945749a43bdf21a0240285d93 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 12 Mar 2023 00:46:46 +0000 Subject: [PATCH 09/11] Add a test that used to take forever to compile --- .../nested-obligations-with-bound-vars-gat.rs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs diff --git a/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs b/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs new file mode 100644 index 0000000000000..92bad959095d2 --- /dev/null +++ b/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs @@ -0,0 +1,43 @@ +// check-pass +// compile-flags: -Ztrait-solver=next +// Issue 96230 + +use std::fmt::Debug; + +trait Classic { + type Assoc; +} + +trait Gat { + type Assoc<'a>; +} + +struct Foo; + +impl Classic for Foo { + type Assoc = (); +} + +impl Gat for Foo { + type Assoc<'i> = (); +} + +fn classic_debug(_: T) +where + T::Assoc: Debug, +{ +} + +fn gat_debug(_: T) +where + for<'a> T::Assoc<'a>: Debug, +{ +} + +fn main() { + classic_debug::(Foo); // fine + classic_debug(Foo); // fine + + gat_debug::(Foo); // fine + gat_debug(Foo); // boom +} From 84d254ead0527c8b098cc35b156d73f9f9c3ec8b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 12 Mar 2023 00:59:54 +0000 Subject: [PATCH 10/11] Better names? --- .../src/coherence/inherent_impls.rs | 13 +++++---- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 12 ++++---- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +-- compiler/rustc_middle/src/ty/fast_reject.rs | 29 ++++++++++--------- compiler/rustc_middle/src/ty/trait_def.rs | 12 ++++---- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- .../src/solve/project_goals.rs | 2 +- .../src/solve/trait_goals.rs | 2 +- .../src/traits/coherence.rs | 2 +- .../src/traits/error_reporting/mod.rs | 4 +-- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/mod.rs | 2 +- .../traits/specialize/specialization_graph.rs | 12 ++++---- .../passes/collect_intra_doc_links.rs | 2 +- 16 files changed, 55 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 068e5a5eb7739..07a33bcbb509b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -102,8 +102,8 @@ impl<'tcx> InherentCollect<'tcx> { if let Some(simp) = simplify_type( self.tcx, self_ty, - TreatParams::AsInfer, - TreatProjections::DefaultCandidate, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { @@ -164,9 +164,12 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = - simplify_type(self.tcx, ty, TreatParams::AsInfer, TreatProjections::DefaultCandidate) - { + if let Some(simp) = simplify_type( + self.tcx, + ty, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected primitive type: {:?}", ty); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index e9d4f9282a3f1..562dd2caae341 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -700,7 +700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { - let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer, TreatProjections::DefaultCandidate) else { + let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index da0d180987aab..7055d9257ec90 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1258,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let target_ty = self .autoderef(sugg_span, rcvr_ty) .find(|(rcvr_ty, _)| { - DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer } + DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey } .types_may_unify(*rcvr_ty, impl_ty) }) .map_or(impl_ty, |(ty, _)| ty) @@ -1517,7 +1517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .any(|info| self.associated_value(info.def_id, item_name).is_some()); let found_assoc = |ty: Ty<'tcx>| { - simplify_type(tcx, ty, TreatParams::AsInfer, TreatProjections::DefaultCandidate) + simplify_type(tcx, ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) .and_then(|simp| { tcx.incoherent_impls(simp) .iter() @@ -2649,8 +2649,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if let Some(simp_rcvr_ty) = simplify_type( self.tcx, rcvr_ty, - TreatParams::AsPlaceholder, - TreatProjections::DefaultLookup, + TreatParams::ForLookup, + TreatProjections::ForLookup, ) { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); @@ -2667,8 +2667,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let imp_simp = simplify_type( self.tcx, imp.self_ty(), - TreatParams::AsPlaceholder, - TreatProjections::DefaultLookup, + TreatParams::ForLookup, + TreatProjections::ForLookup, ); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ccadb0bada260..bbab8a62a2bce 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1858,8 +1858,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), - TreatParams::AsInfer, - TreatProjections::DefaultCandidate, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ); fx_hash_map diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index d672c6cc8033c..ee505742be9a0 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -51,9 +51,12 @@ pub enum SimplifiedType { /// generic parameters as if they were inference variables in that case. #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum TreatParams { - /// Treat parameters as placeholders in the given environment. - AsPlaceholder, - AsInfer, + /// Treat parameters as infer vars. This is the correct mode for caching + /// an impl's type for lookup. + AsCandidateKey, + /// Treat parameters as placeholders in the given environment. This is the + /// correct mode for *lookup*, as during candidate selection. + ForLookup, } /// During fast-rejection, we have the choice of treating projection types @@ -67,13 +70,13 @@ pub enum TreatProjections { /// We must assume that the `impl Trait for ::This` /// can apply to all self types so we don't return a simplified type /// for `::This`. - DefaultCandidate, + AsCandidateKey, /// In the old solver we don't try to normalize projections /// when looking up impls and only access them by using the /// current self type. This means that if the self type is /// a projection which could later be normalized, we must not /// treat it as rigid. - DefaultLookup, + ForLookup, /// We can treat projections in the self type as opaque as /// we separately look up impls for the normalized self type. NextSolverLookup, @@ -133,13 +136,13 @@ pub fn simplify_type<'tcx>( ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Placeholder(..) => Some(PlaceholderSimplifiedType), ty::Param(_) => match treat_params { - TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), - TreatParams::AsInfer => None, + TreatParams::ForLookup => Some(PlaceholderSimplifiedType), + TreatParams::AsCandidateKey => None, }, ty::Alias(..) => match treat_projections { - TreatProjections::DefaultLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType), + TreatProjections::ForLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType), TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType), - TreatProjections::DefaultCandidate | TreatProjections::DefaultLookup => None, + TreatProjections::AsCandidateKey | TreatProjections::ForLookup => None, }, ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, @@ -307,8 +310,8 @@ impl DeepRejectCtxt { // Depending on the value of `treat_obligation_params`, we either // treat generic parameters like placeholders or like inference variables. ty::Param(_) => match self.treat_obligation_params { - TreatParams::AsPlaceholder => false, - TreatParams::AsInfer => true, + TreatParams::ForLookup => false, + TreatParams::AsCandidateKey => true, }, ty::Infer(_) => true, @@ -345,8 +348,8 @@ impl DeepRejectCtxt { let k = impl_ct.kind(); match obligation_ct.kind() { ty::ConstKind::Param(_) => match self.treat_obligation_params { - TreatParams::AsPlaceholder => false, - TreatParams::AsInfer => true, + TreatParams::ForLookup => false, + TreatParams::AsCandidateKey => true, }, // As we don't necessarily eagerly evaluate constants, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index dec6011fe386e..bf2b121f704af 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -127,7 +127,7 @@ impl<'tcx> TyCtxt<'tcx> { self.for_each_relevant_impl_treating_projections( trait_def_id, self_ty, - TreatProjections::DefaultLookup, + TreatProjections::ForLookup, f, ) } @@ -156,8 +156,8 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(simp) = fast_reject::simplify_type( self, self_ty, - TreatParams::AsInfer, - TreatProjections::DefaultCandidate, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { return impls.iter().copied(); @@ -196,7 +196,7 @@ impl<'tcx> TyCtxt<'tcx> { // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. if let Some(simp) = - fast_reject::simplify_type(self, self_ty, TreatParams::AsPlaceholder, treat_projections) + fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup, treat_projections) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { @@ -261,8 +261,8 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait if let Some(simplified_self_ty) = fast_reject::simplify_type( tcx, impl_self_ty, - TreatParams::AsInfer, - TreatProjections::DefaultCandidate, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ) { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e3e8a57caf119..b0f6127baa5d4 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -368,7 +368,7 @@ impl<'tcx> TyCtxt<'tcx> { drop_trait, ty, // FIXME: This could also be some other mode, like "unexpected" - TreatProjections::DefaultLookup, + TreatProjections::ForLookup, |impl_did| { if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { if validate(self, impl_did).is_ok() { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5ef3e13eff801..c8d371dd0846b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2215,7 +2215,7 @@ impl CheckAttrVisitor<'_> { // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments. // // Properly checking this means pulling in additional `rustc` crates, so we don't. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }; if sig.abi != Abi::Rust { tcx.sess.emit_err(errors::ProcMacroInvalidAbi { diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index e206658b4b90d..dbb8e722c8f6f 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -184,7 +184,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index e8696c7d0f5dd..7878539817cfb 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -36,7 +36,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let tcx = ecx.tcx(); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) { diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 6b688c322c786..96a4b76af550f 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -75,7 +75,7 @@ pub fn overlapping_impls( // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }; let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 4ceec0d6a57f9..41ffaeeac1c11 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1803,7 +1803,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.tcx.find_map_relevant_impl( id, proj.projection_ty.self_ty(), - TreatProjections::DefaultLookup, + TreatProjections::ForLookup, |did| { self.tcx .associated_items(did) @@ -2185,7 +2185,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.tcx.find_map_relevant_impl( trait_def_id, trait_ref.skip_binder().self_ty(), - TreatProjections::DefaultLookup, + TreatProjections::ForLookup, Some, ) }; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 4305171aa8066..3182af989f05a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -784,7 +784,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let relevant_impl = self.tcx().find_map_relevant_impl( self.tcx().require_lang_item(LangItem::Drop, None), obligation.predicate.skip_binder().trait_ref.self_ty(), - TreatProjections::DefaultLookup, + TreatProjections::ForLookup, Some, ); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d7ce007812450..38cdaddc1e707 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2558,7 +2558,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // We can avoid creating type variables and doing the full // substitution if we find that any of the input types, when // simplified, do not match. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs) .any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp)) } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index bebaa885cf7c9..cd665d9471db2 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -52,8 +52,8 @@ impl<'tcx> ChildrenExt<'tcx> for Children { if let Some(st) = fast_reject::simplify_type( tcx, trait_ref.self_ty(), - TreatParams::AsInfer, - fast_reject::TreatProjections::DefaultCandidate, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) @@ -72,8 +72,8 @@ impl<'tcx> ChildrenExt<'tcx> for Children { if let Some(st) = fast_reject::simplify_type( tcx, trait_ref.self_ty(), - TreatParams::AsInfer, - TreatProjections::DefaultCandidate, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); @@ -313,8 +313,8 @@ impl<'tcx> GraphExt<'tcx> for Graph { let simplified = fast_reject::simplify_type( tcx, trait_ref.self_ty(), - TreatParams::AsInfer, - TreatProjections::DefaultCandidate, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ); // Descend the specialization tree, where `parent` is the current parent node. diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index bd5e05770fe72..358f6ad566c25 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -735,7 +735,7 @@ fn trait_impls_for<'a>( trace!("considering explicit impl for trait {:?}", trait_); // Look at each trait implementation to see if it's an impl for `did` - tcx.find_map_relevant_impl(trait_, ty, TreatProjections::DefaultLookup, |impl_| { + tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| { let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); // Check if these are the same type. let impl_type = trait_ref.skip_binder().self_ty(); From 04dfedb3e9d11710594aca52f874892cbbbd50ad Mon Sep 17 00:00:00 2001 From: Petr Sumbera Date: Mon, 13 Mar 2023 17:43:04 +0100 Subject: [PATCH 11/11] Don't use fd-lock on Solaris in bootstrap ...as Solaris is missing flock() fixes #103630 --- src/bootstrap/CHANGELOG.md | 1 + src/bootstrap/Cargo.toml | 5 ++++- src/bootstrap/bin/main.rs | 17 ++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index 4105fa5ec9600..4381e51ca22cd 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -46,6 +46,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage 0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed [#77120](https://github.com/rust-lang/rust/pull/77120). +- File locking is now used to avoid collisions between multiple running instances of `x.py` (e.g. when using `rust-analyzer` and `x.py` at the same time). Note that Solaris and possibly other non Unix and non Windows systems don't support it [#108607](https://github.com/rust-lang/rust/pull/108607). This might possibly lead to build data corruption. ## [Version 1] - 2020-09-11 diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 663987f113c8b..afe3fc1741b30 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -32,7 +32,6 @@ test = false [dependencies] build_helper = { path = "../tools/build_helper" } cmake = "0.1.38" -fd-lock = "3.0.8" filetime = "0.2" getopts = "0.2.19" cc = "1.0.69" @@ -56,6 +55,10 @@ walkdir = "2" # Dependencies needed by the build-metrics feature sysinfo = { version = "0.26.0", optional = true } +# Solaris doesn't support flock() and thus fd-lock is not option now +[target.'cfg(not(target_os = "solaris"))'.dependencies] +fd-lock = "3.0.8" + [target.'cfg(windows)'.dependencies.winapi] version = "0.3" features = [ diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index 3856bb64fb310..018f862fae37c 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -7,15 +7,18 @@ use std::env; -use bootstrap::{t, Build, Config, Subcommand, VERSION}; +#[cfg(all(any(unix, windows), not(target_os = "solaris")))] +use bootstrap::t; +use bootstrap::{Build, Config, Subcommand, VERSION}; fn main() { let args = env::args().skip(1).collect::>(); let config = Config::parse(&args); - let mut build_lock; - let _build_lock_guard; - if cfg!(any(unix, windows)) { + #[cfg(all(any(unix, windows), not(target_os = "solaris")))] + { + let mut build_lock; + let _build_lock_guard; let path = config.out.join("lock"); build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path))); _build_lock_guard = match build_lock.try_write() { @@ -30,9 +33,9 @@ fn main() { t!(build_lock.write()) } }; - } else { - println!("warning: file locking not supported for target, not locking build directory"); } + #[cfg(any(not(any(unix, windows)), target_os = "solaris"))] + println!("warning: file locking not supported for target, not locking build directory"); // check_version warnings are not printed during setup let changelog_suggestion = @@ -125,7 +128,7 @@ fn get_lock_owner(f: &std::path::Path) -> Option { }) } -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "solaris")))] fn get_lock_owner(_: &std::path::Path) -> Option { // FIXME: Implement on other OS's None