From fa125e2be682e22cf0c2a005a08d7fef2520cefa Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 21 Sep 2024 01:51:26 +0900 Subject: [PATCH 1/7] Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly --- compiler/rustc_codegen_gcc/src/asm.rs | 8 ++ compiler/rustc_codegen_llvm/src/asm.rs | 6 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/asm/mod.rs | 29 ++++- compiler/rustc_target/src/asm/s390x.rs | 111 ++++++++++++++++-- .../asm-experimental-arch.md | 7 ++ tests/codegen/asm-s390x-clobbers.rs | 50 ++++++++ 7 files changed, 200 insertions(+), 12 deletions(-) create mode 100644 tests/codegen/asm-s390x-clobbers.rs diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 13a00f7e08d80..a04cd4735f478 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -682,6 +682,11 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::S390x( + S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg, + ) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Err => unreachable!(), }, }; @@ -757,6 +762,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr, ) => cx.type_i32(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 430ba7352433b..27f6481c5360e 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -703,6 +703,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> S390x(S390xInlineAsmRegClass::reg) => "r", S390x(S390xInlineAsmRegClass::reg_addr) => "a", S390x(S390xInlineAsmRegClass::freg) => "f", + S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } Msp430(Msp430InlineAsmRegClass::reg) => "r", M68k(M68kInlineAsmRegClass::reg) => "r", M68k(M68kInlineAsmRegClass::reg_addr) => "a", @@ -861,6 +864,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(), S390x(S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr) => cx.type_i32(), S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), + S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 402232a1720b7..e2d965ff91b1d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -410,6 +410,7 @@ symbols! { arbitrary_enum_discriminant, arbitrary_self_types, arbitrary_self_types_pointers, + areg, args, arith_offset, arm, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 4d8c5cea8a830..df13d24cb9e21 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -439,7 +439,7 @@ impl InlineAsmReg { Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), Self::LoongArch(_) => cb(self), Self::Mips(_) => cb(self), - Self::S390x(_) => cb(self), + Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), Self::Msp430(_) => cb(self), @@ -892,6 +892,7 @@ pub enum InlineAsmClobberAbi { AArch64NoX18, RiscV, LoongArch, + S390x, } impl InlineAsmClobberAbi { @@ -941,6 +942,10 @@ impl InlineAsmClobberAbi { "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch), _ => Err(&["C", "system"]), }, + InlineAsmArch::S390x => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::S390x), + _ => Err(&["C", "system"]), + }, _ => Err(&[]), } } @@ -1098,6 +1103,28 @@ impl InlineAsmClobberAbi { f16, f17, f18, f19, f20, f21, f22, f23, } }, + InlineAsmClobberAbi::S390x => clobbered_regs! { + S390x S390xInlineAsmReg { + r0, r1, r2, r3, r4, r5, + r14, + + // f0-f7, v0-v7 + f0, f1, f2, f3, f4, f5, f6, f7, + v0, v1, v2, v3, v4, v5, v6, v7, + + // Technically the left halves of v8-v15 (i.e., f8-f15) are saved, but + // we have no way of expressing this using clobbers. + v8, v9, v10, v11, v12, v13, v14, v15, + + // Other vector registers are volatile + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + + // a0-a1 are reserved, other access registers are volatile + a2, a3, a4, a5, a6, a7, + a8, a9, a10, a11, a12, a13, a14, a15, + } + }, } } } diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 4258b23ac57eb..9b31190a72ba4 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -9,6 +9,8 @@ def_reg_class! { reg, reg_addr, freg, + vreg, + areg, } } @@ -35,11 +37,13 @@ impl S390xInlineAsmRegClass { pub fn supported_types( self, - arch: InlineAsmArch, + _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option)] { - match (self, arch) { - (Self::reg | Self::reg_addr, _) => types! { _: I8, I16, I32, I64; }, - (Self::freg, _) => types! { _: F32, F64; }, + match self { + Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; }, + Self::freg => types! { _: F32, F64; }, + Self::vreg => &[], + Self::areg => &[], } } } @@ -76,6 +80,52 @@ def_regs! { f13: freg = ["f13"], f14: freg = ["f14"], f15: freg = ["f15"], + v0: vreg = ["v0"], + v1: vreg = ["v1"], + v2: vreg = ["v2"], + v3: vreg = ["v3"], + v4: vreg = ["v4"], + v5: vreg = ["v5"], + v6: vreg = ["v6"], + v7: vreg = ["v7"], + v8: vreg = ["v8"], + v9: vreg = ["v9"], + v10: vreg = ["v10"], + v11: vreg = ["v11"], + v12: vreg = ["v12"], + v13: vreg = ["v13"], + v14: vreg = ["v14"], + v15: vreg = ["v15"], + v16: vreg = ["v16"], + v17: vreg = ["v17"], + v18: vreg = ["v18"], + v19: vreg = ["v19"], + v20: vreg = ["v20"], + v21: vreg = ["v21"], + v22: vreg = ["v22"], + v23: vreg = ["v23"], + v24: vreg = ["v24"], + v25: vreg = ["v25"], + v26: vreg = ["v26"], + v27: vreg = ["v27"], + v28: vreg = ["v28"], + v29: vreg = ["v29"], + v30: vreg = ["v30"], + v31: vreg = ["v31"], + a2: areg = ["a2"], + a3: areg = ["a3"], + a4: areg = ["a4"], + a5: areg = ["a5"], + a6: areg = ["a6"], + a7: areg = ["a7"], + a8: areg = ["a8"], + a9: areg = ["a9"], + a10: areg = ["a10"], + a11: areg = ["a11"], + a12: areg = ["a12"], + a13: areg = ["a13"], + a14: areg = ["a14"], + a15: areg = ["a15"], #error = ["r11"] => "The frame pointer cannot be used as an operand for inline asm", #error = ["r15"] => @@ -87,13 +137,8 @@ def_regs! { "c12", "c13", "c14", "c15" ] => "control registers are reserved by the kernel and cannot be used as operands for inline asm", - #error = [ - "a0", "a1", "a2", "a3", - "a4", "a5", "a6", "a7", - "a8", "a9", "a10", "a11", - "a12", "a13", "a14", "a15" - ] => - "access registers are not supported and cannot be used as operands for inline asm", + #error = ["a0", "a1"] => + "a0 and a1 are reserved for system use and cannot be used as operands for inline asm", } } @@ -106,4 +151,48 @@ impl S390xInlineAsmReg { ) -> fmt::Result { write!(out, "%{}", self.name()) } + + pub fn overlapping_regs(self, mut cb: impl FnMut(S390xInlineAsmReg)) { + macro_rules! reg_conflicts { + ( + $( + $full:ident : $($field:ident)* + ),*; + ) => { + match self { + $( + Self::$full => { + cb(Self::$full); + $(cb(Self::$field);)* + } + $(Self::$field)|* => { + cb(Self::$full); + cb(self); + } + )* + r => cb(r), + } + }; + } + + // The left halves of v0-v15 are aliased to f0-f15. + reg_conflicts! { + v0 : f0, + v1 : f1, + v2 : f2, + v3 : f3, + v4 : f4, + v5 : f5, + v6 : f6, + v7 : f7, + v8 : f8, + v9 : f9, + v10 : f10, + v11 : f11, + v12 : f12, + v13 : f13, + v14 : f14, + v15 : f15; + } + } } diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 43e11b6d57dcb..b1c429c7676ef 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -51,7 +51,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `reg` | `r[0-31]` | `r` | | CSKY | `freg` | `f[0-31]` | `f` | | s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | +| s390x | `reg_addr` | `r[1-10]`, `r[12-14]` | `a` | | s390x | `freg` | `f[0-15]` | `f` | +| s390x | `vreg` | `v[0-31]` | Only clobbers | +| s390x | `areg` | `a[2-15]` | Only clobbers | | Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` | | Arm64EC | `vreg` | `v[0-15]` | `w` | | Arm64EC | `vreg_low16` | `v[0-15]` | `x` | @@ -90,6 +93,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `freg` | None | `f32`, | | s390x | `reg`, `reg_addr` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | +| s390x | `vreg` | N/A | Only clobbers | +| s390x | `areg` | N/A | Only clobbers | | Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | Arm64EC | `vreg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | @@ -157,6 +162,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `r15` | This is the link register. | | CSKY | `r[26-30]` | Reserved by its ABI. | | CSKY | `r31` | This is the TLS register. | +| s390x | `c[0-15]` | Reserved by the kernel. | +| s390x | `a[0-1]` | Reserved for system use. | | Arm64EC | `xzr` | This is a constant zero register which can't be modified. | | Arm64EC | `x18` | This is an OS-reserved register. | | Arm64EC | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]` | These are AArch64 registers that are not supported for Arm64EC. | diff --git a/tests/codegen/asm-s390x-clobbers.rs b/tests/codegen/asm-s390x-clobbers.rs new file mode 100644 index 0000000000000..45f72206bdfab --- /dev/null +++ b/tests/codegen/asm-s390x-clobbers.rs @@ -0,0 +1,50 @@ +//@ revisions: s390x +//@[s390x] compile-flags: --target s390x-unknown-linux-gnu +//@[s390x] needs-llvm-components: systemz + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @cc_clobber +// CHECK: call void asm sideeffect "", "~{cc}"() +#[no_mangle] +pub unsafe fn cc_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @a2_clobber +// CHECK: call void asm sideeffect "", "~{a2}"() +#[no_mangle] +pub unsafe fn a2_clobber() { + asm!("", out("a2") _, options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @v0_clobber +// CHECK: call void asm sideeffect "", "~{v0}"() +#[no_mangle] +pub unsafe fn v0_clobber() { + asm!("", out("v0") _, options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// CHECK: asm sideeffect "", "={r0},={r1},={r2},={r3},={r4},={r5},={r14},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31},~{a2},~{a3},~{a4},~{a5},~{a6},~{a7},~{a8},~{a9},~{a10},~{a11},~{a12},~{a13},~{a14},~{a15}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} From af3f212453f667981bb07c0029f86bc607f3baa9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 17:51:38 -0400 Subject: [PATCH 2/7] Instantiate binders in supertrait_vtable_slot --- .../src/traits/vtable.rs | 40 ++++++++++++++----- .../higher-ranked-upcasting-ok.rs | 15 +++---- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index a2760fe6049b0..5aed55ef2d27d 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -2,6 +2,8 @@ use std::fmt::Debug; use std::ops::ControlFlow; use rustc_hir::def_id::DefId; +use rustc_infer::infer::{BoundRegionConversionTime, TyCtxtInferExt}; +use rustc_infer::traits::ObligationCause; use rustc_infer::traits::util::PredicateSet; use rustc_middle::bug; use rustc_middle::query::Providers; @@ -13,7 +15,7 @@ use smallvec::{SmallVec, smallvec}; use tracing::debug; use crate::errors::DumpVTableEntries; -use crate::traits::{impossible_predicates, is_vtable_safe_method}; +use crate::traits::{ObligationCtxt, impossible_predicates, is_vtable_safe_method}; #[derive(Clone, Debug)] pub enum VtblSegment<'tcx> { @@ -383,17 +385,37 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( let ty::Dynamic(target, _, _) = *target.kind() else { bug!(); }; - let target_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal()?) - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let target_principal = target.principal()?.with_self_ty(tcx, tcx.types.trait_object_dummy_self); // Given that we have a target principal, it is a bug for there not to be a source principal. let ty::Dynamic(source, _, _) = *source.kind() else { bug!(); }; - let source_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap()) - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let source_principal = + source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self); + + let infcx = tcx.infer_ctxt().build(); + let param_env = ty::ParamEnv::reveal_all(); + let trait_refs_are_compatible = + |source: ty::PolyTraitRef<'tcx>, target: ty::PolyTraitRef<'tcx>| { + infcx.probe(|_| { + let ocx = ObligationCtxt::new(&infcx); + let source = ocx.normalize(&ObligationCause::dummy(), param_env, source); + let target = ocx.normalize(&ObligationCause::dummy(), param_env, target); + infcx.enter_forall(target, |target| { + let source = infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + source, + ); + let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, target, source) + else { + return false; + }; + ocx.select_all_or_error().is_empty() + }) + }) + }; let vtable_segment_callback = { let mut vptr_offset = 0; @@ -404,9 +426,7 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( } VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len(); - if tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), trait_ref) - == target_principal - { + if trait_refs_are_compatible(trait_ref, target_principal) { if emit_vptr { return ControlFlow::Break(Some(vptr_offset)); } else { diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs index 7f793e1269fd7..c4c070e49fdb7 100644 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs +++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs @@ -1,21 +1,22 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@ check-pass +//@ build-pass -// We should be able to instantiate a binder during trait upcasting. -// This test could be `check-pass`, but we should make sure that we -// do so in both trait solvers. +// Check that we are able to instantiate a binder during trait upcasting, +// and that it doesn't cause any issues with codegen either. #![feature(trait_upcasting)] trait Supertrait<'a, 'b> {} trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {} -impl<'a> Supertrait<'a, 'a> for () {} -impl<'a> Subtrait<'a, 'a> for () {} +impl Supertrait<'_, '_> for () {} +impl Subtrait<'_, '_> for () {} fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> { x } -fn main() {} +fn main() { + ok(&()); +} From d87e0ca497e70fe1c3112de0dce87fbd777f6451 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 Sep 2024 13:14:44 -0400 Subject: [PATCH 3/7] Extract trait_refs_are_compatible, make it instantiate binders --- .../src/traits/engine.rs | 17 ++++- .../src/traits/vtable.rs | 75 ++++++++++++------- 2 files changed, 64 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index de1d4ef15aced..d562692c1a865 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -9,12 +9,13 @@ use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace}; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast, Variance}; +use rustc_type_ir::relate::Relate; use super::{FromSolverError, FulfillmentContext, ScrubbedTraitError, TraitEngine}; use crate::error_reporting::InferCtxtErrorExt; @@ -133,6 +134,20 @@ where .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + pub fn eq_trace>>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + trace: TypeTrace<'tcx>, + expected: T, + actual: T, + ) -> Result<(), TypeError<'tcx>> { + self.infcx + .at(cause, param_env) + .eq_trace(DefineOpaqueTypes::Yes, trace, expected, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + /// Checks whether `expected` is a subtype of `actual`: `expected <: actual`. pub fn sub>( &self, diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 5aed55ef2d27d..4f13524706b2d 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -2,6 +2,7 @@ use std::fmt::Debug; use std::ops::ControlFlow; use rustc_hir::def_id::DefId; +use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::{BoundRegionConversionTime, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::util::PredicateSet; @@ -24,6 +25,8 @@ pub enum VtblSegment<'tcx> { } /// Prepare the segments for a vtable +// FIXME: This should take a `PolyExistentialTraitRef`, since we don't care +// about our `Self` type here. pub fn prepare_vtable_segments<'tcx, T>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, @@ -385,7 +388,7 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( let ty::Dynamic(target, _, _) = *target.kind() else { bug!(); }; - let target_principal = target.principal()?.with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let target_principal = target.principal()?; // Given that we have a target principal, it is a bug for there not to be a source principal. let ty::Dynamic(source, _, _) = *source.kind() else { @@ -394,29 +397,6 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( let source_principal = source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self); - let infcx = tcx.infer_ctxt().build(); - let param_env = ty::ParamEnv::reveal_all(); - let trait_refs_are_compatible = - |source: ty::PolyTraitRef<'tcx>, target: ty::PolyTraitRef<'tcx>| { - infcx.probe(|_| { - let ocx = ObligationCtxt::new(&infcx); - let source = ocx.normalize(&ObligationCause::dummy(), param_env, source); - let target = ocx.normalize(&ObligationCause::dummy(), param_env, target); - infcx.enter_forall(target, |target| { - let source = infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - source, - ); - let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, target, source) - else { - return false; - }; - ocx.select_all_or_error().is_empty() - }) - }) - }; - let vtable_segment_callback = { let mut vptr_offset = 0; move |segment| { @@ -424,9 +404,15 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( VtblSegment::MetadataDSA => { vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len(); } - VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len(); - if trait_refs_are_compatible(trait_ref, target_principal) { + VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => { + vptr_offset += + tcx.own_existential_vtable_entries(vtable_principal.def_id()).len(); + if trait_refs_are_compatible( + tcx, + vtable_principal + .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)), + target_principal, + ) { if emit_vptr { return ControlFlow::Break(Some(vptr_offset)); } else { @@ -446,6 +432,41 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap() } +fn trait_refs_are_compatible<'tcx>( + tcx: TyCtxt<'tcx>, + hr_vtable_principal: ty::PolyExistentialTraitRef<'tcx>, + hr_target_principal: ty::PolyExistentialTraitRef<'tcx>, +) -> bool { + if hr_vtable_principal.def_id() != hr_target_principal.def_id() { + return false; + } + + let infcx = tcx.infer_ctxt().build(); + let param_env = ty::ParamEnv::reveal_all(); + let ocx = ObligationCtxt::new(&infcx); + let hr_source_principal = + ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal); + let hr_target_principal = + ocx.normalize(&ObligationCause::dummy(), param_env, hr_target_principal); + infcx.enter_forall(hr_target_principal, |target_principal| { + let source_principal = infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + hr_source_principal, + ); + let Ok(()) = ocx.eq_trace( + &ObligationCause::dummy(), + param_env, + ToTrace::to_trace(&ObligationCause::dummy(), hr_target_principal, hr_source_principal), + target_principal, + source_principal, + ) else { + return false; + }; + ocx.select_all_or_error().is_empty() + }) +} + pub(super) fn provide(providers: &mut Providers) { *providers = Providers { own_existential_vtable_entries, From 7c552d56b2234018e6aa729cda6bdfbb7d533d28 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 Sep 2024 13:17:31 -0400 Subject: [PATCH 4/7] Also fix first_method_vtable_slot --- .../src/traits/vtable.rs | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 4f13524706b2d..6e6f948a2cdc4 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -332,14 +332,10 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe let ty::Dynamic(source, _, _) = *key.self_ty().kind() else { bug!(); }; - let source_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap()) - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let source_principal = + source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self); - let target_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), key) - // We don't care about the self type, since it will always be the same thing. - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let target_principal = ty::Binder::dummy(ty::ExistentialTraitRef::erase_self_ty(tcx, key)); let vtable_segment_callback = { let mut vptr_offset = 0; @@ -348,15 +344,18 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe VtblSegment::MetadataDSA => { vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len(); } - VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - if tcx - .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref) - == target_principal - { + VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => { + if trait_refs_are_compatible( + tcx, + vtable_principal + .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)), + target_principal, + ) { return ControlFlow::Break(vptr_offset); } - vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len(); + vptr_offset += + tcx.own_existential_vtable_entries(vtable_principal.def_id()).len(); if emit_vptr { vptr_offset += 1; From 91d0752e1698ac393a90b8f3ad58e59d904070d9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 30 Sep 2024 16:56:40 -0700 Subject: [PATCH 5/7] Update wasm-component-ld to 0.5.9 This updates the `wasm-component-ld` linker binary for the `wasm32-wasip2` target to 0.5.9, pulling in a few bug fixes and recent updates. --- Cargo.lock | 48 +++++++++++++------------- src/tools/wasm-component-ld/Cargo.toml | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 582b5a763e6f7..6c1071ccbc226 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5768,16 +5768,16 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-component-ld" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb17cdbc91766d4ea0bcd6026c36ba77a21b5c8199aeb1f0993461fe6a6bec2b" +checksum = "fde17bc96539700198e12516230c76095cc215c84ef39ad206e1af3f84243e0f" dependencies = [ "anyhow", "clap", "lexopt", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.217.0", + "wasmparser 0.218.0", "wat", "wit-component", "wit-parser", @@ -5801,19 +5801,19 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.217.0" +version = "0.218.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b88b0814c9a2b323a9b46c687e726996c255ac8b64aa237dd11c81ed4854760" +checksum = "22b896fa8ceb71091ace9bcb81e853f54043183a1c9667cf93422c40252ffa0a" dependencies = [ "leb128", - "wasmparser 0.217.0", + "wasmparser 0.218.0", ] [[package]] name = "wasm-metadata" -version = "0.217.0" +version = "0.218.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65a146bf9a60e9264f0548a2599aa9656dba9a641eff9ab88299dc2a637e483c" +checksum = "aa5eeb071abe8a2132fdd5565dabffee70775ee8c24fc7e300ac43f51f4a8a91" dependencies = [ "anyhow", "indexmap", @@ -5821,8 +5821,8 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.217.0", - "wasmparser 0.217.0", + "wasm-encoder 0.218.0", + "wasmparser 0.218.0", ] [[package]] @@ -5837,9 +5837,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.217.0" +version = "0.218.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca917a21307d3adf2b9857b94dd05ebf8496bdcff4437a9b9fb3899d3e6c74e7" +checksum = "b09e46c7fceceaa72b2dd1a8a137ea7fd8f93dfaa69806010a709918e496c5dc" dependencies = [ "ahash", "bitflags 2.6.0", @@ -5851,22 +5851,22 @@ dependencies = [ [[package]] name = "wast" -version = "217.0.0" +version = "218.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79004ecebded92d3c710d4841383368c7f04b63d0992ddd6b0c7d5029b7629b7" +checksum = "8a53cd1f0fa505df97557e36a58bddb8296e2fcdcd089529545ebfdb18a1b9d7" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.217.0", + "wasm-encoder 0.218.0", ] [[package]] name = "wat" -version = "1.217.0" +version = "1.218.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c126271c3d92ca0f7c63e4e462e40c69cca52fd4245fcda730d1cf558fb55088" +checksum = "4f87f8e14e776762e07927c27c2054d2cf678aab9aae2d431a79b3e31e4dd391" dependencies = [ "wast", ] @@ -6143,9 +6143,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.217.0" +version = "0.218.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7117809905e49db716d81e794f79590c052bf2fdbbcda1731ca0fb28f6f3ddf" +checksum = "aa53aa7e6bf2b3e8ccaffbcc963fbdb672a603dc0af393a481b6cec24c266406" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -6154,17 +6154,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.217.0", + "wasm-encoder 0.218.0", "wasm-metadata", - "wasmparser 0.217.0", + "wasmparser 0.218.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.217.0" +version = "0.218.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb893dcd6d370cfdf19a0d9adfcd403efb8e544e1a0ea3a8b81a21fe392eaa78" +checksum = "0d3d1066ab761b115f97fef2b191090faabcb0f37b555b758d3caf42d4ed9e55" dependencies = [ "anyhow", "id-arena", @@ -6175,7 +6175,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.217.0", + "wasmparser 0.218.0", ] [[package]] diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 91ff19ad9fcb0..49f4e59650e71 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.4" +wasm-component-ld = "0.5.9" From 4529b86196836ef1efe5c710a8874877d17b9ef8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Oct 2024 11:01:45 +0200 Subject: [PATCH 6/7] make test_lots_of_insertions test take less long in Miri --- library/std/src/collections/hash/map/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index 2599060ef62eb..fa8ea95b89142 100644 --- a/library/std/src/collections/hash/map/tests.rs +++ b/library/std/src/collections/hash/map/tests.rs @@ -274,7 +274,7 @@ fn test_lots_of_insertions() { for _ in 0..loops { assert!(m.is_empty()); - let count = if cfg!(miri) { 101 } else { 1001 }; + let count = if cfg!(miri) { 66 } else { 1001 }; for i in 1..count { assert!(m.insert(i, i).is_none()); From 50a6a3565c10bdb02834a6f25677a09b9a9b4107 Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 1 Oct 2024 14:16:19 +0300 Subject: [PATCH 7/7] add fixme to remove llvm option when minimal version is 19 --- src/bootstrap/src/core/build_steps/llvm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index e4011221286f6..3021358415790 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -344,6 +344,7 @@ impl Step for Llvm { .define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_BENCHMARKS", "OFF") .define("LLVM_INCLUDE_TESTS", enable_tests) + // FIXME: remove this when minimal llvm is 19 .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") .define("LLVM_ENABLE_BINDINGS", "OFF")