Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #128427

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
4 changes: 3 additions & 1 deletion library/std/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn main() {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86", "windows") => false,
("x86_64", "windows") => false,
// x86 has ABI bugs that show up with optimizations. This should be partially fixed with
// the compiler-builtins update. <https://github.com/rust-lang/rust/issues/123885>
("x86" | "x86_64", _) => false,
Expand Down Expand Up @@ -122,6 +122,8 @@ fn main() {
("nvptx64", _) => false,
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
("sparc", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") => false,
// 64-bit Linux is about the only platform to have f128 symbols by default
(_, "linux") if target_pointer_width == 64 => true,
// Same as for f16, except MacOS is also missing f128 symbols.
Expand Down
Loading
Loading