Auto merge of #115787 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum
[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`
This commit is contained in:
commit
d5c2e9c342
21 changed files with 414 additions and 56 deletions
10
RELEASES.md
10
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)
|
||||
==========================
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>>,
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:22.10
|
||||
FROM ubuntu:23.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
COPY scripts/android-base-apt-get.sh /scripts/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:22.10
|
||||
FROM ubuntu:23.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
|
|
|
|||
|
|
@ -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`");
|
||||
};
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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())))
|
||||
|
|
@ -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,
|
||||
}),
|
||||
))),
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
1.72.0
|
||||
1.72.1
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
179
tests/ui/async-await/deep-futures-are-freeze.rs
Normal file
179
tests/ui/async-await/deep-futures-are-freeze.rs
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
// build-pass
|
||||
// compile-flags: -Copt-level=s -Clto=fat
|
||||
// no-prefer-dynamic
|
||||
// edition: 2021
|
||||
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
fn main() {
|
||||
spawn(move || main0())
|
||||
}
|
||||
|
||||
fn spawn<F>(future: impl FnOnce() -> F) {
|
||||
future();
|
||||
}
|
||||
|
||||
async fn main0() {
|
||||
main1().await;
|
||||
main2().await;
|
||||
}
|
||||
async fn main1() {
|
||||
main2().await;
|
||||
main3().await;
|
||||
}
|
||||
async fn main2() {
|
||||
main3().await;
|
||||
main4().await;
|
||||
}
|
||||
async fn main3() {
|
||||
main4().await;
|
||||
main5().await;
|
||||
}
|
||||
async fn main4() {
|
||||
main5().await;
|
||||
main6().await;
|
||||
}
|
||||
async fn main5() {
|
||||
main6().await;
|
||||
main7().await;
|
||||
}
|
||||
async fn main6() {
|
||||
main7().await;
|
||||
main8().await;
|
||||
}
|
||||
async fn main7() {
|
||||
main8().await;
|
||||
main9().await;
|
||||
}
|
||||
async fn main8() {
|
||||
main9().await;
|
||||
main10().await;
|
||||
}
|
||||
async fn main9() {
|
||||
main10().await;
|
||||
main11().await;
|
||||
}
|
||||
async fn main10() {
|
||||
main11().await;
|
||||
main12().await;
|
||||
}
|
||||
async fn main11() {
|
||||
main12().await;
|
||||
main13().await;
|
||||
}
|
||||
async fn main12() {
|
||||
main13().await;
|
||||
main14().await;
|
||||
}
|
||||
async fn main13() {
|
||||
main14().await;
|
||||
main15().await;
|
||||
}
|
||||
async fn main14() {
|
||||
main15().await;
|
||||
main16().await;
|
||||
}
|
||||
async fn main15() {
|
||||
main16().await;
|
||||
main17().await;
|
||||
}
|
||||
async fn main16() {
|
||||
main17().await;
|
||||
main18().await;
|
||||
}
|
||||
async fn main17() {
|
||||
main18().await;
|
||||
main19().await;
|
||||
}
|
||||
async fn main18() {
|
||||
main19().await;
|
||||
main20().await;
|
||||
}
|
||||
async fn main19() {
|
||||
main20().await;
|
||||
main21().await;
|
||||
}
|
||||
async fn main20() {
|
||||
main21().await;
|
||||
main22().await;
|
||||
}
|
||||
async fn main21() {
|
||||
main22().await;
|
||||
main23().await;
|
||||
}
|
||||
async fn main22() {
|
||||
main23().await;
|
||||
main24().await;
|
||||
}
|
||||
async fn main23() {
|
||||
main24().await;
|
||||
main25().await;
|
||||
}
|
||||
async fn main24() {
|
||||
main25().await;
|
||||
main26().await;
|
||||
}
|
||||
async fn main25() {
|
||||
main26().await;
|
||||
main27().await;
|
||||
}
|
||||
async fn main26() {
|
||||
main27().await;
|
||||
main28().await;
|
||||
}
|
||||
async fn main27() {
|
||||
main28().await;
|
||||
main29().await;
|
||||
}
|
||||
async fn main28() {
|
||||
main29().await;
|
||||
main30().await;
|
||||
}
|
||||
async fn main29() {
|
||||
main30().await;
|
||||
main31().await;
|
||||
}
|
||||
async fn main30() {
|
||||
main31().await;
|
||||
main32().await;
|
||||
}
|
||||
async fn main31() {
|
||||
main32().await;
|
||||
main33().await;
|
||||
}
|
||||
async fn main32() {
|
||||
main33().await;
|
||||
main34().await;
|
||||
}
|
||||
async fn main33() {
|
||||
main34().await;
|
||||
main35().await;
|
||||
}
|
||||
async fn main34() {
|
||||
main35().await;
|
||||
main36().await;
|
||||
}
|
||||
async fn main35() {
|
||||
main36().await;
|
||||
main37().await;
|
||||
}
|
||||
async fn main36() {
|
||||
main37().await;
|
||||
main38().await;
|
||||
}
|
||||
async fn main37() {
|
||||
main38().await;
|
||||
main39().await;
|
||||
}
|
||||
async fn main38() {
|
||||
main39().await;
|
||||
main40().await;
|
||||
}
|
||||
async fn main39() {
|
||||
main40().await;
|
||||
}
|
||||
async fn main40() {
|
||||
boom(&mut ()).await;
|
||||
}
|
||||
|
||||
async fn boom(f: &mut ()) {}
|
||||
48
tests/ui/codegen/subtyping-enforces-type-equality.rs
Normal file
48
tests/ui/codegen/subtyping-enforces-type-equality.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// ignore-pass
|
||||
// build-pass
|
||||
// edition:2021
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
||||
|
||||
fn main() {
|
||||
let _ = wrapper_call(handler);
|
||||
}
|
||||
|
||||
async fn wrapper_call(handler: impl Handler) {
|
||||
handler.call().await;
|
||||
}
|
||||
async fn handler() {
|
||||
f(&()).await;
|
||||
}
|
||||
async fn f<'a>(db: impl Acquire<'a>) {
|
||||
db.acquire().await;
|
||||
}
|
||||
|
||||
trait Handler {
|
||||
type Future: Future;
|
||||
fn call(self) -> Self::Future;
|
||||
}
|
||||
|
||||
impl<Fut, F> Handler for F
|
||||
where
|
||||
F: Fn() -> Fut,
|
||||
Fut: Future,
|
||||
{
|
||||
type Future = Fut;
|
||||
fn call(self) -> Self::Future {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
trait Acquire<'a> {
|
||||
type Connection;
|
||||
fn acquire(self) -> BoxFuture<Self::Connection>;
|
||||
}
|
||||
impl<'a> Acquire<'a> for &'a () {
|
||||
type Connection = Self;
|
||||
fn acquire(self) -> BoxFuture<Self> {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
1
tests/ui/codegen/subtyping-enforces-type-equality.stderr
Normal file
1
tests/ui/codegen/subtyping-enforces-type-equality.stderr
Normal file
|
|
@ -0,0 +1 @@
|
|||
WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type. See the issues/114858
|
||||
28
tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs
Normal file
28
tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// check-pass
|
||||
|
||||
// Regression test for #112832.
|
||||
pub trait QueryDb {
|
||||
type Db;
|
||||
}
|
||||
|
||||
pub struct QueryTable<Q, DB> {
|
||||
db: DB,
|
||||
storage: Q,
|
||||
}
|
||||
|
||||
// We normalize `<Q as QueryDb>::Db` to `<Q as AsyncQueryFunction<'d>>::SendDb`
|
||||
// using the where-bound. 'd is an unconstrained region variable which previously
|
||||
// triggered an assert.
|
||||
impl<Q> QueryTable<Q, <Q as QueryDb>::Db> where Q: for<'d> AsyncQueryFunction<'d> {}
|
||||
|
||||
pub trait AsyncQueryFunction<'d>: QueryDb<Db = <Self as AsyncQueryFunction<'d>>::SendDb> {
|
||||
type SendDb: 'd;
|
||||
}
|
||||
|
||||
pub trait QueryStorageOpsAsync<Q>
|
||||
where
|
||||
Q: for<'d> AsyncQueryFunction<'d>,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
20
tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs
Normal file
20
tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// check-pass
|
||||
|
||||
// Another minimized regression test for #112832.
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
trait Sub<'a>: Trait<Assoc = <Self as Sub<'a>>::SubAssoc> {
|
||||
type SubAssoc;
|
||||
}
|
||||
|
||||
// By using the where-clause we normalize `<T as Trait>::Assoc` to
|
||||
// `<T as Sub<'a>>::SubAssoc` where `'a` is an unconstrained region
|
||||
// variable.
|
||||
fn foo<T>(x: <T as Trait>::Assoc)
|
||||
where
|
||||
for<'a> T: Sub<'a>,
|
||||
{}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue