Skip to content

Commit

Permalink
Auto merge of #128418 - tgross35:rollup-wtt07jr, r=tgross35
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #125048 (PinCoerceUnsized trait into core)
 - #127681 (derive(SmartPointer): rewrite bounds in where and generic bounds)
 - #127830 (When an archive fails to build, print the path)
 - #128147 (migrate fmt-write-bloat to rmake)
 - #128356 (Migrate `cross-lang-lto-clang` and `cross-lang-lto-pgo-smoketest` `run-make` tests to rmake)
 - #128387 (More detailed note to deprecate ONCE_INIT)
 - #128388 (Match LLVM ABI in `extern "C"` functions for `f128` on Windows)
 - #128412 (Remove `crate_level_only` from `ELIDED_LIFETIMES_IN_PATHS`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 31, 2024
2 parents 83dcdb3 + c7481d7 commit 546da25
Show file tree
Hide file tree
Showing 41 changed files with 950 additions and 62 deletions.
244 changes: 227 additions & 17 deletions compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
use std::mem::swap;

use ast::ptr::P;
use ast::HasAttrs;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::visit::BoundKind;
use rustc_ast::{
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
TraitBoundModifiers, VariantData,
TraitBoundModifiers, VariantData, WherePredicate,
};
use rustc_attr as attr;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_span::{Span, Symbol};
use smallvec::{smallvec, SmallVec};
use thin_vec::{thin_vec, ThinVec};

Expand Down Expand Up @@ -141,33 +145,239 @@ pub fn expand_deriving_smart_ptr(
alt_self_params[pointee_param_idx] = GenericArg::Type(s_ty.clone());
let alt_self_type = cx.ty_path(cx.path_all(span, false, vec![name_ident], alt_self_params));

// # Add `Unsize<__S>` bound to `#[pointee]` at the generic parameter location
//
// Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it.
let mut impl_generics = generics.clone();
let pointee_ty_ident = generics.params[pointee_param_idx].ident;
let mut self_bounds;
{
let p = &mut impl_generics.params[pointee_param_idx];
let pointee = &mut impl_generics.params[pointee_param_idx];
self_bounds = pointee.bounds.clone();
let arg = GenericArg::Type(s_ty.clone());
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
p.bounds.push(cx.trait_bound(unsize, false));
pointee.bounds.push(cx.trait_bound(unsize, false));
let mut attrs = thin_vec![];
swap(&mut p.attrs, &mut attrs);
p.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
swap(&mut pointee.attrs, &mut attrs);
// Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)`
pointee.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
}

// Add the `__S: ?Sized` extra parameter to the impl block.
// # Rewrite generic parameter bounds
// For each bound `U: ..` in `struct<U: ..>`, make a new bound with `__S` in place of `#[pointee]`
// Example:
// ```
// struct<
// U: Trait<T>,
// #[pointee] T: Trait<T>,
// V: Trait<T>> ...
// ```
// ... generates this `impl` generic parameters
// ```
// impl<
// U: Trait<T> + Trait<__S>,
// T: Trait<T> + Unsize<__S>, // (**)
// __S: Trait<__S> + ?Sized, // (*)
// V: Trait<T> + Trait<__S>> ...
// ```
// The new bound marked with (*) has to be done separately.
// See next section
for (idx, (params, orig_params)) in
impl_generics.params.iter_mut().zip(&generics.params).enumerate()
{
// Default type parameters are rejected for `impl` block.
// We should drop them now.
match &mut params.kind {
ast::GenericParamKind::Const { default, .. } => *default = None,
ast::GenericParamKind::Type { default } => *default = None,
ast::GenericParamKind::Lifetime => {}
}
// We CANNOT rewrite `#[pointee]` type parameter bounds.
// This has been set in stone. (**)
// So we skip over it.
// Otherwise, we push extra bounds involving `__S`.
if idx != pointee_param_idx {
for bound in &orig_params.bounds {
let mut bound = bound.clone();
let mut substitution = TypeSubstitution {
from_name: pointee_ty_ident.name,
to_ty: &s_ty,
rewritten: false,
};
substitution.visit_param_bound(&mut bound, BoundKind::Bound);
if substitution.rewritten {
// We found use of `#[pointee]` somewhere,
// so we make a new bound using `__S` in place of `#[pointee]`
params.bounds.push(bound);
}
}
}
}

// # Insert `__S` type parameter
//
// We now insert `__S` with the missing bounds marked with (*) above.
// We should also write the bounds from `#[pointee]` to `__S` as required by `Unsize<__S>`.
let sized = cx.path_global(span, path!(span, core::marker::Sized));
let bound = GenericBound::Trait(
cx.poly_trait_ref(span, sized),
TraitBoundModifiers {
polarity: ast::BoundPolarity::Maybe(span),
constness: ast::BoundConstness::Never,
asyncness: ast::BoundAsyncness::Normal,
},
);
let extra_param = cx.typaram(span, Ident::new(sym::__S, span), vec![bound], None);
impl_generics.params.push(extra_param);
// For some reason, we are not allowed to write `?Sized` bound twice like `__S: ?Sized + ?Sized`.
if !contains_maybe_sized_bound(&self_bounds)
&& !contains_maybe_sized_bound_on_pointee(
&generics.where_clause.predicates,
pointee_ty_ident.name,
)
{
self_bounds.push(GenericBound::Trait(
cx.poly_trait_ref(span, sized),
TraitBoundModifiers {
polarity: ast::BoundPolarity::Maybe(span),
constness: ast::BoundConstness::Never,
asyncness: ast::BoundAsyncness::Normal,
},
));
}
{
let mut substitution =
TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false };
for bound in &mut self_bounds {
substitution.visit_param_bound(bound, BoundKind::Bound);
}
}

// # Rewrite `where` clauses
//
// Move on to `where` clauses.
// Example:
// ```
// struct MyPointer<#[pointee] T, ..>
// where
// U: Trait<V> + Trait<T>,
// Companion<T>: Trait<T>,
// T: Trait<T>,
// { .. }
// ```
// ... will have a impl prelude like so
// ```
// impl<..> ..
// where
// U: Trait<V> + Trait<T>,
// U: Trait<__S>,
// Companion<T>: Trait<T>,
// Companion<__S>: Trait<__S>,
// T: Trait<T>,
// __S: Trait<__S>,
// ```
//
// We should also write a few new `where` bounds from `#[pointee] T` to `__S`
// as well as any bound that indirectly involves the `#[pointee] T` type.
for bound in &generics.where_clause.predicates {
if let ast::WherePredicate::BoundPredicate(bound) = bound {
let mut substitution = TypeSubstitution {
from_name: pointee_ty_ident.name,
to_ty: &s_ty,
rewritten: false,
};
let mut predicate = ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
span: bound.span,
bound_generic_params: bound.bound_generic_params.clone(),
bounded_ty: bound.bounded_ty.clone(),
bounds: bound.bounds.clone(),
});
substitution.visit_where_predicate(&mut predicate);
if substitution.rewritten {
impl_generics.where_clause.predicates.push(predicate);
}
}
}

let extra_param = cx.typaram(span, Ident::new(sym::__S, span), self_bounds, None);
impl_generics.params.insert(pointee_param_idx + 1, extra_param);

// Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`.
let gen_args = vec![GenericArg::Type(alt_self_type.clone())];
add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone());
add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args.clone());
}

fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: Symbol) -> bool {
for bound in predicates {
if let ast::WherePredicate::BoundPredicate(bound) = bound
&& bound.bounded_ty.kind.is_simple_path().is_some_and(|name| name == pointee)
{
for bound in &bound.bounds {
if is_maybe_sized_bound(bound) {
return true;
}
}
}
}
false
}

fn is_maybe_sized_bound(bound: &GenericBound) -> bool {
if let GenericBound::Trait(
trait_ref,
TraitBoundModifiers { polarity: ast::BoundPolarity::Maybe(_), .. },
) = bound
{
is_sized_marker(&trait_ref.trait_ref.path)
} else {
false
}
}

fn contains_maybe_sized_bound(bounds: &[GenericBound]) -> bool {
bounds.iter().any(is_maybe_sized_bound)
}

fn path_segment_is_exact_match(path_segments: &[ast::PathSegment], syms: &[Symbol]) -> bool {
path_segments.iter().zip(syms).all(|(segment, &symbol)| segment.ident.name == symbol)
}

fn is_sized_marker(path: &ast::Path) -> bool {
const CORE_UNSIZE: [Symbol; 3] = [sym::core, sym::marker, sym::Sized];
const STD_UNSIZE: [Symbol; 3] = [sym::std, sym::marker, sym::Sized];
if path.segments.len() == 4 && path.is_global() {
path_segment_is_exact_match(&path.segments[1..], &CORE_UNSIZE)
|| path_segment_is_exact_match(&path.segments[1..], &STD_UNSIZE)
} else if path.segments.len() == 3 {
path_segment_is_exact_match(&path.segments, &CORE_UNSIZE)
|| path_segment_is_exact_match(&path.segments, &STD_UNSIZE)
} else {
*path == sym::Sized
}
}

struct TypeSubstitution<'a> {
from_name: Symbol,
to_ty: &'a ast::Ty,
rewritten: bool,
}

impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> {
fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
if let Some(name) = ty.kind.is_simple_path()
&& name == self.from_name
{
**ty = self.to_ty.clone();
self.rewritten = true;
} else {
ast::mut_visit::walk_ty(self, ty);
}
}

fn visit_where_predicate(&mut self, where_predicate: &mut ast::WherePredicate) {
match where_predicate {
rustc_ast::WherePredicate::BoundPredicate(bound) => {
bound
.bound_generic_params
.flat_map_in_place(|param| self.flat_map_generic_param(param));
self.visit_ty(&mut bound.bounded_ty);
for bound in &mut bound.bounds {
self.visit_param_bound(bound, BoundKind::Bound)
}
}
rustc_ast::WherePredicate::RegionPredicate(_)
| rustc_ast::WherePredicate::EqPredicate(_) => {}
}
}
}
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_llvm/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> {
fn build(mut self: Box<Self>, output: &Path) -> bool {
match self.build_with_llvm(output) {
Ok(any_members) => any_members,
Err(e) => self.sess.dcx().emit_fatal(ArchiveBuildFailure { error: e }),
Err(error) => {
self.sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error })
}
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ codegen_ssa_add_native_library = failed to add native library {$library_path}: {
codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
codegen_ssa_archive_build_failure =
failed to build archive: {$error}
codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error}
codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
Expand Down Expand Up @@ -198,7 +197,7 @@ codegen_ssa_read_file = failed to read file: {$message}
codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error}
codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib at `{$path}`: {$error}
codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
let sess = self.sess;
match self.build_inner(output) {
Ok(any_members) => any_members,
Err(e) => sess.dcx().emit_fatal(ArchiveBuildFailure { error: e }),
Err(error) => {
sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error })
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2911,7 +2911,8 @@ fn add_static_crate(
false
}),
) {
sess.dcx().emit_fatal(errors::RlibArchiveBuildFailure { error });
sess.dcx()
.emit_fatal(errors::RlibArchiveBuildFailure { path: cratepath.clone(), error });
}
if archive.build(&dst) {
link_upstream(&dst);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ pub struct UnableToWriteDebuggerVisualizer {
#[derive(Diagnostic)]
#[diag(codegen_ssa_rlib_archive_build_failure)]
pub struct RlibArchiveBuildFailure {
pub path: PathBuf,
pub error: Error,
}

Expand Down Expand Up @@ -557,6 +558,7 @@ pub struct UnsupportedLinkSelfContained;
#[diag(codegen_ssa_archive_build_failure)]
// Public for rustc_codegen_llvm::back::archive
pub struct ArchiveBuildFailure {
pub path: PathBuf,
pub error: std::io::Error,
}

Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1834,8 +1834,7 @@ declare_lint! {
/// [placeholder lifetime]: https://doc.rust-lang.org/reference/lifetime-elision.html#lifetime-elision-in-functions
pub ELIDED_LIFETIMES_IN_PATHS,
Allow,
"hidden lifetime parameters in types are deprecated",
crate_level_only
"hidden lifetime parameters in types are deprecated"
}

declare_lint! {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ symbols! {
Path,
PathBuf,
Pending,
PinCoerceUnsized,
Pointer,
Poll,
ProcMacro,
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_target/src/abi/call/x86_win64.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::abi::call::{ArgAbi, FnAbi, Reg};
use crate::abi::Abi;
use crate::abi::{Abi, Float, Primitive};

// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing

Expand All @@ -18,8 +18,12 @@ pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
// FIXME(eddyb) there should be a size cap here
// (probably what clang calls "illegal vectors").
}
Abi::Scalar(_) => {
if a.layout.size.bytes() > 8 {
Abi::Scalar(scalar) => {
// Match what LLVM does for `f128` so that `compiler-builtins` builtins match up
// with what LLVM expects.
if a.layout.size.bytes() > 8
&& !matches!(scalar.primitive(), Primitive::Float(Float::F128))
{
a.make_indirect();
} else {
a.extend_integer_width_to(32);
Expand Down
5 changes: 4 additions & 1 deletion library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ use core::ops::{
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut,
DerefPure, DispatchFromDyn, Receiver,
};
use core::pin::Pin;
use core::pin::{Pin, PinCoerceUnsized};
use core::ptr::{self, addr_of_mut, NonNull, Unique};
use core::task::{Context, Poll};
use core::{borrow, fmt, slice};
Expand Down Expand Up @@ -2724,3 +2724,6 @@ impl<T: core::error::Error> core::error::Error for Box<T> {
core::error::Error::provide(&**self, request);
}
}

#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}
Loading

0 comments on commit 546da25

Please sign in to comment.