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

Lines changed: 27 additions & 1 deletion
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

Lines changed: 15 additions & 9 deletions
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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 49 additions & 20 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 6 additions & 1 deletion
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

Lines changed: 11 additions & 7 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

0 commit comments

Comments
 (0)