Skip to content

Commit e7d66ea

Browse files
committed
Auto merge of rust-lang#128155 - matthiaskrgr:rollup-lxtal9f, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#122192 (Do not try to reveal hidden types when trying to prove auto-traits in the defining scope) - rust-lang#126042 (Implement `unsigned_signed_diff`) - rust-lang#126548 (Improved clarity of documentation for std::fs::create_dir_all) - rust-lang#127717 (Fix malformed suggestion for repeated maybe unsized bounds) - rust-lang#128046 (Fix some `#[cfg_attr(not(doc), repr(..))]`) - rust-lang#128122 (Mark `missing_fragment_specifier` as `FutureReleaseErrorReportInDeps`) - rust-lang#128135 (std: use duplicate thread local state in tests) - rust-lang#128140 (Remove Unnecessary `.as_str()` Conversions) r? `@ghost` `@rustbot` modify labels: rollup
2 parents c1a6199 + 104a421 commit e7d66ea

File tree

53 files changed

+742
-335
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+742
-335
lines changed

compiler/rustc_const_eval/src/check_consts/qualifs.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,33 @@ impl Qualif for HasMutInterior {
100100
}
101101

102102
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
103-
!ty.is_freeze(cx.tcx, cx.param_env)
103+
// Avoid selecting for simple cases, such as builtin types.
104+
if ty.is_trivially_freeze() {
105+
return false;
106+
}
107+
108+
// We do not use `ty.is_freeze` here, because that requires revealing opaque types, which
109+
// requires borrowck, which in turn will invoke mir_const_qualifs again, causing a cycle error.
110+
// Instead we invoke an obligation context manually, and provide the opaque type inference settings
111+
// that allow the trait solver to just error out instead of cycling.
112+
let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span));
113+
114+
let obligation = Obligation::new(
115+
cx.tcx,
116+
ObligationCause::dummy_with_span(cx.body.span),
117+
cx.param_env,
118+
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
119+
);
120+
121+
let infcx = cx
122+
.tcx
123+
.infer_ctxt()
124+
.with_opaque_type_inference(cx.body.source.def_id().expect_local())
125+
.build();
126+
let ocx = ObligationCtxt::new(&infcx);
127+
ocx.register_obligation(obligation);
128+
let errors = ocx.select_all_or_error();
129+
!errors.is_empty()
104130
}
105131

106132
fn in_adt_inherently<'tcx>(

compiler/rustc_hir/src/hir.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ impl<'hir> Generics<'hir> {
763763
)
764764
}
765765

766-
fn span_for_predicate_removal(&self, pos: usize) -> Span {
766+
pub fn span_for_predicate_removal(&self, pos: usize) -> Span {
767767
let predicate = &self.predicates[pos];
768768
let span = predicate.span();
769769

@@ -806,15 +806,21 @@ impl<'hir> Generics<'hir> {
806806
return self.span_for_predicate_removal(predicate_pos);
807807
}
808808

809-
let span = bounds[bound_pos].span();
810-
if bound_pos == 0 {
811-
// where T: ?Sized + Bar, Foo: Bar,
812-
// ^^^^^^^^^
813-
span.to(bounds[1].span().shrink_to_lo())
809+
let bound_span = bounds[bound_pos].span();
810+
if bound_pos < bounds.len() - 1 {
811+
// If there's another bound after the current bound
812+
// include the following '+' e.g.:
813+
//
814+
// `T: Foo + CurrentBound + Bar`
815+
// ^^^^^^^^^^^^^^^
816+
bound_span.to(bounds[bound_pos + 1].span().shrink_to_lo())
814817
} else {
815-
// where T: Bar + ?Sized, Foo: Bar,
816-
// ^^^^^^^^^
817-
bounds[bound_pos - 1].span().shrink_to_hi().to(span)
818+
// If the current bound is the last bound
819+
// include the preceding '+' E.g.:
820+
//
821+
// `T: Foo + Bar + CurrentBound`
822+
// ^^^^^^^^^^^^^^^
823+
bound_span.with_lo(bounds[bound_pos - 1].span().hi())
818824
}
819825
}
820826
}

compiler/rustc_hir_typeck/src/method/probe.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1846,7 +1846,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18461846
/// Determine if the associated item with the given DefId matches
18471847
/// the desired name via a doc alias.
18481848
fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
1849-
let Some(name) = self.method_name else {
1849+
let Some(method) = self.method_name else {
18501850
return false;
18511851
};
18521852
let Some(local_def_id) = def_id.as_local() else {
@@ -1863,7 +1863,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18631863
// #[rustc_confusables("foo", "bar"))]
18641864
for n in confusables {
18651865
if let Some(lit) = n.lit()
1866-
&& name.as_str() == lit.symbol.as_str()
1866+
&& method.name == lit.symbol
18671867
{
18681868
return true;
18691869
}
@@ -1883,14 +1883,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18831883
// #[doc(alias("foo", "bar"))]
18841884
for n in nested {
18851885
if let Some(lit) = n.lit()
1886-
&& name.as_str() == lit.symbol.as_str()
1886+
&& method.name == lit.symbol
18871887
{
18881888
return true;
18891889
}
18901890
}
18911891
} else if let Some(meta) = v.meta_item()
18921892
&& let Some(lit) = meta.name_value_literal()
1893-
&& name.as_str() == lit.symbol.as_str()
1893+
&& method.name == lit.symbol
18941894
{
18951895
// #[doc(alias = "foo")]
18961896
return true;

compiler/rustc_lint_defs/src/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ declare_lint! {
14241424
Deny,
14251425
"detects missing fragment specifiers in unused `macro_rules!` patterns",
14261426
@future_incompatible = FutureIncompatibleInfo {
1427-
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
1427+
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
14281428
reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
14291429
};
14301430
}

compiler/rustc_middle/src/ty/diagnostics.rs

+49-20
Original file line numberDiff line numberDiff line change
@@ -188,31 +188,60 @@ fn suggest_changing_unsized_bound(
188188
continue;
189189
};
190190

191-
for (pos, bound) in predicate.bounds.iter().enumerate() {
192-
let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound else {
193-
continue;
194-
};
195-
if poly.trait_ref.trait_def_id() != def_id {
196-
continue;
197-
}
198-
if predicate.origin == PredicateOrigin::ImplTrait && predicate.bounds.len() == 1 {
199-
// For `impl ?Sized` with no other bounds, suggest `impl Sized` instead.
200-
let bound_span = bound.span();
201-
if bound_span.can_be_used_for_suggestions() {
202-
let question_span = bound_span.with_hi(bound_span.lo() + BytePos(1));
203-
suggestions.push((
191+
let unsized_bounds = predicate
192+
.bounds
193+
.iter()
194+
.enumerate()
195+
.filter(|(_, bound)| {
196+
if let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound
197+
&& poly.trait_ref.trait_def_id() == def_id
198+
{
199+
true
200+
} else {
201+
false
202+
}
203+
})
204+
.collect::<Vec<_>>();
205+
206+
if unsized_bounds.is_empty() {
207+
continue;
208+
}
209+
210+
let mut push_suggestion = |sp, msg| suggestions.push((sp, String::new(), msg));
211+
212+
if predicate.bounds.len() == unsized_bounds.len() {
213+
// All the bounds are unsized bounds, e.g.
214+
// `T: ?Sized + ?Sized` or `_: impl ?Sized + ?Sized`,
215+
// so in this case:
216+
// - if it's an impl trait predicate suggest changing the
217+
// the first bound to sized and removing the rest
218+
// - Otherwise simply suggest removing the entire predicate
219+
if predicate.origin == PredicateOrigin::ImplTrait {
220+
let first_bound = unsized_bounds[0].1;
221+
let first_bound_span = first_bound.span();
222+
if first_bound_span.can_be_used_for_suggestions() {
223+
let question_span =
224+
first_bound_span.with_hi(first_bound_span.lo() + BytePos(1));
225+
push_suggestion(
204226
question_span,
205-
String::new(),
206227
SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized,
207-
));
228+
);
229+
230+
for (pos, _) in unsized_bounds.iter().skip(1) {
231+
let sp = generics.span_for_bound_removal(where_pos, *pos);
232+
push_suggestion(sp, SuggestChangingConstraintsMessage::RemoveMaybeUnsized);
233+
}
208234
}
209235
} else {
236+
let sp = generics.span_for_predicate_removal(where_pos);
237+
push_suggestion(sp, SuggestChangingConstraintsMessage::RemoveMaybeUnsized);
238+
}
239+
} else {
240+
// Some of the bounds are other than unsized.
241+
// So push separate removal suggestion for each unsized bound
242+
for (pos, _) in unsized_bounds {
210243
let sp = generics.span_for_bound_removal(where_pos, pos);
211-
suggestions.push((
212-
sp,
213-
String::new(),
214-
SuggestChangingConstraintsMessage::RemoveMaybeUnsized,
215-
));
244+
push_suggestion(sp, SuggestChangingConstraintsMessage::RemoveMaybeUnsized);
216245
}
217246
}
218247
}

compiler/rustc_middle/src/ty/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1268,7 +1268,7 @@ impl<'tcx> Ty<'tcx> {
12681268
///
12691269
/// Returning true means the type is known to be `Freeze`. Returning
12701270
/// `false` means nothing -- could be `Freeze`, might not be.
1271-
fn is_trivially_freeze(self) -> bool {
1271+
pub fn is_trivially_freeze(self) -> bool {
12721272
match self.kind() {
12731273
ty::Int(_)
12741274
| ty::Uint(_)

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
772772
);
773773
}
774774

775-
ty::Alias(ty::Opaque, _) => {
775+
ty::Alias(ty::Opaque, alias) => {
776776
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
777777
// We do not generate an auto impl candidate for `impl Trait`s which already
778778
// reference our auto trait.
@@ -787,6 +787,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
787787
// We do not emit auto trait candidates for opaque types in coherence.
788788
// Doing so can result in weird dependency cycles.
789789
candidates.ambiguous = true;
790+
} else if self.infcx.can_define_opaque_ty(alias.def_id) {
791+
// We do not emit auto trait candidates for opaque types in their defining scope, as
792+
// we need to know the hidden type first, which we can't reliably know within the defining
793+
// scope.
794+
candidates.ambiguous = true;
790795
} else {
791796
candidates.vec.push(AutoImplCandidate)
792797
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -2386,13 +2386,17 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
23862386
}
23872387

23882388
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
2389-
// We can resolve the `impl Trait` to its concrete type,
2390-
// which enforces a DAG between the functions requiring
2391-
// the auto trait bounds in question.
2392-
match self.tcx().type_of_opaque(def_id) {
2393-
Ok(ty) => t.rebind(vec![ty.instantiate(self.tcx(), args)]),
2394-
Err(_) => {
2395-
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
2389+
if self.infcx.can_define_opaque_ty(def_id) {
2390+
unreachable!()
2391+
} else {
2392+
// We can resolve the `impl Trait` to its concrete type,
2393+
// which enforces a DAG between the functions requiring
2394+
// the auto trait bounds in question.
2395+
match self.tcx().type_of_opaque(def_id) {
2396+
Ok(ty) => t.rebind(vec![ty.instantiate(self.tcx(), args)]),
2397+
Err(_) => {
2398+
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
2399+
}
23962400
}
23972401
}
23982402
}

library/core/src/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ where
506506
/// ```
507507
///
508508
#[unstable(feature = "error_generic_member_access", issue = "99301")]
509-
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
509+
#[repr(transparent)]
510510
pub struct Request<'a>(Tagged<dyn Erased<'a> + 'a>);
511511

512512
impl<'a> Request<'a> {

library/core/src/ffi/c_str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ use crate::str;
103103
// However, `CStr` layout is considered an implementation detail and must not be relied upon. We
104104
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
105105
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
106-
#[cfg_attr(not(doc), repr(transparent))]
106+
#[repr(transparent)]
107107
#[allow(clippy::derived_hash_with_manual_eq)]
108108
pub struct CStr {
109109
// FIXME: this should not be represented with a DST slice but rather with

library/core/src/ffi/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ mod c_long_definition {
191191
// be UB.
192192
#[doc = include_str!("c_void.md")]
193193
#[lang = "c_void"]
194-
#[cfg_attr(not(doc), repr(u8))] // work around https://github.com/rust-lang/rust/issues/90435
194+
#[cfg_attr(not(doc), repr(u8))] // An implementation detail we don't want to show up in rustdoc
195195
#[stable(feature = "core_c_void", since = "1.30.0")]
196196
pub enum c_void {
197197
#[unstable(

library/core/src/ffi/va_list.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::ops::{Deref, DerefMut};
2323
target_os = "uefi",
2424
windows,
2525
))]
26-
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
26+
#[repr(transparent)]
2727
#[lang = "va_list"]
2828
pub struct VaListImpl<'f> {
2929
ptr: *mut c_void,
@@ -115,7 +115,7 @@ pub struct VaListImpl<'f> {
115115
}
116116

117117
/// A wrapper for a `va_list`
118-
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
118+
#[repr(transparent)]
119119
#[derive(Debug)]
120120
pub struct VaList<'a, 'f: 'a> {
121121
#[cfg(any(

library/core/src/num/uint_macros.rs

+61
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,67 @@ macro_rules! uint_impl {
765765
}
766766
}
767767

768+
#[doc = concat!(
769+
"Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`",
770+
stringify!($SignedT), "`], returning `None` if overflow occurred."
771+
)]
772+
///
773+
/// # Examples
774+
///
775+
/// Basic usage:
776+
///
777+
/// ```
778+
/// #![feature(unsigned_signed_diff)]
779+
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_signed_diff(2), Some(8));")]
780+
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_signed_diff(10), Some(-8));")]
781+
#[doc = concat!(
782+
"assert_eq!(",
783+
stringify!($SelfT),
784+
"::MAX.checked_signed_diff(",
785+
stringify!($SignedT),
786+
"::MAX as ",
787+
stringify!($SelfT),
788+
"), None);"
789+
)]
790+
#[doc = concat!(
791+
"assert_eq!((",
792+
stringify!($SignedT),
793+
"::MAX as ",
794+
stringify!($SelfT),
795+
").checked_signed_diff(",
796+
stringify!($SelfT),
797+
"::MAX), Some(",
798+
stringify!($SignedT),
799+
"::MIN));"
800+
)]
801+
#[doc = concat!(
802+
"assert_eq!((",
803+
stringify!($SignedT),
804+
"::MAX as ",
805+
stringify!($SelfT),
806+
" + 1).checked_signed_diff(0), None);"
807+
)]
808+
#[doc = concat!(
809+
"assert_eq!(",
810+
stringify!($SelfT),
811+
"::MAX.checked_signed_diff(",
812+
stringify!($SelfT),
813+
"::MAX), Some(0));"
814+
)]
815+
/// ```
816+
#[unstable(feature = "unsigned_signed_diff", issue = "126041")]
817+
#[inline]
818+
pub const fn checked_signed_diff(self, rhs: Self) -> Option<$SignedT> {
819+
let res = self.wrapping_sub(rhs) as $SignedT;
820+
let overflow = (self >= rhs) == (res < 0);
821+
822+
if !overflow {
823+
Some(res)
824+
} else {
825+
None
826+
}
827+
}
828+
768829
/// Checked integer multiplication. Computes `self * rhs`, returning
769830
/// `None` if overflow occurred.
770831
///

library/core/src/task/wake.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ impl<'a> ContextBuilder<'a> {
428428
/// [`Future::poll()`]: core::future::Future::poll
429429
/// [`Poll::Pending`]: core::task::Poll::Pending
430430
/// [`Wake`]: ../../alloc/task/trait.Wake.html
431-
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
431+
#[repr(transparent)]
432432
#[stable(feature = "futures_api", since = "1.36.0")]
433433
pub struct Waker {
434434
waker: RawWaker,
@@ -692,7 +692,7 @@ impl fmt::Debug for Waker {
692692
/// [`Poll::Pending`]: core::task::Poll::Pending
693693
/// [`local_waker`]: core::task::Context::local_waker
694694
#[unstable(feature = "local_waker", issue = "118959")]
695-
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
695+
#[repr(transparent)]
696696
pub struct LocalWaker {
697697
waker: RawWaker,
698698
}

library/std/src/ffi/os_str.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,8 @@ impl crate::sealed::Sealed for OsString {}
115115
#[stable(feature = "rust1", since = "1.0.0")]
116116
// `OsStr::from_inner` current implementation relies
117117
// on `OsStr` being layout-compatible with `Slice`.
118-
// However, `OsStr` layout is considered an implementation detail and must not be relied upon. We
119-
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
120-
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
121-
#[cfg_attr(not(doc), repr(transparent))]
118+
// However, `OsStr` layout is considered an implementation detail and must not be relied upon.
119+
#[repr(transparent)]
122120
pub struct OsStr {
123121
inner: Slice,
124122
}

0 commit comments

Comments
 (0)