Skip to content

Commit

Permalink
Auto merge of #115787 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
[stable] 1.72.1 release

This backports:

*  Remove assert that checks type equality #115215
*  implied bounds: do not ICE on unconstrained region vars #115559
*  rustdoc: correctly deal with self ty params when eliding default object lifetimes #115276
*  Stop emitting non-power-of-two vectors in (non-portable-SIMD) codegen #115236
*  Normalize before checking if local is freeze in deduced_param_attrs #114948

Some cherry-picks required merge conflict resolution, we'll see if I got it right based on CI (rustdoc fix and LLVM codegen test).

r? `@Mark-Simulacrum`
  • Loading branch information
bors committed Sep 13, 2023
2 parents 5680fa1 + 7900923 commit d5c2e9c
Show file tree
Hide file tree
Showing 21 changed files with 414 additions and 56 deletions.
10 changes: 10 additions & 0 deletions RELEASES.md
@@ -1,3 +1,13 @@
Version 1.72.1 (2023-09-14)
===========================

- [Adjust codegen change to improve LLVM codegen](https://github.com/rust-lang/rust/pull/115236)
- [rustdoc: Fix self ty params in objects with lifetimes](https://github.com/rust-lang/rust/pull/115276)
- [Fix regression in compile times](https://github.com/rust-lang/rust/pull/114948)
- Resolve some ICE regressions in the compiler:
- [#115215](https://github.com/rust-lang/rust/pull/115215)
- [#115559](https://github.com/rust-lang/rust/pull/115559)

Version 1.72.0 (2023-08-24)
==========================

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/type_of.rs
Expand Up @@ -431,7 +431,11 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {

// Vectors, even for non-power-of-two sizes, have the same layout as
// arrays but don't count as aggregate types
// While LLVM theoretically supports non-power-of-two sizes, and they
// often work fine, sometimes x86-isel deals with them horribly
// (see #115212) so for now only use power-of-two ones.
if let FieldsShape::Array { count, .. } = self.layout.fields()
&& count.is_power_of_two()
&& let element = self.field(cx, 0)
&& element.ty.is_integral()
{
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/mir/locals.rs
Expand Up @@ -7,7 +7,6 @@ use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use std::ops::{Index, IndexMut};

pub(super) struct Locals<'tcx, V> {
values: IndexVec<mir::Local, LocalRef<'tcx, V>>,
}
Expand Down Expand Up @@ -36,17 +35,18 @@ impl<'tcx, V> Locals<'tcx, V> {
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub(super) fn initialize_locals(&mut self, values: Vec<LocalRef<'tcx, Bx::Value>>) {
assert!(self.locals.values.is_empty());

// FIXME(#115215): After #115025 get's merged this might not be necessary
for (local, value) in values.into_iter().enumerate() {
match value {
LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (),
LocalRef::Operand(op) => {
let local = mir::Local::from_usize(local);
let expected_ty = self.monomorphize(self.mir.local_decls[local].ty);
assert_eq!(expected_ty, op.layout.ty, "unexpected initial operand type");
if expected_ty != op.layout.ty {
warn!("Unexpected initial operand type. See the issues/114858");
}
}
}

self.locals.values.push(value);
}
}
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_mir_transform/src/deduce_param_attrs.rs
Expand Up @@ -203,7 +203,12 @@ pub fn deduced_param_attrs<'tcx>(
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
|(arg_index, local_decl)| DeducedParamAttrs {
read_only: !deduce_read_only.mutable_args.contains(arg_index)
&& local_decl.ty.is_freeze(tcx, param_env),
// We must normalize here to reveal opaques and normalize
// their substs, otherwise we'll see exponential blow-up in
// compile times: #113372
&& tcx
.normalize_erasing_regions(param_env, local_decl.ty)
.is_freeze(tcx, param_env),
},
),
);
Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
Expand Up @@ -57,16 +57,12 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
let ty = OpportunisticRegionResolver::new(self).fold_ty(ty);

// We do not expect existential variables in implied bounds.
// We may however encounter unconstrained lifetime variables in invalid
// code. See #110161 for context.
// We may however encounter unconstrained lifetime variables
// in very rare cases.
//
// See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for
// an example.
assert!(!ty.has_non_region_infer());
if ty.has_infer() {
self.tcx.sess.delay_span_bug(
self.tcx.def_span(body_id),
"skipped implied_outlives_bounds due to unconstrained lifetimes",
);
return vec![];
}

let mut canonical_var_values = OriginalQueryValues::default();
let canonical_ty =
Expand Down
2 changes: 1 addition & 1 deletion src/ci/docker/host-x86_64/arm-android/Dockerfile
@@ -1,4 +1,4 @@
FROM ubuntu:22.10
FROM ubuntu:23.04

ARG DEBIAN_FRONTEND=noninteractive
COPY scripts/android-base-apt-get.sh /scripts/
Expand Down
2 changes: 1 addition & 1 deletion src/ci/docker/host-x86_64/dist-android/Dockerfile
@@ -1,4 +1,4 @@
FROM ubuntu:22.10
FROM ubuntu:23.04

COPY scripts/android-base-apt-get.sh /scripts/
RUN sh /scripts/android-base-apt-get.sh
Expand Down
Expand Up @@ -2,5 +2,5 @@

set -ex

curl https://static.redox-os.org/toolchain/x86_64-unknown-redox/relibc-install.tar.gz | \
curl https://ci-mirrors.rust-lang.org/rustc/2022-11-27-relibc-install.tar.gz | \
tar --extract --gzip --directory /usr/local
2 changes: 1 addition & 1 deletion src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
@@ -1,4 +1,4 @@
FROM ubuntu:22.10
FROM ubuntu:23.04

ARG DEBIAN_FRONTEND=noninteractive

Expand Down
34 changes: 23 additions & 11 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -167,8 +167,7 @@ fn clean_generic_bound<'tcx>(
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(cx.tcx, def_id));

let generic_args = clean_generic_args(generic_args, cx);
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
else {
let GenericArgs::AngleBracketed { bindings, .. } = generic_args else {
bug!("clean: parenthesized `GenericBound::LangItemTrait`");
};

Expand Down Expand Up @@ -1818,33 +1817,46 @@ fn can_elide_trait_object_lifetime_bound<'tcx>(
#[derive(Debug)]
pub(crate) enum ContainerTy<'tcx> {
Ref(ty::Region<'tcx>),
Regular { ty: DefId, substs: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, arg: usize },
Regular {
ty: DefId,
args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
has_self: bool,
arg: usize,
},
}

impl<'tcx> ContainerTy<'tcx> {
fn object_lifetime_default(self, tcx: TyCtxt<'tcx>) -> ObjectLifetimeDefault<'tcx> {
match self {
Self::Ref(region) => ObjectLifetimeDefault::Arg(region),
Self::Regular { ty: container, substs, arg: index } => {
Self::Regular { ty: container, args, has_self, arg: index } => {
let (DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::TyAlias
| DefKind::Trait
| DefKind::AssocTy
| DefKind::Variant) = tcx.def_kind(container)
| DefKind::TyAlias { .. }
| DefKind::Trait) = tcx.def_kind(container)
else {
return ObjectLifetimeDefault::Empty;
};

let generics = tcx.generics_of(container);
let param = generics.params[index].def_id;
let default = tcx.object_lifetime_default(param);
debug_assert_eq!(generics.parent_count, 0);

// If the container is a trait object type, the arguments won't contain the self type but the
// generics of the corresponding trait will. In such a case, offset the index by one.
// For comparison, if the container is a trait inside a bound, the arguments do contain the
// self type.
let offset =
if !has_self && generics.parent.is_none() && generics.has_self { 1 } else { 0 };
let param = generics.params[index + offset].def_id;

let default = tcx.object_lifetime_default(param);
match default {
rbv::ObjectLifetimeDefault::Param(lifetime) => {
// The index is relative to the parent generics but since we don't have any,
// we don't need to translate it.
let index = generics.param_def_id_to_index[&lifetime];
let arg = substs.skip_binder()[index as usize].expect_region();
let arg = args.skip_binder()[index as usize].expect_region();
ObjectLifetimeDefault::Arg(arg)
}
rbv::ObjectLifetimeDefault::Empty => ObjectLifetimeDefault::Empty,
Expand Down
19 changes: 8 additions & 11 deletions src/librustdoc/clean/utils.rs
Expand Up @@ -54,8 +54,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
let primitives = local_crate.primitives(cx.tcx);
let keywords = local_crate.keywords(cx.tcx);
{
let ItemKind::ModuleItem(ref mut m) = *module.kind
else { unreachable!() };
let ItemKind::ModuleItem(ref mut m) = *module.kind else { unreachable!() };
m.items.extend(primitives.iter().map(|&(def_id, prim)| {
Item::from_def_id_and_parts(
def_id,
Expand All @@ -74,18 +73,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {

pub(crate) fn substs_to_args<'tcx>(
cx: &mut DocContext<'tcx>,
substs: ty::Binder<'tcx, &'tcx [ty::subst::GenericArg<'tcx>]>,
mut skip_first: bool,
args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
has_self: bool,
container: Option<DefId>,
) -> Vec<GenericArg> {
let mut skip_first = has_self;
let mut ret_val =
Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
1
} else {
0
}));
Vec::with_capacity(args.skip_binder().len().saturating_sub(if skip_first { 1 } else { 0 }));

ret_val.extend(substs.iter().enumerate().filter_map(|(index, kind)| {
ret_val.extend(args.iter().enumerate().filter_map(|(index, kind)| {
match kind.skip_binder().unpack() {
GenericArgKind::Lifetime(lt) => {
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
Expand All @@ -100,7 +96,8 @@ pub(crate) fn substs_to_args<'tcx>(
None,
container.map(|container| crate::clean::ContainerTy::Regular {
ty: container,
substs,
args,
has_self,
arg: index,
}),
))),
Expand Down
2 changes: 1 addition & 1 deletion src/version
@@ -1 +1 @@
1.72.0
1.72.1
21 changes: 15 additions & 6 deletions tests/codegen/mem-replace-simple-type.rs
Expand Up @@ -34,12 +34,21 @@ pub fn replace_ref_str<'a>(r: &mut &'a str, v: &'a str) -> &'a str {
}

#[no_mangle]
// CHECK-LABEL: @replace_short_array(
pub fn replace_short_array(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] {
// CHECK-LABEL: @replace_short_array_3(
pub fn replace_short_array_3(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] {
// CHECK-NOT: alloca
// CHECK: %[[R:.+]] = load <3 x i32>, ptr %r, align 4
// CHECK: store <3 x i32> %[[R]], ptr %0
// CHECK: %[[V:.+]] = load <3 x i32>, ptr %v, align 4
// CHECK: store <3 x i32> %[[V]], ptr %r
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %0, ptr align 4 %r, i64 12, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %r, ptr align 4 %v, i64 12, i1 false)
std::mem::replace(r, v)
}

#[no_mangle]
// CHECK-LABEL: @replace_short_array_4(
pub fn replace_short_array_4(r: &mut [u32; 4], v: [u32; 4]) -> [u32; 4] {
// CHECK-NOT: alloca
// CHECK: %[[R:.+]] = load <4 x i32>, ptr %r, align 4
// CHECK: store <4 x i32> %[[R]], ptr %0
// CHECK: %[[V:.+]] = load <4 x i32>, ptr %v, align 4
// CHECK: store <4 x i32> %[[V]], ptr %r
std::mem::replace(r, v)
}
33 changes: 24 additions & 9 deletions tests/codegen/swap-small-types.rs
Expand Up @@ -11,11 +11,12 @@ type RGB48 = [u16; 3];
// CHECK-LABEL: @swap_rgb48_manually(
#[no_mangle]
pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) {
// CHECK-NOT: alloca
// CHECK: %[[TEMP0:.+]] = load <3 x i16>, ptr %x, align 2
// CHECK: %[[TEMP1:.+]] = load <3 x i16>, ptr %y, align 2
// CHECK: store <3 x i16> %[[TEMP1]], ptr %x, align 2
// CHECK: store <3 x i16> %[[TEMP0]], ptr %y, align 2
// FIXME: See #115212 for why this has an alloca again

// CHECK: alloca [3 x i16], align 2
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)

let temp = *x;
*x = *y;
Expand All @@ -25,11 +26,25 @@ pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) {
// CHECK-LABEL: @swap_rgb48
#[no_mangle]
pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) {
// FIXME: See #115212 for why this has an alloca again

// CHECK: alloca [3 x i16], align 2
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
swap(x, y)
}

type RGBA64 = [u16; 4];

// CHECK-LABEL: @swap_rgba64
#[no_mangle]
pub fn swap_rgba64(x: &mut RGBA64, y: &mut RGBA64) {
// CHECK-NOT: alloca
// CHECK: load <3 x i16>
// CHECK: load <3 x i16>
// CHECK: store <3 x i16>
// CHECK: store <3 x i16>
// CHECK-DAG: %[[XVAL:.+]] = load <4 x i16>, ptr %x, align 2
// CHECK-DAG: %[[YVAL:.+]] = load <4 x i16>, ptr %y, align 2
// CHECK-DAG: store <4 x i16> %[[YVAL]], ptr %x, align 2
// CHECK-DAG: store <4 x i16> %[[XVAL]], ptr %y, align 2
swap(x, y)
}

Expand Down
19 changes: 19 additions & 0 deletions tests/rustdoc/inline_cross/auxiliary/dyn_trait.rs
Expand Up @@ -65,3 +65,22 @@ pub trait HigherRankedBoundTrait1<'e> where for<'l> Self: 'e + 'l {}
pub trait AmbiguousBoundTrait<'a, 'b>: 'a + 'b {}

pub struct AmbiguousBoundWrapper<'a, 'b, T: ?Sized + 'a + 'b>(&'a T, &'b T);

// Trait objects inside of another trait object, a trait bound or an associated type.

pub trait Inner {}
pub trait Outer<T: ?Sized> {}
pub trait Base {
type Type<T: ?Sized>;
}
impl Base for () {
type Type<T: ?Sized> = ();
}

pub type NestedTraitObjects = dyn Outer<dyn Inner>;

pub fn apit_rpit(o: impl Outer<dyn Inner>) -> impl Outer<dyn Inner> {
o
}

pub type AssocTy = <() as Base>::Type<dyn Inner>;
15 changes: 15 additions & 0 deletions tests/rustdoc/inline_cross/dyn_trait.rs
Expand Up @@ -128,3 +128,18 @@ pub use dyn_trait::BareAmbiguousBoundEarly1;
// @has user/type.BareAmbiguousBoundStatic.html
// @has - '//*[@class="rust item-decl"]//code' "dyn AmbiguousBoundTrait<'o, 'o> + 'static;"
pub use dyn_trait::BareAmbiguousBoundStatic;

// Regression test for issue #115179:

// @has user/type.NestedTraitObjects.html
// @has - '//*[@class="rust item-decl"]//code' "dyn Outer<dyn Inner>;"
pub use dyn_trait::NestedTraitObjects;

// @has user/fn.apit_rpit.html
// @has - '//pre[@class="rust item-decl"]' \
// "apit_rpit(o: impl Outer<dyn Inner>) -> impl Outer<dyn Inner>"
pub use dyn_trait::apit_rpit;

// @has user/type.AssocTy.html
// @has - '//*[@class="rust item-decl"]//code' "<() as Base>::Type<dyn Inner>"
pub use dyn_trait::AssocTy;

0 comments on commit d5c2e9c

Please sign in to comment.