Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 419b3e2

Browse files
committedJan 15, 2025
Auto merge of rust-lang#135540 - GuillaumeGomez:rollup-40lfb7l, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - rust-lang#132654 (std: lazily allocate the main thread handle) - rust-lang#135003 (deprecate `std::intrinsics::transmute` etc, use `std::mem::*` instead) - rust-lang#135428 (rustdoc: Remove `AttributesExt` trait magic that added needless complexity) - rust-lang#135498 (Prefer lower `TraitUpcasting` candidates in selection) - rust-lang#135507 (TRPL: incorporate all backward-compatible Edition changes) - rust-lang#135529 (remove outdated FIXME) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 27f3361 + 01ae58b commit 419b3e2

File tree

39 files changed

+605
-465
lines changed

39 files changed

+605
-465
lines changed
 

‎compiler/rustc_ast/src/attr/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,8 @@ impl MetaItemLit {
723723
pub trait AttributeExt: Debug {
724724
fn id(&self) -> AttrId;
725725

726+
/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
727+
/// return the name of the attribute, else return the empty identifier.
726728
fn name_or_empty(&self) -> Symbol {
727729
self.ident().unwrap_or_else(Ident::empty).name
728730
}

‎compiler/rustc_attr_data_structures/src/stability.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ impl PartialConstStability {
101101
}
102102
}
103103

104+
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
105+
#[derive(HashStable_Generic)]
106+
pub enum AllowedThroughUnstableModules {
107+
/// This does not get a deprecation warning. We still generally would prefer people to use the
108+
/// fully stable path, and a warning will likely be emitted in the future.
109+
WithoutDeprecation,
110+
/// Emit the given deprecation warning.
111+
WithDeprecation(Symbol),
112+
}
113+
104114
/// The available stability levels.
105115
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
106116
#[derive(HashStable_Generic)]
@@ -137,9 +147,8 @@ pub enum StabilityLevel {
137147
Stable {
138148
/// Rust release which stabilized this feature.
139149
since: StableSince,
140-
/// Is this item allowed to be referred to on stable, despite being contained in unstable
141-
/// modules?
142-
allowed_through_unstable_modules: bool,
150+
/// This is `Some` if this item allowed to be referred to on stable via unstable modules.
151+
allowed_through_unstable_modules: Option<AllowedThroughUnstableModules>,
143152
},
144153
}
145154

‎compiler/rustc_attr_parsing/src/attributes/stability.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use rustc_ast::MetaItem;
66
use rustc_ast::attr::AttributeExt;
77
use rustc_ast_pretty::pprust;
88
use rustc_attr_data_structures::{
9-
ConstStability, DefaultBodyStability, Stability, StabilityLevel, StableSince, UnstableReason,
10-
VERSION_PLACEHOLDER,
9+
AllowedThroughUnstableModules, ConstStability, DefaultBodyStability, Stability, StabilityLevel,
10+
StableSince, UnstableReason, VERSION_PLACEHOLDER,
1111
};
1212
use rustc_errors::ErrorGuaranteed;
1313
use rustc_session::Session;
@@ -24,11 +24,16 @@ pub fn find_stability(
2424
item_sp: Span,
2525
) -> Option<(Stability, Span)> {
2626
let mut stab: Option<(Stability, Span)> = None;
27-
let mut allowed_through_unstable_modules = false;
27+
let mut allowed_through_unstable_modules = None;
2828

2929
for attr in attrs {
3030
match attr.name_or_empty() {
31-
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
31+
sym::rustc_allowed_through_unstable_modules => {
32+
allowed_through_unstable_modules = Some(match attr.value_str() {
33+
Some(msg) => AllowedThroughUnstableModules::WithDeprecation(msg),
34+
None => AllowedThroughUnstableModules::WithoutDeprecation,
35+
})
36+
}
3237
sym::unstable => {
3338
if stab.is_some() {
3439
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
@@ -56,15 +61,15 @@ pub fn find_stability(
5661
}
5762
}
5863

59-
if allowed_through_unstable_modules {
64+
if let Some(allowed_through_unstable_modules) = allowed_through_unstable_modules {
6065
match &mut stab {
6166
Some((
6267
Stability {
63-
level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
68+
level: StabilityLevel::Stable { allowed_through_unstable_modules: in_stab, .. },
6469
..
6570
},
6671
_,
67-
)) => *allowed_through_unstable_modules = true,
72+
)) => *in_stab = Some(allowed_through_unstable_modules),
6873
_ => {
6974
sess.dcx()
7075
.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
@@ -283,7 +288,7 @@ fn parse_stability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol,
283288

284289
match feature {
285290
Ok(feature) => {
286-
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
291+
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: None };
287292
Some((feature, level))
288293
}
289294
Err(ErrorGuaranteed { .. }) => None,

‎compiler/rustc_feature/src/builtin_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
623623
EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
624624
),
625625
rustc_attr!(
626-
rustc_allowed_through_unstable_modules, Normal, template!(Word),
626+
rustc_allowed_through_unstable_modules, Normal, template!(Word, NameValueStr: "deprecation message"),
627627
WarnFollowing, EncodeCrossCrate::No,
628628
"rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
629629
through unstable paths"

‎compiler/rustc_middle/src/middle/stability.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,18 @@ fn late_report_deprecation(
249249
return;
250250
}
251251

252+
let is_in_effect = depr.is_in_effect();
253+
let lint = deprecation_lint(is_in_effect);
254+
255+
// Calculating message for lint involves calling `self.def_path_str`,
256+
// which will by default invoke the expensive `visible_parent_map` query.
257+
// Skip all that work if the lint is allowed anyway.
258+
if tcx.lint_level_at_node(lint, hir_id).0 == Level::Allow {
259+
return;
260+
}
261+
252262
let def_path = with_no_trimmed_paths!(tcx.def_path_str(def_id));
253263
let def_kind = tcx.def_descr(def_id);
254-
let is_in_effect = depr.is_in_effect();
255264

256265
let method_span = method_span.unwrap_or(span);
257266
let suggestion =
@@ -267,7 +276,7 @@ fn late_report_deprecation(
267276
note: depr.note,
268277
since_kind: deprecated_since_kind(is_in_effect, depr.since),
269278
};
270-
tcx.emit_node_span_lint(deprecation_lint(is_in_effect), hir_id, method_span, diag);
279+
tcx.emit_node_span_lint(lint, hir_id, method_span, diag);
271280
}
272281

273282
/// Result of `TyCtxt::eval_stability`.
@@ -377,13 +386,7 @@ impl<'tcx> TyCtxt<'tcx> {
377386
// hierarchy.
378387
let depr_attr = &depr_entry.attr;
379388
if !skip || depr_attr.is_since_rustc_version() {
380-
// Calculating message for lint involves calling `self.def_path_str`.
381-
// Which by default to calculate visible path will invoke expensive `visible_parent_map` query.
382-
// So we skip message calculation altogether, if lint is allowed.
383-
let lint = deprecation_lint(depr_attr.is_in_effect());
384-
if self.lint_level_at_node(lint, id).0 != Level::Allow {
385-
late_report_deprecation(self, depr_attr, span, method_span, id, def_id);
386-
}
389+
late_report_deprecation(self, depr_attr, span, method_span, id, def_id);
387390
}
388391
};
389392
}

‎compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -741,12 +741,14 @@ where
741741
a_data.principal(),
742742
));
743743
} else if let Some(a_principal) = a_data.principal() {
744-
for new_a_principal in
745-
elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty)).skip(1)
744+
for (idx, new_a_principal) in
745+
elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
746+
.enumerate()
747+
.skip(1)
746748
{
747749
responses.extend(self.consider_builtin_upcast_to_principal(
748750
goal,
749-
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting),
751+
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
750752
a_data,
751753
a_region,
752754
b_data,

‎compiler/rustc_passes/src/stability.rs

+97-39
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::mem::replace;
55
use std::num::NonZero;
66

77
use rustc_attr_parsing::{
8-
self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince,
9-
UnstableReason, VERSION_PLACEHOLDER,
8+
self as attr, AllowedThroughUnstableModules, ConstStability, DeprecatedSince, Stability,
9+
StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER,
1010
};
1111
use rustc_data_structures::fx::FxIndexMap;
1212
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
@@ -20,11 +20,16 @@ use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
2020
use rustc_middle::hir::nested_filter;
2121
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
2222
use rustc_middle::middle::privacy::EffectiveVisibilities;
23-
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
23+
use rustc_middle::middle::stability::{
24+
AllowUnstable, Deprecated, DeprecationEntry, EvalResult, Index,
25+
};
2426
use rustc_middle::query::Providers;
2527
use rustc_middle::ty::TyCtxt;
28+
use rustc_middle::ty::print::with_no_trimmed_paths;
2629
use rustc_session::lint;
27-
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
30+
use rustc_session::lint::builtin::{
31+
DEPRECATED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED,
32+
};
2833
use rustc_span::{Span, Symbol, sym};
2934
use tracing::{debug, info};
3035

@@ -874,42 +879,95 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
874879
},
875880
);
876881

877-
let is_allowed_through_unstable_modules = |def_id| {
878-
self.tcx.lookup_stability(def_id).is_some_and(|stab| match stab.level {
879-
StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
880-
allowed_through_unstable_modules
882+
if item_is_allowed {
883+
// The item itself is allowed; check whether the path there is also allowed.
884+
let is_allowed_through_unstable_modules: Option<AllowedThroughUnstableModules> =
885+
self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level {
886+
StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
887+
allowed_through_unstable_modules
888+
}
889+
_ => None,
890+
});
891+
892+
if is_allowed_through_unstable_modules.is_none() {
893+
// Check parent modules stability as well if the item the path refers to is itself
894+
// stable. We only emit warnings for unstable path segments if the item is stable
895+
// or allowed because stability is often inherited, so the most common case is that
896+
// both the segments and the item are unstable behind the same feature flag.
897+
//
898+
// We check here rather than in `visit_path_segment` to prevent visiting the last
899+
// path segment twice
900+
//
901+
// We include special cases via #[rustc_allowed_through_unstable_modules] for items
902+
// that were accidentally stabilized through unstable paths before this check was
903+
// added, such as `core::intrinsics::transmute`
904+
let parents = path.segments.iter().rev().skip(1);
905+
for path_segment in parents {
906+
if let Some(def_id) = path_segment.res.opt_def_id() {
907+
// use `None` for id to prevent deprecation check
908+
self.tcx.check_stability_allow_unstable(
909+
def_id,
910+
None,
911+
path.span,
912+
None,
913+
if is_unstable_reexport(self.tcx, id) {
914+
AllowUnstable::Yes
915+
} else {
916+
AllowUnstable::No
917+
},
918+
);
919+
}
881920
}
882-
_ => false,
883-
})
884-
};
885-
886-
if item_is_allowed && !is_allowed_through_unstable_modules(def_id) {
887-
// Check parent modules stability as well if the item the path refers to is itself
888-
// stable. We only emit warnings for unstable path segments if the item is stable
889-
// or allowed because stability is often inherited, so the most common case is that
890-
// both the segments and the item are unstable behind the same feature flag.
891-
//
892-
// We check here rather than in `visit_path_segment` to prevent visiting the last
893-
// path segment twice
894-
//
895-
// We include special cases via #[rustc_allowed_through_unstable_modules] for items
896-
// that were accidentally stabilized through unstable paths before this check was
897-
// added, such as `core::intrinsics::transmute`
898-
let parents = path.segments.iter().rev().skip(1);
899-
for path_segment in parents {
900-
if let Some(def_id) = path_segment.res.opt_def_id() {
901-
// use `None` for id to prevent deprecation check
902-
self.tcx.check_stability_allow_unstable(
903-
def_id,
904-
None,
905-
path.span,
906-
None,
907-
if is_unstable_reexport(self.tcx, id) {
908-
AllowUnstable::Yes
909-
} else {
910-
AllowUnstable::No
911-
},
912-
);
921+
} else if let Some(AllowedThroughUnstableModules::WithDeprecation(deprecation)) =
922+
is_allowed_through_unstable_modules
923+
{
924+
// Similar to above, but we cannot use `check_stability_allow_unstable` as that would
925+
// immediately show the stability error. We just want to know the result and disaplay
926+
// our own kind of error.
927+
let parents = path.segments.iter().rev().skip(1);
928+
for path_segment in parents {
929+
if let Some(def_id) = path_segment.res.opt_def_id() {
930+
// use `None` for id to prevent deprecation check
931+
let eval_result = self.tcx.eval_stability_allow_unstable(
932+
def_id,
933+
None,
934+
path.span,
935+
None,
936+
if is_unstable_reexport(self.tcx, id) {
937+
AllowUnstable::Yes
938+
} else {
939+
AllowUnstable::No
940+
},
941+
);
942+
let is_allowed = matches!(eval_result, EvalResult::Allow);
943+
if !is_allowed {
944+
// Calculating message for lint involves calling `self.def_path_str`,
945+
// which will by default invoke the expensive `visible_parent_map` query.
946+
// Skip all that work if the lint is allowed anyway.
947+
if self.tcx.lint_level_at_node(DEPRECATED, id).0
948+
== lint::Level::Allow
949+
{
950+
return;
951+
}
952+
// Show a deprecation message.
953+
let def_path =
954+
with_no_trimmed_paths!(self.tcx.def_path_str(def_id));
955+
let def_kind = self.tcx.def_descr(def_id);
956+
let diag = Deprecated {
957+
sub: None,
958+
kind: def_kind.to_owned(),
959+
path: def_path,
960+
note: Some(deprecation),
961+
since_kind: lint::DeprecatedSinceKind::InEffect,
962+
};
963+
self.tcx.emit_node_span_lint(
964+
DEPRECATED,
965+
id,
966+
method_span.unwrap_or(path.span),
967+
diag,
968+
);
969+
}
970+
}
913971
}
914972
}
915973
}

‎compiler/rustc_trait_selection/src/solve/select.rs

+4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
117117
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(a)),
118118
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(b)),
119119
) => a >= b,
120+
(
121+
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(a)),
122+
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(b)),
123+
) => a >= b,
120124
// Prefer dyn candidates over non-dyn candidates. This is necessary to
121125
// handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
122126
(

‎compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10901090
)?
10911091
.expect("did not expect ambiguity during confirmation");
10921092

1093-
Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting, nested))
1093+
Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting(idx), nested))
10941094
}
10951095

10961096
fn confirm_builtin_unsize_candidate(

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

+12
Original file line numberDiff line numberDiff line change
@@ -1895,6 +1895,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18951895
Some(None) => {}
18961896
None => return None,
18971897
}
1898+
// Same for upcasting.
1899+
let upcast_bound = candidates
1900+
.iter()
1901+
.filter_map(|c| {
1902+
if let TraitUpcastingUnsizeCandidate(i) = c.candidate { Some(i) } else { None }
1903+
})
1904+
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
1905+
match upcast_bound {
1906+
Some(Some(index)) => return Some(TraitUpcastingUnsizeCandidate(index)),
1907+
Some(None) => {}
1908+
None => return None,
1909+
}
18981910

18991911
// Finally, handle overlapping user-written impls.
19001912
let impls = candidates.iter().filter_map(|c| {

‎compiler/rustc_type_ir/src/solve/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ pub enum BuiltinImplSource {
177177
/// A built-in implementation of `Upcast` for trait objects to other trait objects.
178178
///
179179
/// This can be removed when `feature(dyn_upcasting)` is stabilized, since we only
180-
/// use it to detect when upcasting traits in hir typeck.
181-
TraitUpcasting,
180+
/// use it to detect when upcasting traits in hir typeck. The index is only used
181+
/// for winnowing.
182+
TraitUpcasting(usize),
182183
/// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`.
183184
///
184185
/// This can be removed when `feature(tuple_unsizing)` is stabilized, since we only
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.