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 7 pull requests #133978

Merged
merged 20 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
741d6ef
Stabilize `std::io::ErrorKind::CrossesDevices`
GrigorenkoPV Sep 10, 2024
b2c1c8f
Stabilize `std::io::ErrorKind::QuotaExceeded`
GrigorenkoPV Sep 11, 2024
eb52032
Unbreak tidy
GrigorenkoPV Sep 11, 2024
59be878
Add Extend impls for tuples of arity 1 through 12
shahn Oct 26, 2024
be06502
Simplify documentation for Extend impl for tuples
shahn Oct 26, 2024
9cebcba
Don't impl Extend for 13-tuples
shahn Oct 31, 2024
27342cb
Add a `collect_into` tuple test case
shahn Oct 31, 2024
a122dde
do not implement unsafe auto traits for types with unsafe fields
jswrenn Dec 5, 2024
83909b6
skip formatting when `--json-output` is used
onur-ozkan Dec 4, 2024
31c4057
handle `json_output` in `test::run_cargo_test`
onur-ozkan Dec 5, 2024
cb72b9b
Silence follow-up errors from `lit_to_const`
oli-obk Dec 5, 2024
060cecb
Hide errors whose suggestions would contain error constants or types
oli-obk Dec 5, 2024
8523074
remove eq for attributes
jdonszelmann Dec 6, 2024
14710ec
Rollup merge of #130209 - GrigorenkoPV:CrossesDevices, r=dtolnay
matthiaskrgr Dec 6, 2024
d0fe04e
Rollup merge of #130254 - GrigorenkoPV:QuotaExceeded, r=dtolnay
matthiaskrgr Dec 6, 2024
bfbbe95
Rollup merge of #132187 - shahn:extend_more_tuples, r=dtolnay
matthiaskrgr Dec 6, 2024
8c78d7a
Rollup merge of #133875 - onur-ozkan:early-return-rustfmt, r=jieyouxu
matthiaskrgr Dec 6, 2024
6457761
Rollup merge of #133934 - jswrenn:unsafe-fields-auto-traits, r=compil…
matthiaskrgr Dec 6, 2024
5d3a963
Rollup merge of #133954 - oli-obk:push-lxrmszqzszzu, r=jieyouxu
matthiaskrgr Dec 6, 2024
d210b91
Rollup merge of #133960 - jdonszelmann:remove-eq-on-attributes, r=not…
matthiaskrgr Dec 6, 2024
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
3 changes: 3 additions & 0 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
self.lower_const_arg(ct, FeedConstTy::No).into()
}
};
if term.references_error() {
continue;
}
// FIXME(#97583): This isn't syntactically well-formed!
where_bounds.push(format!(
" T: {trait}::{assoc_name} = {term}",
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.trait_def(trait_def_id).implement_via_object
}

fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool {
self.trait_def(trait_def_id).safety == hir::Safety::Unsafe
}

fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
self.is_impl_trait_in_trait(def_id)
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
self.async_destructor_ty(interner)
}

fn has_unsafe_fields(self) -> bool {
if let ty::Adt(adt_def, ..) = self.kind() {
adt_def.all_fields().any(|x| x.safety == hir::Safety::Unsafe)
} else {
false
}
}
}

/// Type utilities
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_mir_build/src/thir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use rustc_ast as ast;
use rustc_hir::LangItem;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
use rustc_middle::ty::{self, ScalarInt, TyCtxt};
use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _};
use tracing::trace;

use crate::build::parse_float_into_scalar;
Expand All @@ -13,6 +13,10 @@ pub(crate) fn lit_to_const<'tcx>(
) -> Result<ty::Const<'tcx>, LitToConstError> {
let LitToConstInput { lit, ty, neg } = lit_input;

if let Err(guar) = ty.error_reported() {
return Ok(ty::Const::new_error(tcx, guar));
}

let trunc = |n| {
let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
Ok(layout) => layout.size,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ where
return result;
}

// Only consider auto impls of unsafe traits when there are no unsafe
// fields.
if ecx.cx().trait_is_unsafe(goal.predicate.def_id())
&& goal.predicate.self_ty().has_unsafe_fields()
{
return Err(NoSolution);
}

// We only look into opaque types during analysis for opaque types
// outside of their defining scope. Doing so for opaques in the
// defining scope may require calling `typeck` on the same item we're
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use rustc_infer::traits::{
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug};
use rustc_type_ir::Interner;
use tracing::{debug, instrument, trace};

use super::SelectionCandidate::*;
Expand Down Expand Up @@ -794,6 +795,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Never
| ty::Tuple(_)
| ty::CoroutineWitness(..) => {
use rustc_type_ir::inherent::*;

// Only consider auto impls of unsafe traits when there are
// no unsafe fields.
if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
return;
}

// Only consider auto impls if there are no manual impls for the root of `self_ty`.
//
// For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_type_ir/src/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ pub trait Ty<I: Interner<Ty = Self>>:
matches!(self.kind(), ty::FnPtr(..))
}

/// Checks whether this type is an ADT that has unsafe fields.
fn has_unsafe_fields(self) -> bool;

fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
match self.kind() {
ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_type_ir/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ pub trait Interner:

fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;

/// Returns `true` if this is an `unsafe trait`.
fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool;

fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;

fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed;
Expand Down
239 changes: 129 additions & 110 deletions library/core/src/iter/traits/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,131 +492,150 @@ impl Extend<()> for () {
fn extend_one(&mut self, _item: ()) {}
}

#[stable(feature = "extend_for_tuple", since = "1.56.0")]
impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB)
where
ExtendA: Extend<A>,
ExtendB: Extend<B>,
{
/// Allows to `extend` a tuple of collections that also implement `Extend`.
///
/// See also: [`Iterator::unzip`]
///
/// # Examples
/// ```
/// let mut tuple = (vec![0], vec![1]);
/// tuple.extend([(2, 3), (4, 5), (6, 7)]);
/// assert_eq!(tuple.0, [0, 2, 4, 6]);
/// assert_eq!(tuple.1, [1, 3, 5, 7]);
///
/// // also allows for arbitrarily nested tuples as elements
/// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
/// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
///
/// let (a, (b, c)) = nested_tuple;
/// assert_eq!(a, [1, 4, 7]);
/// assert_eq!(b, [2, 5, 8]);
/// assert_eq!(c, [3, 6, 9]);
/// ```
fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
let (a, b) = self;
let iter = into_iter.into_iter();
SpecTupleExtend::extend(iter, a, b);
}
macro_rules! spec_tuple_impl {
( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => {
spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),);
};
( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => {

fn extend_one(&mut self, item: (A, B)) {
self.0.extend_one(item.0);
self.1.extend_one(item.1);
}
spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*);
spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*);
};
($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => {
#[$meta]
$(#[$doctext])?
#[stable(feature = "extend_for_tuple", since = "1.56.0")]
impl<$($ty_names,)* $($extend_ty_names,)*> Extend<($($ty_names,)*)> for ($($extend_ty_names,)*)
where
$($extend_ty_names: Extend<$ty_names>,)*
{
/// Allows to `extend` a tuple of collections that also implement `Extend`.
///
/// See also: [`Iterator::unzip`]
///
/// # Examples
/// ```
/// // Example given for a 2-tuple, but 1- through 12-tuples are supported
/// let mut tuple = (vec![0], vec![1]);
/// tuple.extend([(2, 3), (4, 5), (6, 7)]);
/// assert_eq!(tuple.0, [0, 2, 4, 6]);
/// assert_eq!(tuple.1, [1, 3, 5, 7]);
///
/// // also allows for arbitrarily nested tuples as elements
/// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
/// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
///
/// let (a, (b, c)) = nested_tuple;
/// assert_eq!(a, [1, 4, 7]);
/// assert_eq!(b, [2, 5, 8]);
/// assert_eq!(c, [3, 6, 9]);
/// ```
fn extend<T: IntoIterator<Item = ($($ty_names,)*)>>(&mut self, into_iter: T) {
let ($($var_names,)*) = self;
let iter = into_iter.into_iter();
$trait_name::extend(iter, $($var_names,)*);
}

fn extend_reserve(&mut self, additional: usize) {
self.0.extend_reserve(additional);
self.1.extend_reserve(additional);
}
fn extend_one(&mut self, item: ($($ty_names,)*)) {
$(self.$cnts.extend_one(item.$cnts);)*
}

unsafe fn extend_one_unchecked(&mut self, item: (A, B)) {
// SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
unsafe {
self.0.extend_one_unchecked(item.0);
self.1.extend_one_unchecked(item.1);
}
}
}
fn extend_reserve(&mut self, additional: usize) {
$(self.$cnts.extend_reserve(additional);)*
}

fn default_extend_tuple<A, B, ExtendA, ExtendB>(
iter: impl Iterator<Item = (A, B)>,
a: &mut ExtendA,
b: &mut ExtendB,
) where
ExtendA: Extend<A>,
ExtendB: Extend<B>,
{
fn extend<'a, A, B>(
a: &'a mut impl Extend<A>,
b: &'a mut impl Extend<B>,
) -> impl FnMut((), (A, B)) + 'a {
move |(), (t, u)| {
a.extend_one(t);
b.extend_one(u);
unsafe fn extend_one_unchecked(&mut self, item: ($($ty_names,)*)) {
// SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
unsafe {
$(self.$cnts.extend_one_unchecked(item.$cnts);)*
}
}
}
}

let (lower_bound, _) = iter.size_hint();
if lower_bound > 0 {
a.extend_reserve(lower_bound);
b.extend_reserve(lower_bound);
}
trait $trait_name<$($ty_names),*> {
fn extend(self, $($var_names: &mut $ty_names,)*);
}

iter.fold((), extend(a, b));
}
fn $default_fn_name<$($ty_names,)* $($extend_ty_names,)*>(
iter: impl Iterator<Item = ($($ty_names,)*)>,
$($var_names: &mut $extend_ty_names,)*
) where
$($extend_ty_names: Extend<$ty_names>,)*
{
fn extend<'a, $($ty_names,)*>(
$($var_names: &'a mut impl Extend<$ty_names>,)*
) -> impl FnMut((), ($($ty_names,)*)) + 'a {
#[allow(non_snake_case)]
move |(), ($($extend_ty_names,)*)| {
$($var_names.extend_one($extend_ty_names);)*
}
}

trait SpecTupleExtend<A, B> {
fn extend(self, a: &mut A, b: &mut B);
}
let (lower_bound, _) = iter.size_hint();
if lower_bound > 0 {
$($var_names.extend_reserve(lower_bound);)*
}

impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
where
ExtendA: Extend<A>,
ExtendB: Extend<B>,
Iter: Iterator<Item = (A, B)>,
{
default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
default_extend_tuple(self, a, b);
}
}
iter.fold((), extend($($var_names,)*));
}

impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
where
ExtendA: Extend<A>,
ExtendB: Extend<B>,
Iter: TrustedLen<Item = (A, B)>,
{
fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
fn extend<'a, A, B>(
a: &'a mut impl Extend<A>,
b: &'a mut impl Extend<B>,
) -> impl FnMut((), (A, B)) + 'a {
// SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
// so its `size_hint` is exact.
move |(), (t, u)| unsafe {
a.extend_one_unchecked(t);
b.extend_one_unchecked(u);
impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
where
$($extend_ty_names: Extend<$ty_names>,)*
Iter: Iterator<Item = ($($ty_names,)*)>,
{
default fn extend(self, $($var_names: &mut $extend_ty_names),*) {
$default_fn_name(self, $($var_names),*);
}
}

let (lower_bound, upper_bound) = self.size_hint();
impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
where
$($extend_ty_names: Extend<$ty_names>,)*
Iter: TrustedLen<Item = ($($ty_names,)*)>,
{
fn extend(self, $($var_names: &mut $extend_ty_names,)*) {
fn extend<'a, $($ty_names,)*>(
$($var_names: &'a mut impl Extend<$ty_names>,)*
) -> impl FnMut((), ($($ty_names,)*)) + 'a {
#[allow(non_snake_case)]
// SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
// so its `size_hint` is exact.
move |(), ($($extend_ty_names,)*)| unsafe {
$($var_names.extend_one_unchecked($extend_ty_names);)*
}
}

if upper_bound.is_none() {
// We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
default_extend_tuple(self, a, b);
return;
}
let (lower_bound, upper_bound) = self.size_hint();

if lower_bound > 0 {
a.extend_reserve(lower_bound);
b.extend_reserve(lower_bound);
}
if upper_bound.is_none() {
// We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
$default_fn_name(self, $($var_names,)*);
return;
}

self.fold((), extend(a, b));
if lower_bound > 0 {
$($var_names.extend_reserve(lower_bound);)*
}

self.fold((), extend($($var_names,)*));
}
}

};
}

spec_tuple_impl!(
(L, l, EL, TraitL, default_extend_tuple_l, 11),
(K, k, EK, TraitK, default_extend_tuple_k, 10),
(J, j, EJ, TraitJ, default_extend_tuple_j, 9),
(I, i, EI, TraitI, default_extend_tuple_i, 8),
(H, h, EH, TraitH, default_extend_tuple_h, 7),
(G, g, EG, TraitG, default_extend_tuple_g, 6),
(F, f, EF, TraitF, default_extend_tuple_f, 5),
(E, e, EE, TraitE, default_extend_tuple_e, 4),
(D, d, ED, TraitD, default_extend_tuple_d, 3),
(C, c, EC, TraitC, default_extend_tuple_c, 2),
(B, b, EB, TraitB, default_extend_tuple_b, 1),
(A, a, EA, TraitA, default_extend_tuple_a, 0),
);
13 changes: 13 additions & 0 deletions library/core/tests/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,19 @@ fn test_next_chunk() {
assert_eq!(it.next_chunk::<0>().unwrap(), []);
}

#[test]
fn test_collect_into_tuples() {
let a = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)];
let b = vec![1, 4, 7];
let c = vec![2, 5, 8];
let d = vec![3, 6, 9];
let mut e = (Vec::new(), Vec::new(), Vec::new());
a.iter().cloned().collect_into(&mut e);
assert!(e.0 == b);
assert!(e.1 == c);
assert!(e.2 == d);
}

// just tests by whether or not this compiles
fn _empty_impl_all_auto_traits<T>() {
use std::panic::{RefUnwindSafe, UnwindSafe};
Expand Down
Loading
Loading