Auto merge of #115672 - GuillaumeGomez:rollup-mjiy56f, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - #104299 (Clarify stability guarantee for lifetimes in enum discriminants) - #115088 (Fix Step Skipping Caused by Using the `--exclude` Option) - #115201 (rustdoc: list matching impls on type aliases) - #115633 (Lint node for `PRIVATE_BOUNDS`/`PRIVATE_INTERFACES` is the item which names the private type) - #115638 (`-Cllvm-args` usability improvement) - #115643 (fix: return early when has tainted in mir-lint) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
309af3442a
@ -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) {
|
||||
|
@ -39,6 +39,10 @@
|
||||
|
||||
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;
|
||||
|
@ -1463,14 +1463,15 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
|
||||
};
|
||||
|
||||
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 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
|
||||
};
|
||||
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,
|
||||
|
@ -1126,6 +1126,11 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
///
|
||||
/// [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
|
||||
|
@ -109,7 +109,7 @@ pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
|
||||
/// 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 @@ pub const fn cast_const(self) -> *const 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 @@ pub fn to_bits(self) -> usize
|
||||
/// 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 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
|
||||
///
|
||||
/// 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 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
|
||||
///
|
||||
/// 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 @@ pub fn mask(self, mask: usize) -> *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 @@ pub fn mask(self, mask: usize) -> *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 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
|
||||
///
|
||||
/// This function is the inverse of [`offset`].
|
||||
///
|
||||
/// [`offset`]: #method.offset-1
|
||||
/// [`offset`]: pointer#method.offset-1
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
@ -2064,7 +2064,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
|
||||
///
|
||||
/// 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
|
||||
|
@ -302,8 +302,10 @@ fn from<S: Step>(kind: Kind) -> 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;
|
||||
}
|
||||
|
||||
|
@ -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>());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -54,6 +54,7 @@
|
||||
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 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);
|
||||
}
|
||||
|
59
tests/rustdoc/issue-32077-type-alias-impls.rs
Normal file
59
tests/rustdoc/issue-32077-type-alias-impls.rs
Normal file
@ -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
|
||||
}
|
||||
}
|
7
tests/ui/privacy/private-bounds-locally-allowed.rs
Normal file
7
tests/ui/privacy/private-bounds-locally-allowed.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// check-pass
|
||||
// compile-flags: --crate-type=lib
|
||||
|
||||
#[allow(private_bounds)]
|
||||
pub trait Foo: FooImpl {}
|
||||
|
||||
trait FooImpl {}
|
11
tests/ui/unsized/issue-115203.rs
Normal file
11
tests/ui/unsized/issue-115203.rs
Normal file
@ -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
|
||||
[[]] => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
19
tests/ui/unsized/issue-115203.stderr
Normal file
19
tests/ui/unsized/issue-115203.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user