Skip to content

Commit

Permalink
Auto merge of #134097 - fmease:rollup-e6kszfd, r=fmease
Browse files Browse the repository at this point in the history
Rollup of 9 pull requests

Successful merges:

 - #133967 ([AIX] Pass -bnoipath when adding rust upstream dynamic crates)
 - #133970 ([AIX] Replace sa_sigaction with sa_union.__su_sigaction for AIX)
 - #133980 ([AIX] Remove option "-n" from AIX "ln" command)
 - #134008 (Make `Copy` unsafe to implement for ADTs with `unsafe` fields)
 - #134017 (Don't use `AsyncFnOnce::CallOnceFuture` bounds for signature deduction)
 - #134023 (handle cygwin environment in `install::sanitize_sh`)
 - #134041 (Use SourceMap to load debugger visualizer files)
 - #134065 (Move `write_graphviz_results`)
 - #134070 (Some asm! diagnostic adjustments and a papercut fix)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Dec 10, 2024
2 parents ff7906b + c553994 commit dee520e
Show file tree
Hide file tree
Showing 30 changed files with 560 additions and 317 deletions.
40 changes: 20 additions & 20 deletions compiler/rustc_codegen_cranelift/example/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,26 +55,26 @@ impl<T: ?Sized> LegacyReceiver for &mut T {}
impl<T: ?Sized> LegacyReceiver for Box<T> {}

#[lang = "copy"]
pub unsafe trait Copy {}

unsafe impl Copy for bool {}
unsafe impl Copy for u8 {}
unsafe impl Copy for u16 {}
unsafe impl Copy for u32 {}
unsafe impl Copy for u64 {}
unsafe impl Copy for u128 {}
unsafe impl Copy for usize {}
unsafe impl Copy for i8 {}
unsafe impl Copy for i16 {}
unsafe impl Copy for i32 {}
unsafe impl Copy for isize {}
unsafe impl Copy for f32 {}
unsafe impl Copy for f64 {}
unsafe impl Copy for char {}
unsafe impl<'a, T: ?Sized> Copy for &'a T {}
unsafe impl<T: ?Sized> Copy for *const T {}
unsafe impl<T: ?Sized> Copy for *mut T {}
unsafe impl<T: Copy> Copy for Option<T> {}
pub trait Copy {}

impl Copy for bool {}
impl Copy for u8 {}
impl Copy for u16 {}
impl Copy for u32 {}
impl Copy for u64 {}
impl Copy for u128 {}
impl Copy for usize {}
impl Copy for i8 {}
impl Copy for i16 {}
impl Copy for i32 {}
impl Copy for isize {}
impl Copy for f32 {}
impl Copy for f64 {}
impl Copy for char {}
impl<'a, T: ?Sized> Copy for &'a T {}
impl<T: ?Sized> Copy for *const T {}
impl<T: ?Sized> Copy for *mut T {}
impl<T: Copy> Copy for Option<T> {}

#[lang = "sync"]
pub unsafe trait Sync {}
Expand Down
36 changes: 18 additions & 18 deletions compiler/rustc_codegen_gcc/example/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,24 @@ impl<T: ?Sized> LegacyReceiver for &mut T {}
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}

#[lang = "copy"]
pub unsafe trait Copy {}

unsafe impl Copy for bool {}
unsafe impl Copy for u8 {}
unsafe impl Copy for u16 {}
unsafe impl Copy for u32 {}
unsafe impl Copy for u64 {}
unsafe impl Copy for usize {}
unsafe impl Copy for i8 {}
unsafe impl Copy for i16 {}
unsafe impl Copy for i32 {}
unsafe impl Copy for isize {}
unsafe impl Copy for f32 {}
unsafe impl Copy for f64 {}
unsafe impl Copy for char {}
unsafe impl<'a, T: ?Sized> Copy for &'a T {}
unsafe impl<T: ?Sized> Copy for *const T {}
unsafe impl<T: ?Sized> Copy for *mut T {}
pub trait Copy {}

impl Copy for bool {}
impl Copy for u8 {}
impl Copy for u16 {}
impl Copy for u32 {}
impl Copy for u64 {}
impl Copy for usize {}
impl Copy for i8 {}
impl Copy for i16 {}
impl Copy for i32 {}
impl Copy for isize {}
impl Copy for f32 {}
impl Copy for f64 {}
impl Copy for char {}
impl<'a, T: ?Sized> Copy for &'a T {}
impl<T: ?Sized> Copy for *const T {}
impl<T: ?Sized> Copy for *mut T {}

#[lang = "sync"]
pub unsafe trait Sync {}
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2745,6 +2745,15 @@ fn add_upstream_rust_crates(
.find(|(ty, _)| *ty == crate_type)
.expect("failed to find crate type in dependency format list");

if sess.target.is_like_aix {
// Unlike ELF linkers, AIX doesn't feature `DT_SONAME` to override
// the dependency name when outputing a shared library. Thus, `ld` will
// use the full path to shared libraries as the dependency if passed it
// by default unless `noipath` is passed.
// https://www.ibm.com/docs/en/aix/7.3?topic=l-ld-command.
cmd.link_or_cc_arg("-bnoipath");
}

for &cnum in &codegen_results.crate_info.used_crates {
// We may not pass all crates through to the linker. Some crates may appear statically in
// an existing dylib, meaning we'll pick up all the symbols from the dylib.
Expand Down
118 changes: 74 additions & 44 deletions compiler/rustc_hir_analysis/src/check/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::assert_matches::debug_assert_matches;
use rustc_abi::FieldIdx;
use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_middle::bug;
use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
Expand All @@ -21,6 +22,12 @@ pub struct InlineAsmCtxt<'a, 'tcx> {
get_operand_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
}

enum NonAsmTypeReason<'tcx> {
UnevaluatedSIMDArrayLength(DefId, ty::Const<'tcx>),
Invalid(Ty<'tcx>),
InvalidElement(DefId, Ty<'tcx>),
}

impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self {
InlineAsmCtxt {
Expand Down Expand Up @@ -56,7 +63,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
false
}

fn get_asm_ty(&self, ty: Ty<'tcx>) -> Option<InlineAsmType> {
fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result<InlineAsmType, NonAsmTypeReason<'tcx>> {
let asm_ty_isize = match self.tcx.sess.target.pointer_width {
16 => InlineAsmType::I16,
32 => InlineAsmType::I32,
Expand All @@ -65,64 +72,62 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
};

match *ty.kind() {
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
ty::Float(FloatTy::F16) => Some(InlineAsmType::F16),
ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
ty::Float(FloatTy::F128) => Some(InlineAsmType::F128),
ty::FnPtr(..) => Some(asm_ty_isize),
ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::I8),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::I16),
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::I32),
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::I64),
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Ok(InlineAsmType::I128),
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Ok(asm_ty_isize),
ty::Float(FloatTy::F16) => Ok(InlineAsmType::F16),
ty::Float(FloatTy::F32) => Ok(InlineAsmType::F32),
ty::Float(FloatTy::F64) => Ok(InlineAsmType::F64),
ty::Float(FloatTy::F128) => Ok(InlineAsmType::F128),
ty::FnPtr(..) => Ok(asm_ty_isize),
ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Ok(asm_ty_isize),
ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
let elem_ty = fields[FieldIdx::ZERO].ty(self.tcx, args);
let field = &fields[FieldIdx::ZERO];
let elem_ty = field.ty(self.tcx, args);

let (size, ty) = match elem_ty.kind() {
ty::Array(ty, len) => {
let len = self.tcx.normalize_erasing_regions(self.typing_env, *len);
if let Some(len) = len.try_to_target_usize(self.tcx) {
(len, *ty)
} else {
return None;
return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength(
field.did, len,
));
}
}
_ => (fields.len() as u64, elem_ty),
};

match ty.kind() {
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::VecI8(size)),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => {
Some(InlineAsmType::VecI16(size))
}
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => {
Some(InlineAsmType::VecI32(size))
}
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => {
Some(InlineAsmType::VecI64(size))
}
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::VecI8(size)),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::VecI16(size)),
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::VecI32(size)),
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::VecI64(size)),
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => {
Some(InlineAsmType::VecI128(size))
Ok(InlineAsmType::VecI128(size))
}
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => {
Some(match self.tcx.sess.target.pointer_width {
Ok(match self.tcx.sess.target.pointer_width {
16 => InlineAsmType::VecI16(size),
32 => InlineAsmType::VecI32(size),
64 => InlineAsmType::VecI64(size),
width => bug!("unsupported pointer width: {width}"),
})
}
ty::Float(FloatTy::F16) => Some(InlineAsmType::VecF16(size)),
ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)),
ty::Float(FloatTy::F128) => Some(InlineAsmType::VecF128(size)),
_ => None,
ty::Float(FloatTy::F16) => Ok(InlineAsmType::VecF16(size)),
ty::Float(FloatTy::F32) => Ok(InlineAsmType::VecF32(size)),
ty::Float(FloatTy::F64) => Ok(InlineAsmType::VecF64(size)),
ty::Float(FloatTy::F128) => Ok(InlineAsmType::VecF128(size)),
_ => Err(NonAsmTypeReason::InvalidElement(field.did, ty)),
}
}
ty::Infer(_) => bug!("unexpected infer ty in asm operand"),
_ => None,
_ => Err(NonAsmTypeReason::Invalid(ty)),
}
}

Expand Down Expand Up @@ -163,17 +168,42 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
_ => self.get_asm_ty(ty),
};
let Some(asm_ty) = asm_ty else {
let msg = format!("cannot use value of type `{ty}` for inline assembly");
self.tcx
.dcx()
.struct_span_err(expr.span, msg)
.with_note(
"only integers, floats, SIMD vectors, pointers and function pointers \
can be used as arguments for inline assembly",
)
.emit();
return None;
let asm_ty = match asm_ty {
Ok(asm_ty) => asm_ty,
Err(reason) => {
match reason {
NonAsmTypeReason::UnevaluatedSIMDArrayLength(did, len) => {
let msg = format!("cannot evaluate SIMD vector length `{len}`");
self.tcx
.dcx()
.struct_span_err(self.tcx.def_span(did), msg)
.with_span_note(
expr.span,
"SIMD vector length needs to be known statically for use in `asm!`",
)
.emit();
}
NonAsmTypeReason::Invalid(ty) => {
let msg = format!("cannot use value of type `{ty}` for inline assembly");
self.tcx.dcx().struct_span_err(expr.span, msg).with_note(
"only integers, floats, SIMD vectors, pointers and function pointers \
can be used as arguments for inline assembly",
).emit();
}
NonAsmTypeReason::InvalidElement(did, ty) => {
let msg = format!(
"cannot use SIMD vector with element type `{ty}` for inline assembly"
);
self.tcx.dcx()
.struct_span_err(self.tcx.def_span(did), msg).with_span_note(
expr.span,
"only integers, floats, SIMD vectors, pointers and function pointers \
can be used as arguments for inline assembly",
).emit();
}
}
return None;
}
};

// Check that the type implements Copy. The only case where this can
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
}

let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
Ok(()) => Ok(()),
Err(CopyImplementationError::InfringingFields(fields)) => {
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
Expand All @@ -123,6 +123,12 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span }))
}
Err(CopyImplementationError::HasUnsafeFields) => {
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
Err(tcx
.dcx()
.span_delayed_bug(span, format!("cannot implement `Copy` for `{}`", self_type)))
}
}
}

Expand Down
38 changes: 30 additions & 8 deletions compiler/rustc_hir_analysis/src/coherence/unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir::Safety;
use rustc_hir::{LangItem, Safety};
use rustc_middle::ty::ImplPolarity::*;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{ImplTraitHeader, TraitDef, TyCtxt};
Expand All @@ -20,7 +20,19 @@ pub(super) fn check_item(
tcx.generics_of(def_id).own_params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
let trait_ref = trait_header.trait_ref.instantiate_identity();

match (trait_def.safety, unsafe_attr, trait_header.safety, trait_header.polarity) {
let is_copy = tcx.is_lang_item(trait_def.def_id, LangItem::Copy);
let trait_def_safety = if is_copy {
// If `Self` has unsafe fields, `Copy` is unsafe to implement.
if trait_header.trait_ref.skip_binder().self_ty().has_unsafe_fields() {
rustc_hir::Safety::Unsafe
} else {
rustc_hir::Safety::Safe
}
} else {
trait_def.safety
};

match (trait_def_safety, unsafe_attr, trait_header.safety, trait_header.polarity) {
(Safety::Safe, None, Safety::Unsafe, Positive | Reservation) => {
let span = tcx.def_span(def_id);
return Err(struct_span_code_err!(
Expand Down Expand Up @@ -48,12 +60,22 @@ pub(super) fn check_item(
"the trait `{}` requires an `unsafe impl` declaration",
trait_ref.print_trait_sugared()
)
.with_note(format!(
"the trait `{}` enforces invariants that the compiler can't check. \
Review the trait documentation and make sure this implementation \
upholds those invariants before adding the `unsafe` keyword",
trait_ref.print_trait_sugared()
))
.with_note(if is_copy {
format!(
"the trait `{}` cannot be safely implemented for `{}` \
because it has unsafe fields. Review the invariants \
of those fields before adding an `unsafe impl`",
trait_ref.print_trait_sugared(),
trait_ref.self_ty(),
)
} else {
format!(
"the trait `{}` enforces invariants that the compiler can't check. \
Review the trait documentation and make sure this implementation \
upholds those invariants before adding the `unsafe` keyword",
trait_ref.print_trait_sugared()
)
})
.with_span_suggestion_verbose(
span.shrink_to_lo(),
"add `unsafe` to this trait implementation",
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,28 +454,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
closure_kind: hir::ClosureKind,
projection: ty::PolyProjectionPredicate<'tcx>,
) -> Option<ExpectedSig<'tcx>> {
let tcx = self.tcx;

let trait_def_id = projection.trait_def_id(tcx);
let def_id = projection.projection_def_id();

// For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
// for closures and async closures, respectively.
match closure_kind {
hir::ClosureKind::Closure
if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() =>
{
hir::ClosureKind::Closure if self.tcx.is_lang_item(def_id, LangItem::FnOnceOutput) => {
self.extract_sig_from_projection(cause_span, projection)
}
hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async)
if self.tcx.async_fn_trait_kind_from_def_id(trait_def_id).is_some() =>
if self.tcx.is_lang_item(def_id, LangItem::AsyncFnOnceOutput) =>
{
self.extract_sig_from_projection(cause_span, projection)
}
// It's possible we've passed the closure to a (somewhat out-of-fashion)
// `F: FnOnce() -> Fut, Fut: Future<Output = T>` style bound. Let's still
// guide inference here, since it's beneficial for the user.
hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async)
if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() =>
if self.tcx.is_lang_item(def_id, LangItem::FnOnceOutput) =>
{
self.extract_sig_from_projection_and_future_bound(cause_span, projection)
}
Expand Down
Loading

0 comments on commit dee520e

Please sign in to comment.