From 7b9f64475ed51fbf8221ecb8c7f4fc9e71fa1d53 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Sun, 8 Jan 2023 22:53:51 +0300 Subject: [PATCH 01/15] Change memory ordering in System wrapper example Currently, the `SeqCst` ordering is used, which seems unnecessary: + Even `Relaxed` ordering guarantees that all updates are atomic and are executed in total order + User code only reads atomic for monitoring purposes, no "happens-before" relationships with actual allocations and deallocations are needed for this If argumentation above is correct, I propose changing ordering to `Relaxed` to clarify that no synchronization is required here, and improve performance (if somebody copy-pastes this example into their code). --- library/std/src/alloc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c5a5991cc81c4..ec774e62debbf 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -93,7 +93,7 @@ pub use alloc_crate::alloc::*; /// /// ```rust /// use std::alloc::{System, GlobalAlloc, Layout}; -/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; /// /// struct Counter; /// @@ -103,14 +103,14 @@ pub use alloc_crate::alloc::*; /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 { /// let ret = System.alloc(layout); /// if !ret.is_null() { -/// ALLOCATED.fetch_add(layout.size(), SeqCst); +/// ALLOCATED.fetch_add(layout.size(), Relaxed); /// } /// ret /// } /// /// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { /// System.dealloc(ptr, layout); -/// ALLOCATED.fetch_sub(layout.size(), SeqCst); +/// ALLOCATED.fetch_sub(layout.size(), Relaxed); /// } /// } /// @@ -118,7 +118,7 @@ pub use alloc_crate::alloc::*; /// static A: Counter = Counter; /// /// fn main() { -/// println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst)); +/// println!("allocated bytes before main: {}", ALLOCATED.load(Relaxed)); /// } /// ``` /// From 671de6d62a21de60073d2e4d0f8ccfcd5ea826bd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 17 Apr 2023 07:16:25 +1000 Subject: [PATCH 02/15] Remove unused `TypeFoldable`/`TypeVisitable` impls. --- compiler/rustc_infer/src/traits/project.rs | 2 +- compiler/rustc_middle/src/hir/place.rs | 1 - compiler/rustc_middle/src/thir.rs | 1 - compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_middle/src/traits/select.rs | 2 +- compiler/rustc_middle/src/traits/solve.rs | 2 +- compiler/rustc_middle/src/ty/error.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../rustc_middle/src/ty/structural_impls.rs | 20 ------------ compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_transmute/src/lib.rs | 4 +-- .../rustc_type_ir/src/structural_impls.rs | 31 ++----------------- 12 files changed, 12 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 8d0af738dd115..e375d611936ea 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -20,7 +20,7 @@ pub struct MismatchedProjectionTypes<'tcx> { pub err: ty::error::TypeError<'tcx>, } -#[derive(Clone, TypeFoldable, TypeVisitable)] +#[derive(Clone)] pub struct Normalized<'tcx, T> { pub value: T, pub obligations: Vec>, diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 80b4c964ce402..8a22de931c35b 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -66,7 +66,6 @@ pub struct Place<'tcx> { /// /// This is an HIR version of [`rustc_middle::mir::Place`]. #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct PlaceWithHirId<'tcx> { /// `HirId` of the expression or pattern producing this value. pub hir_id: HirId, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index da86cfd477229..813e109c41e14 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -234,7 +234,6 @@ pub enum StmtKind<'tcx> { } #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct LocalVarId(pub hir::HirId); /// A THIR expression. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 6a8ae525069c0..02433026266a3 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -569,7 +569,7 @@ pub struct DerivedObligationCause<'tcx> { pub parent_code: InternedObligationCauseCode<'tcx>, } -#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, TypeVisitable, Lift)] pub enum SelectionError<'tcx> { /// The trait is not implemented. Unimplemented, diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 1cc9fd526b44f..f2dda003b99c5 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -103,7 +103,7 @@ pub type EvaluationCache<'tcx> = Cache< /// required for associated types to work in default impls, as the bounds /// are visible both as projection bounds and as where-clauses from the /// parameter environment. -#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable, TypeVisitable)] +#[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)] pub enum SelectionCandidate<'tcx> { /// A builtin implementation for some specific traits, used in cases /// where we cannot rely an ordinary library implementations. diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index fef2be133e81f..6b7b910a59bf9 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -120,7 +120,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { } /// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)] pub struct ExternalConstraintsData<'tcx> { // FIXME: implement this. pub region_constraints: QueryRegionConstraints<'tcx>, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index aff6c77e039af..1be61e16dbed8 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -28,7 +28,7 @@ impl ExpectedFound { } // Data structures used in type unification -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, TypeVisitable, Lift, PartialEq, Eq)] #[rustc_pass_by_value] pub enum TypeError<'tcx> { Mismatch, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1c1432ecd5a05..2aced27f7bbdc 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2690,7 +2690,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> { } } -#[derive(Debug, Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +#[derive(Debug, Copy, Clone, Lift)] pub struct PrintClosureAsImpl<'tcx> { pub closure: ty::ClosureSubsts<'tcx>, } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a2611022406f6..d4116a763e13b 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -4,7 +4,6 @@ //! to help with the tedium. use crate::mir::interpret; -use crate::mir::ProjectionKind; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -373,16 +372,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { /////////////////////////////////////////////////////////////////////////// // Traversal implementations. -/// AdtDefs are basically the same as a DefId. -impl<'tcx> TypeFoldable> for ty::AdtDef<'tcx> { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { fn visit_with>>( &self, @@ -445,15 +434,6 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { } } -impl<'tcx> TypeFoldable> for &'tcx ty::List { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_projs(v)) - } -} - impl<'tcx> TypeFoldable> for Ty<'tcx> { fn try_fold_with>>( self, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 29ae42be09643..aa658fc5e45fb 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -631,7 +631,7 @@ impl<'tcx> UpvarSubsts<'tcx> { /// type of the constant. The reason that `R` is represented as an extra type parameter /// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters: /// inline const can reference lifetimes that are internal to the creating function. -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, Debug)] pub struct InlineConstSubsts<'tcx> { /// Generic parameters from the enclosing item, /// concatenated with the inferred type of the constant. diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 8be02c1d9888a..77c0526e3aabe 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -62,7 +62,7 @@ mod rustc { use rustc_hir::lang_items::LangItem; use rustc_infer::infer::InferCtxt; - use rustc_macros::{TypeFoldable, TypeVisitable}; + use rustc_macros::TypeVisitable; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::Const; use rustc_middle::ty::ParamEnv; @@ -70,7 +70,7 @@ mod rustc { use rustc_middle::ty::TyCtxt; /// The source and destination types of a transmutation. - #[derive(TypeFoldable, TypeVisitable, Debug, Clone, Copy)] + #[derive(TypeVisitable, Debug, Clone, Copy)] pub struct Types<'tcx> { /// The source type. pub src: Ty<'tcx>, diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 54c1ab5a275ef..c513bde6ecfc2 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -6,11 +6,10 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::Interner; use rustc_data_structures::functor::IdFunctor; +use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; use std::ops::ControlFlow; -use std::rc::Rc; -use std::sync::Arc; /////////////////////////////////////////////////////////////////////////// // Atomic structs @@ -106,25 +105,13 @@ impl, E: TypeVisitable> TypeVisitable for } } -impl> TypeFoldable for Rc { +impl> TypeFoldable for Lrc { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|value| value.try_fold_with(folder)) } } -impl> TypeVisitable for Rc { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - (**self).visit_with(visitor) - } -} - -impl> TypeFoldable for Arc { - fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|value| value.try_fold_with(folder)) - } -} - -impl> TypeVisitable for Arc { +impl> TypeVisitable for Lrc { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } @@ -160,18 +147,6 @@ impl> TypeVisitable for &[T] { } } -impl> TypeFoldable for Box<[T]> { - fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|t| t.try_fold_with(folder)) - } -} - -impl> TypeVisitable for Box<[T]> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl, Ix: Idx> TypeFoldable for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|x| x.try_fold_with(folder)) From a82ad2fed4b97daf757c34407bf2cde19a40cce3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Apr 2023 14:53:14 +1000 Subject: [PATCH 03/15] Derive `Type{Foldable,Visitable}` for `UserTypeProjection`. Because the derived versions are good enough. --- compiler/rustc_middle/src/mir/mod.rs | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 039194284b80f..2490b17aac09b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -9,7 +9,7 @@ use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer}; -use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; +use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; @@ -36,7 +36,7 @@ use either::Either; use std::borrow::Cow; use std::fmt::{self, Debug, Display, Formatter, Write}; -use std::ops::{ControlFlow, Index, IndexMut}; +use std::ops::{Index, IndexMut}; use std::{iter, mem}; pub use self::query::*; @@ -2722,6 +2722,7 @@ impl<'tcx> UserTypeProjections { /// `field[0]` (aka `.0`), indicating that the type of `s` is /// determined by finding the type of the `.0` field from `T`. #[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] +#[derive(TypeFoldable, TypeVisitable)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, pub projs: Vec, @@ -2765,28 +2766,6 @@ impl UserTypeProjection { } } -impl<'tcx> TypeFoldable> for UserTypeProjection { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(UserTypeProjection { - base: self.base.try_fold_with(folder)?, - projs: self.projs.try_fold_with(folder)?, - }) - } -} - -impl<'tcx> TypeVisitable> for UserTypeProjection { - fn visit_with>>( - &self, - visitor: &mut Vs, - ) -> ControlFlow { - self.base.visit_with(visitor) - // Note: there's nothing in `self.proj` to visit. - } -} - rustc_index::newtype_index! { #[derive(HashStable)] #[debug_format = "promoted[{}]"] From 9b2cf895137d7fd56d844e47514e6d9accd21606 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 26 Apr 2023 12:49:27 -0400 Subject: [PATCH 04/15] compiletest: emit assembly-output header in error --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6597c729387e..f5b34f8395205 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2332,7 +2332,7 @@ impl<'test> TestCx<'test> { // No extra flags needed. } - Some(_) => self.fatal("unknown 'assembly-output' header"), + Some(header) => self.fatal(&format!("unknown 'assembly-output' header: {header}")), None => self.fatal("missing 'assembly-output' header"), } From c7e16af796ffcf95e9e4063c0711229bcfaa659e Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 26 Apr 2023 12:59:43 -0400 Subject: [PATCH 05/15] compiletest: add bpf-linker assembly support --- src/tools/compiletest/src/runtest.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6597c729387e..6087d36203360 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -224,6 +224,7 @@ enum Emit { Metadata, LlvmIr, Asm, + LinkArgsAsm, } impl<'test> TestCx<'test> { @@ -2035,6 +2036,9 @@ impl<'test> TestCx<'test> { Emit::Asm => { rustc.args(&["--emit", "asm"]); } + Emit::LinkArgsAsm => { + rustc.args(&["-Clink-args=--emit=asm"]); + } } if !is_rustdoc { @@ -2328,6 +2332,10 @@ impl<'test> TestCx<'test> { emit = Emit::Asm; } + Some("bpf-linker") => { + emit = Emit::LinkArgsAsm; + } + Some("ptx-linker") => { // No extra flags needed. } From d5d2785c86a70fba65e9baa862a54be22b3b786c Mon Sep 17 00:00:00 2001 From: Philpax Date: Thu, 15 Dec 2022 11:14:13 +0100 Subject: [PATCH 06/15] docs(std): clarify `remove_dir_all` errors --- library/std/src/fs.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 42a68496fc491..30e553f285b98 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2284,6 +2284,11 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// See [`fs::remove_file`] and [`fs::remove_dir`]. /// +/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root path. +/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent. +/// +/// Consider ignoring the error if validating the removal is not required for your use case. +/// /// [`fs::remove_file`]: remove_file /// [`fs::remove_dir`]: remove_dir /// From bfdd1c4e351f1a30f445c33efdfb946c0eae81ba Mon Sep 17 00:00:00 2001 From: whtahy Date: Wed, 26 Apr 2023 20:37:42 -0400 Subject: [PATCH 07/15] add known-bug test for unsound issue 40582 --- tests/ui/specialization/issue-40582.rs | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/ui/specialization/issue-40582.rs diff --git a/tests/ui/specialization/issue-40582.rs b/tests/ui/specialization/issue-40582.rs new file mode 100644 index 0000000000000..9805933553dd7 --- /dev/null +++ b/tests/ui/specialization/issue-40582.rs @@ -0,0 +1,35 @@ +// check-pass +// known-bug: #40582 + +// Should fail. Should not be possible to implement `make_static`. + +#![feature(specialization)] +#![allow(incomplete_features)] + +trait FromRef<'a, T: ?Sized> { + fn from_ref(r: &'a T) -> Self; +} + +impl<'a, T: ?Sized> FromRef<'a, T> for &'a T { + fn from_ref(r: &'a T) -> Self { + r + } +} + +impl<'a, T: ?Sized, R> FromRef<'a, T> for R { + default fn from_ref(_: &'a T) -> Self { + unimplemented!() + } +} + +fn make_static(data: &T) -> &'static T { + fn helper(data: &T) -> R { + R::from_ref(data) + } + helper(data) +} + +fn main() { + let s = "specialization".to_owned(); + println!("{:?}", make_static(s.as_str())); +} From a87359d7c98790e75e71587058cfea9defee78c7 Mon Sep 17 00:00:00 2001 From: whtahy Date: Wed, 26 Apr 2023 20:35:16 -0400 Subject: [PATCH 08/15] add known-bug test for unsound issue 49682 --- .../thread-local-static-ref-use-after-free.rs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/ui/thread-local/thread-local-static-ref-use-after-free.rs diff --git a/tests/ui/thread-local/thread-local-static-ref-use-after-free.rs b/tests/ui/thread-local/thread-local-static-ref-use-after-free.rs new file mode 100644 index 0000000000000..c282e2185bca2 --- /dev/null +++ b/tests/ui/thread-local/thread-local-static-ref-use-after-free.rs @@ -0,0 +1,46 @@ +// check-pass +// known-bug: #49682 +// edition:2021 + +// Should fail. Keeping references to thread local statics can result in a +// use-after-free. + +#![feature(thread_local)] + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::thread; + +#[allow(dead_code)] +#[thread_local] +static FOO: AtomicUsize = AtomicUsize::new(0); + +#[allow(dead_code)] +async fn bar() {} + +#[allow(dead_code)] +async fn foo() { + let r = &FOO; + bar().await; + r.load(Ordering::SeqCst); +} + +fn main() { + // &FOO = 0x7fd1e9cbf6d0 + _ = thread::spawn(|| { + let g = foo(); + println!("&FOO = {:p}", &FOO); + g + }) + .join() + .unwrap(); + + // &FOO = 0x7fd1e9cc0f50 + println!("&FOO = {:p}", &FOO); + + // &FOO = 0x7fd1e9cbf6d0 + thread::spawn(move || { + println!("&FOO = {:p}", &FOO); + }) + .join() + .unwrap(); +} From 21b9f5c3bb55a8be44fe277891dd1c77fd6ca782 Mon Sep 17 00:00:00 2001 From: whtahy Date: Wed, 26 Apr 2023 20:48:38 -0400 Subject: [PATCH 09/15] add known-bug test for unsound issue 74629 --- .../coherence-overlap-negative-impls.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/ui/coherence/coherence-overlap-negative-impls.rs diff --git a/tests/ui/coherence/coherence-overlap-negative-impls.rs b/tests/ui/coherence/coherence-overlap-negative-impls.rs new file mode 100644 index 0000000000000..cd1df53a52889 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negative-impls.rs @@ -0,0 +1,41 @@ +// check-pass +// known-bug: #74629 + +// Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with +// `T = Test, F = ()`, all bounds are true, making both impls applicable. +// `Test: Fold`, `Test: Fold<()>` are true because of `2`. +// `Is: NotNil` is true because of `auto trait` and lack of negative impl. + +#![feature(negative_impls)] +#![feature(auto_traits)] + +struct Nil; +struct Cons(H); +struct Test; + +trait Fold {} + +impl Fold for Cons // 0 +where + T: Fold, +{} + +impl Fold for Cons // 1 +where + T: Fold, + private::Is: private::NotNil, +{} + +impl Fold for Test {} // 2 + +mod private { + use crate::Nil; + + pub struct Is(T); + pub auto trait NotNil {} + + #[allow(suspicious_auto_trait_impls)] + impl !NotNil for Is {} +} + +fn main() {} From fcf8468efc7cab2f66372baf9bb28131de444f86 Mon Sep 17 00:00:00 2001 From: whtahy Date: Wed, 26 Apr 2023 21:47:31 -0400 Subject: [PATCH 10/15] add known-bug test for unsound issue 105782 --- ...ialization-default-items-drop-coherence.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/ui/specialization/specialization-default-items-drop-coherence.rs diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs new file mode 100644 index 0000000000000..16ad942d5ab95 --- /dev/null +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -0,0 +1,30 @@ +// check-pass +// known-bug: #105782 + +// Should fail. Default items completely drop candidates instead of ambiguity, +// which is unsound during coherence, since coherence requires completeness. + +#![feature(specialization)] +#![allow(incomplete_features)] + +trait Default { + type Id; +} + +impl Default for T { + default type Id = T; +} + +trait Overlap { + type Assoc; +} + +impl Overlap for u32 { + type Assoc = usize; +} + +impl Overlap for ::Id { + type Assoc = Box; +} + +fn main() {} From 4b85aa99ad487a5e64eaaee830077d866e8a9e0d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Apr 2023 16:21:20 +1000 Subject: [PATCH 11/15] Add a comment about `TypeFoldable` and slices. --- compiler/rustc_type_ir/src/structural_impls.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index c513bde6ecfc2..c9675f93f9564 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -141,6 +141,10 @@ impl> TypeVisitable for Vec { } } +// `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general +// case, because we can't return a new slice. But note that there are a couple +// of trivial impls of `TypeFoldable` for specific slice types elsewhere. + impl> TypeVisitable for &[T] { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) From 207cec017f7ba30a15ab6faf60f28f6e027400a4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Apr 2023 15:04:18 +1000 Subject: [PATCH 12/15] Clean up `with_task`. Currently it creates an `Option` and then does `map`/`unwrap_or` and `map_or_else` on it, which is hard to read. This commit simplifies things by moving more code into the two arms of the if/else. --- .../rustc_query_system/src/dep_graph/graph.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index b9922b26afcbf..aada94ab26647 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -354,24 +354,20 @@ impl DepGraphData { - dep-node: {key:?}" ); - let task_deps = if cx.dep_context().is_eval_always(key.kind) { - None + let with_deps = |task_deps| K::with_deps(task_deps, || task(cx, arg)); + let (result, edges) = if cx.dep_context().is_eval_always(key.kind) { + (with_deps(TaskDepsRef::EvalAlways), smallvec![]) } else { - Some(Lock::new(TaskDeps { + let task_deps = Lock::new(TaskDeps { #[cfg(debug_assertions)] node: Some(key), reads: SmallVec::new(), read_set: Default::default(), phantom_data: PhantomData, - })) + }); + (with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads) }; - let task_deps_ref = - task_deps.as_ref().map(TaskDepsRef::Allow).unwrap_or(TaskDepsRef::EvalAlways); - - let result = K::with_deps(task_deps_ref, || task(cx, arg)); - let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads); - let dcx = cx.dep_context(); let hashing_timer = dcx.profiler().incr_result_hashing(); let current_fingerprint = From 793b2ffb67630bd4d92ba5083bfdd06ae84b61eb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Apr 2023 15:40:17 +1000 Subject: [PATCH 13/15] Factor out common code in `intern_node`. There are three very similar blocks in this function. --- .../rustc_query_system/src/dep_graph/graph.rs | 80 ++++++------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index aada94ab26647..8de4d06fe782b 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1232,76 +1232,48 @@ impl CurrentDepGraph { self.node_intern_event_id.map(|eid| profiler.generic_activity_with_event_id(eid)); if let Some(prev_index) = prev_graph.node_to_index_opt(&key) { + let get_dep_node_index = |color, fingerprint| { + if print_status { + eprintln!("[task::{color:}] {key:?}"); + } + + let mut prev_index_to_index = self.prev_index_to_index.lock(); + + let dep_node_index = match prev_index_to_index[prev_index] { + Some(dep_node_index) => dep_node_index, + None => { + let dep_node_index = + self.encoder.borrow().send(profiler, key, fingerprint, edges); + prev_index_to_index[prev_index] = Some(dep_node_index); + dep_node_index + } + }; + + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key, fingerprint); + + dep_node_index + }; + // Determine the color and index of the new `DepNode`. if let Some(fingerprint) = fingerprint { if fingerprint == prev_graph.fingerprint_by_index(prev_index) { - if print_status { - eprintln!("[task::green] {key:?}"); - } - // This is a green node: it existed in the previous compilation, // its query was re-executed, and it has the same result as before. - let mut prev_index_to_index = self.prev_index_to_index.lock(); - - let dep_node_index = match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let dep_node_index = - self.encoder.borrow().send(profiler, key, fingerprint, edges); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index - } - }; - - #[cfg(debug_assertions)] - self.record_edge(dep_node_index, key, fingerprint); + let dep_node_index = get_dep_node_index("green", fingerprint); (dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index)))) } else { - if print_status { - eprintln!("[task::red] {key:?}"); - } - // This is a red node: it existed in the previous compilation, its query // was re-executed, but it has a different result from before. - let mut prev_index_to_index = self.prev_index_to_index.lock(); - - let dep_node_index = match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let dep_node_index = - self.encoder.borrow().send(profiler, key, fingerprint, edges); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index - } - }; - - #[cfg(debug_assertions)] - self.record_edge(dep_node_index, key, fingerprint); + let dep_node_index = get_dep_node_index("red", fingerprint); (dep_node_index, Some((prev_index, DepNodeColor::Red))) } } else { - if print_status { - eprintln!("[task::unknown] {key:?}"); - } - // This is a red node, effectively: it existed in the previous compilation // session, its query was re-executed, but it doesn't compute a result hash // (i.e. it represents a `no_hash` query), so we have no way of determining // whether or not the result was the same as before. - let mut prev_index_to_index = self.prev_index_to_index.lock(); - - let dep_node_index = match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let dep_node_index = - self.encoder.borrow().send(profiler, key, Fingerprint::ZERO, edges); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index - } - }; - - #[cfg(debug_assertions)] - self.record_edge(dep_node_index, key, Fingerprint::ZERO); + let dep_node_index = get_dep_node_index("unknown", Fingerprint::ZERO); (dep_node_index, Some((prev_index, DepNodeColor::Red))) } } else { From 60ab69d168f9a1b300a2e430cd05dcfd835bd8f7 Mon Sep 17 00:00:00 2001 From: KaDiWa Date: Tue, 3 Jan 2023 21:37:16 +0100 Subject: [PATCH 14/15] correct `std::prelude` comment --- library/std/src/prelude/v1.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 2aefd7c513dc8..7a7a773763559 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -91,10 +91,10 @@ pub use core::prelude::v1::cfg_eval; )] pub use core::prelude::v1::type_ascribe; -// The file so far is equivalent to src/libcore/prelude/v1.rs, -// and below to src/liballoc/prelude.rs. -// Those files are duplicated rather than using glob imports -// because we want docs to show these re-exports as pointing to within `std`. +// The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated +// rather than glob imported because we want docs to show these re-exports as +// pointing to within `std`. +// Below are the items from the alloc crate. #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] From db0bb92ff1fe4c16330d0465041b1399c5bc5fb2 Mon Sep 17 00:00:00 2001 From: John Kelly Date: Thu, 27 Apr 2023 17:21:45 +0100 Subject: [PATCH 15/15] Remove invalid value from scraped-examples.md --- src/doc/rustdoc/src/scraped-examples.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustdoc/src/scraped-examples.md b/src/doc/rustdoc/src/scraped-examples.md index d75f6d522e8ed..7197e01c8e313 100644 --- a/src/doc/rustdoc/src/scraped-examples.md +++ b/src/doc/rustdoc/src/scraped-examples.md @@ -24,14 +24,14 @@ Then this code snippet will be included in the documentation for `a_func`. This This feature is unstable, so you can enable it by calling Rustdoc with the unstable `rustdoc-scrape-examples` flag: ```bash -cargo doc -Zunstable-options -Zrustdoc-scrape-examples=examples +cargo doc -Zunstable-options -Zrustdoc-scrape-examples ``` To enable this feature on [docs.rs](https://docs.rs), add this to your Cargo.toml: ```toml [package.metadata.docs.rs] -cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples=examples"] +cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"] ```