about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp5
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs4
-rw-r--r--compiler/rustc_privacy/src/lib.rs7
-rw-r--r--library/core/src/mem/mod.rs5
-rw-r--r--library/core/src/ptr/mut_ptr.rs18
-rw-r--r--src/bootstrap/builder.rs6
-rw-r--r--src/bootstrap/builder/tests.rs4
-rw-r--r--src/ci/docker/host-x86_64/wasm32/Dockerfile3
-rw-r--r--src/librustdoc/html/render/mod.rs47
-rw-r--r--tests/rustdoc/issue-32077-type-alias-impls.rs59
-rw-r--r--tests/ui/privacy/private-bounds-locally-allowed.rs7
-rw-r--r--tests/ui/unsized/issue-115203.rs11
-rw-r--r--tests/ui/unsized/issue-115203.stderr19
13 files changed, 173 insertions, 22 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 4ed086ff42f..5ecf3aec65d 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -9,6 +9,7 @@
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/CommandFlags.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
@@ -50,6 +51,8 @@
 
 using namespace llvm;
 
+static codegen::RegisterCodeGenFlags CGF;
+
 typedef struct LLVMOpaquePass *LLVMPassRef;
 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
 
@@ -422,7 +425,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     return nullptr;
   }
 
-  TargetOptions Options;
+  TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Trip);
 
   Options.FloatABIType = FloatABI::Default;
   if (UseSoftFloat) {
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 4b51beed095..b52827a1e88 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -39,6 +39,10 @@ pub struct ConstProp;
 
 impl<'tcx> MirLint<'tcx> for ConstProp {
     fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
+        if body.tainted_by_errors.is_some() {
+            return;
+        }
+
         // will be evaluated by miri and produce its errors there
         if body.source.promoted.is_some() {
             return;
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 906a36cdb25..aedc7b22725 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1463,14 +1463,15 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
         };
 
         let vis = self.tcx.local_visibility(local_def_id);
-        let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
         let span = self.tcx.def_span(self.item_def_id.to_def_id());
         let vis_span = self.tcx.def_span(def_id);
         if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) {
             let vis_descr = match vis {
                 ty::Visibility::Public => "public",
                 ty::Visibility::Restricted(vis_def_id) => {
-                    if vis_def_id == self.tcx.parent_module(hir_id).to_local_def_id() {
+                    if vis_def_id
+                        == self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id()
+                    {
                         "private"
                     } else if vis_def_id.is_top_level_module() {
                         "crate-private"
@@ -1504,7 +1505,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
             };
             self.tcx.emit_spanned_lint(
                 lint,
-                hir_id,
+                self.tcx.hir().local_def_id_to_hir_id(self.item_def_id),
                 span,
                 PrivateInterfacesOrBoundsLint {
                     item_span: span,
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 732fcce0f29..bc701d97bbb 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1126,6 +1126,11 @@ impl<T> fmt::Debug for Discriminant<T> {
 ///
 /// [Reference]: ../../reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
 ///
+/// The value of a [`Discriminant<T>`] is independent of any *lifetimes* in `T`. As such, reading
+/// or writing a `Discriminant<Foo<'a>>` as a `Discriminant<Foo<'b>>` (whether via [`transmute`] or
+/// otherwise) is always sound. Note that this is **not** true for other kinds of generic
+/// parameters; `Discriminant<Foo<A>>` and `Discriminant<Foo<B>>` might be incompatible.
+///
 /// # Examples
 ///
 /// This can be used to compare enums that carry data, while disregarding
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 9dbb3f9d322..6d623b82c1c 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -109,7 +109,7 @@ impl<T: ?Sized> *mut T {
     /// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit
     /// coercion.
     ///
-    /// [`cast_mut`]: #method.cast_mut
+    /// [`cast_mut`]: pointer::cast_mut
     #[stable(feature = "ptr_const_cast", since = "1.65.0")]
     #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
     #[rustc_diagnostic_item = "ptr_cast_const"]
@@ -121,7 +121,7 @@ impl<T: ?Sized> *mut T {
     /// Casts a pointer to its raw bits.
     ///
     /// This is equivalent to `as usize`, but is more specific to enhance readability.
-    /// The inverse method is [`from_bits`](#method.from_bits-1).
+    /// The inverse method is [`from_bits`](pointer#method.from_bits-1).
     ///
     /// In particular, `*p as usize` and `p as usize` will both compile for
     /// pointers to numeric types but do very different things, so using this
@@ -157,7 +157,7 @@ impl<T: ?Sized> *mut T {
     /// Creates a pointer from its raw bits.
     ///
     /// This is equivalent to `as *mut T`, but is more specific to enhance readability.
-    /// The inverse method is [`to_bits`](#method.to_bits-1).
+    /// The inverse method is [`to_bits`](pointer#method.to_bits-1).
     ///
     /// # Examples
     ///
@@ -307,7 +307,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// For the mutable counterpart see [`as_mut`].
     ///
-    /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+    /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
     /// [`as_mut`]: #method.as_mut
     ///
     /// # Safety
@@ -373,7 +373,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// For the mutable counterpart see [`as_uninit_mut`].
     ///
-    /// [`as_ref`]: #method.as_ref-1
+    /// [`as_ref`]: pointer#method.as_ref-1
     /// [`as_uninit_mut`]: #method.as_uninit_mut
     ///
     /// # Safety
@@ -628,7 +628,7 @@ impl<T: ?Sized> *mut T {
     /// For the shared counterpart see [`as_ref`].
     ///
     /// [`as_uninit_mut`]: #method.as_uninit_mut
-    /// [`as_ref`]: #method.as_ref-1
+    /// [`as_ref`]: pointer#method.as_ref-1
     ///
     /// # Safety
     ///
@@ -693,7 +693,7 @@ impl<T: ?Sized> *mut T {
     /// For the shared counterpart see [`as_uninit_ref`].
     ///
     /// [`as_mut`]: #method.as_mut
-    /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+    /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
     ///
     /// # Safety
     ///
@@ -783,7 +783,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// This function is the inverse of [`offset`].
     ///
-    /// [`offset`]: #method.offset-1
+    /// [`offset`]: pointer#method.offset-1
     ///
     /// # Safety
     ///
@@ -2064,7 +2064,7 @@ impl<T> *mut [T] {
     ///
     /// For the mutable counterpart see [`as_uninit_slice_mut`].
     ///
-    /// [`as_ref`]: #method.as_ref-1
+    /// [`as_ref`]: pointer#method.as_ref-1
     /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
     ///
     /// # Safety
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index a24a6a4636d..c62548875bf 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -302,8 +302,10 @@ impl StepDescription {
         }
     }
 
-    fn maybe_run(&self, builder: &Builder<'_>, pathsets: Vec<PathSet>) {
-        if pathsets.iter().any(|set| self.is_excluded(builder, set)) {
+    fn maybe_run(&self, builder: &Builder<'_>, mut pathsets: Vec<PathSet>) {
+        pathsets.retain(|set| !self.is_excluded(builder, set));
+
+        if pathsets.is_empty() {
             return;
         }
 
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 43b4a34fe5b..80e66622e8b 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -136,9 +136,9 @@ fn test_exclude_kind() {
     let mut config = configure("test", &["A"], &["A"]);
     // Ensure our test is valid, and `test::Rustc` would be run without the exclude.
     assert!(run_build(&[], config.clone()).contains::<test::CrateLibrustc>());
-    // Ensure tests for rustc are skipped.
+    // Ensure tests for rustc are not skipped.
     config.skip = vec![path.clone()];
-    assert!(!run_build(&[], config.clone()).contains::<test::CrateLibrustc>());
+    assert!(run_build(&[], config.clone()).contains::<test::CrateLibrustc>());
     // Ensure builds for rustc are not skipped.
     assert!(run_build(&[], config).contains::<compile::Rustc>());
 }
diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile
index 02b4664eb55..0d0f1edd003 100644
--- a/src/ci/docker/host-x86_64/wasm32/Dockerfile
+++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile
@@ -58,5 +58,6 @@ ENV NO_CHANGE_USER=1
 RUN chown 10719 -R /emsdk-portable/
 
 # Exclude library/alloc due to OOM in benches.
+# FIXME: Fix std tests
 ENV SCRIPT python3 ../x.py test --stage 2 --host='' --target $TARGETS \
-    --skip library/alloc
+    --skip library/alloc --skip library/std
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index aef8f1a74fb..a85e8356c2f 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -54,6 +54,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::Mutability;
 use rustc_middle::middle::stability;
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::{
     symbol::{sym, Symbol},
@@ -62,6 +63,7 @@ use rustc_span::{
 use serde::ser::{SerializeMap, SerializeSeq};
 use serde::{Serialize, Serializer};
 
+use crate::clean::types::TypeAliasItem;
 use crate::clean::{self, ItemId, RenderedLink, SelfTy};
 use crate::error::Error;
 use crate::formats::cache::Cache;
@@ -1139,8 +1141,40 @@ fn render_assoc_items_inner(
     info!("Documenting associated items of {:?}", containing_item.name);
     let shared = Rc::clone(&cx.shared);
     let cache = &shared.cache;
-    let Some(v) = cache.impls.get(&it) else { return };
-    let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
+    let tcx = cx.tcx();
+    let av = if let TypeAliasItem(ait) = &*containing_item.kind &&
+        let aliased_clean_type = ait.item_type.as_ref().unwrap_or(&ait.type_) &&
+        let Some(aliased_type_defid) = aliased_clean_type.def_id(cache) &&
+        let Some(mut av) = cache.impls.get(&aliased_type_defid).cloned() &&
+        let Some(alias_def_id) = containing_item.item_id.as_def_id()
+    {
+        // This branch of the compiler compares types structually, but does
+        // not check trait bounds. That's probably fine, since type aliases
+        // don't normally constrain on them anyway.
+        // https://github.com/rust-lang/rust/issues/21903
+        //
+        // FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this to use type unification.
+        // Be aware of `tests/rustdoc/issue-112515-impl-ty-alias.rs` which might regress.
+        let aliased_ty = tcx.type_of(alias_def_id).skip_binder();
+        let reject_cx = DeepRejectCtxt {
+            treat_obligation_params: TreatParams::AsCandidateKey,
+        };
+        av.retain(|impl_| {
+            if let Some(impl_def_id) = impl_.impl_item.item_id.as_def_id() {
+                reject_cx.types_may_unify(aliased_ty, tcx.type_of(impl_def_id).skip_binder())
+            } else {
+                false
+            }
+        });
+        av
+    } else {
+        Vec::new()
+    };
+    let blank = Vec::new();
+    let v = cache.impls.get(&it).unwrap_or(&blank);
+    let (non_trait, traits): (Vec<_>, _) =
+        v.iter().chain(&av[..]).partition(|i| i.inner_impl().trait_.is_none());
+    let mut saw_impls = FxHashSet::default();
     if !non_trait.is_empty() {
         let mut tmp_buf = Buffer::html();
         let (render_mode, id, class_html) = match what {
@@ -1169,6 +1203,9 @@ fn render_assoc_items_inner(
         };
         let mut impls_buf = Buffer::html();
         for i in &non_trait {
+            if !saw_impls.insert(i.def_id()) {
+                continue;
+            }
             render_impl(
                 &mut impls_buf,
                 cx,
@@ -1214,8 +1251,10 @@ fn render_assoc_items_inner(
 
         let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
             traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
-        let (blanket_impl, concrete): (Vec<&Impl>, _) =
-            concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
+        let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete
+            .into_iter()
+            .filter(|t| saw_impls.insert(t.def_id()))
+            .partition(|t| t.inner_impl().kind.is_blanket());
 
         render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl);
     }
diff --git a/tests/rustdoc/issue-32077-type-alias-impls.rs b/tests/rustdoc/issue-32077-type-alias-impls.rs
new file mode 100644
index 00000000000..555d0579bee
--- /dev/null
+++ b/tests/rustdoc/issue-32077-type-alias-impls.rs
@@ -0,0 +1,59 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/32077>.
+
+#![crate_name = "foo"]
+
+pub struct GenericStruct<T>(T);
+
+impl<T> GenericStruct<T> {
+    pub fn on_gen(arg: T) {}
+}
+
+impl GenericStruct<u32> {
+    pub fn on_u32(arg: u32) {}
+}
+
+pub trait Foo {}
+pub trait Bar {}
+
+impl<T> Foo for GenericStruct<T> {}
+impl Bar for GenericStruct<u32> {}
+
+// @has 'foo/type.TypedefStruct.html'
+// We check that we have the implementation of the type alias itself.
+// @has - '//*[@id="impl-TypedefStruct"]/h3' 'impl TypedefStruct'
+// @has - '//*[@id="method.on_alias"]/h4' 'pub fn on_alias()'
+// @has - '//*[@id="impl-GenericStruct%3CT%3E"]/h3' 'impl<T> GenericStruct<T>'
+// @has - '//*[@id="method.on_gen"]/h4' 'pub fn on_gen(arg: T)'
+// @has - '//*[@id="impl-Foo-for-GenericStruct%3CT%3E"]/h3' 'impl<T> Foo for GenericStruct<T>'
+// This trait implementation doesn't match the type alias parameters so shouldn't appear in docs.
+// @!has - '//h3' 'impl Bar for GenericStruct<u32> {}'
+// Same goes for the `Deref` impl.
+// @!has - '//h2' 'Methods from Deref<Target = u32>'
+pub type TypedefStruct = GenericStruct<u8>;
+
+impl TypedefStruct {
+    pub fn on_alias() {}
+}
+
+impl std::ops::Deref for GenericStruct<u32> {
+    type Target = u32;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+pub struct Wrap<T>(GenericStruct<T>);
+
+// @has 'foo/type.Alias.html'
+// @has - '//h2' 'Methods from Deref<Target = u32>'
+// @has - '//*[@id="impl-Deref-for-Wrap%3CT%3E"]/h3' 'impl<T> Deref for Wrap<T>'
+pub type Alias = Wrap<u32>;
+
+impl<T> std::ops::Deref for Wrap<T> {
+    type Target = GenericStruct<T>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
diff --git a/tests/ui/privacy/private-bounds-locally-allowed.rs b/tests/ui/privacy/private-bounds-locally-allowed.rs
new file mode 100644
index 00000000000..96a007a64f6
--- /dev/null
+++ b/tests/ui/privacy/private-bounds-locally-allowed.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: --crate-type=lib
+
+#[allow(private_bounds)]
+pub trait Foo: FooImpl {}
+
+trait FooImpl {}
diff --git a/tests/ui/unsized/issue-115203.rs b/tests/ui/unsized/issue-115203.rs
new file mode 100644
index 00000000000..5fe7bd64288
--- /dev/null
+++ b/tests/ui/unsized/issue-115203.rs
@@ -0,0 +1,11 @@
+// compile-flags: --emit link
+
+fn main() {
+    let a: [i32; 0] = [];
+    match [a[..]] {
+        //~^ ERROR cannot move a value of type `[i32]
+        //~| ERROR cannot move out of type `[i32]`, a non-copy slice
+        [[]] => (),
+        _ => (),
+    }
+}
diff --git a/tests/ui/unsized/issue-115203.stderr b/tests/ui/unsized/issue-115203.stderr
new file mode 100644
index 00000000000..3ee734988c5
--- /dev/null
+++ b/tests/ui/unsized/issue-115203.stderr
@@ -0,0 +1,19 @@
+error[E0161]: cannot move a value of type `[i32]`
+  --> $DIR/issue-115203.rs:5:12
+   |
+LL |     match [a[..]] {
+   |            ^^^^^ the size of `[i32]` cannot be statically determined
+
+error[E0508]: cannot move out of type `[i32]`, a non-copy slice
+  --> $DIR/issue-115203.rs:5:12
+   |
+LL |     match [a[..]] {
+   |            ^^^^^
+   |            |
+   |            cannot move out of here
+   |            move occurs because value has type `[i32]`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0161, E0508.
+For more information about an error, try `rustc --explain E0161`.