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 #135540

Merged
merged 20 commits into from
Jan 15, 2025
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
e2fcdb8
rustdoc: Extract `AttributesExt::cfg` trait method as function
camelid Jan 13, 2025
5ccd6c0
rustdoc: Extract `AttributesExt::lists` trait method as function
camelid Jan 13, 2025
f92b32c
rustdoc: Eliminate `AttributesExt`
camelid Jan 13, 2025
0e5ee89
Revert "Remove the Arc rt::init allocation for thread info"
joboet Nov 25, 2024
14f7f4b
std: lazily allocate the main thread handle
joboet Nov 25, 2024
1d25252
make sure that the allocator is actually called in allocator test
joboet Nov 25, 2024
2c28cc4
add comments explaining main thread identification
joboet Nov 27, 2024
bf545ce
Prefer lower TraitUpcasting candidates
compiler-errors Jan 14, 2025
7bae381
TRPL: incorporate all backward-compatible Edition changes
chriskrycho Jan 14, 2025
561a097
late_report_deprecation: move fast-path closer to the core logic
RalfJung Jan 1, 2025
cf0ab86
allowed_through_unstable_modules: support showing a deprecation messa…
RalfJung Jan 1, 2025
f1c95c9
intrinsics: deprecate calling them via the unstable std::intrinsics path
RalfJung Jan 1, 2025
7ae494a
show deprecation message in rustdoc, too
RalfJung Jan 6, 2025
896953a
remove outdated FIXME
onur-ozkan Jan 15, 2025
4c26dc5
Rollup merge of #132654 - joboet:lazy_main, r=ChrisDenton
GuillaumeGomez Jan 15, 2025
369d135
Rollup merge of #135003 - RalfJung:deprecate-allowed-through-unstable…
GuillaumeGomez Jan 15, 2025
b1d047b
Rollup merge of #135428 - camelid:attr-cleanup, r=GuillaumeGomez
GuillaumeGomez Jan 15, 2025
b1035d7
Rollup merge of #135498 - compiler-errors:dyn-upcasting-completeness,…
GuillaumeGomez Jan 15, 2025
4de739b
Rollup merge of #135507 - chriskrycho:trpl-edition-updates-stable, r=…
GuillaumeGomez Jan 15, 2025
01ae58b
Rollup merge of #135529 - onur-ozkan:outdated-fixme, r=jieyouxu
GuillaumeGomez Jan 15, 2025
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
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,8 @@ impl MetaItemLit {
pub trait AttributeExt: Debug {
fn id(&self) -> AttrId;

/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
/// return the name of the attribute, else return the empty identifier.
fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
}
Expand Down
15 changes: 12 additions & 3 deletions compiler/rustc_attr_data_structures/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ impl PartialConstStability {
}
}

#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
#[derive(HashStable_Generic)]
pub enum AllowedThroughUnstableModules {
/// This does not get a deprecation warning. We still generally would prefer people to use the
/// fully stable path, and a warning will likely be emitted in the future.
WithoutDeprecation,
/// Emit the given deprecation warning.
WithDeprecation(Symbol),
}

/// The available stability levels.
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
#[derive(HashStable_Generic)]
Expand Down Expand Up @@ -137,9 +147,8 @@ pub enum StabilityLevel {
Stable {
/// Rust release which stabilized this feature.
since: StableSince,
/// Is this item allowed to be referred to on stable, despite being contained in unstable
/// modules?
allowed_through_unstable_modules: bool,
/// This is `Some` if this item allowed to be referred to on stable via unstable modules.
allowed_through_unstable_modules: Option<AllowedThroughUnstableModules>,
},
}

Expand Down
21 changes: 13 additions & 8 deletions compiler/rustc_attr_parsing/src/attributes/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use rustc_ast::MetaItem;
use rustc_ast::attr::AttributeExt;
use rustc_ast_pretty::pprust;
use rustc_attr_data_structures::{
ConstStability, DefaultBodyStability, Stability, StabilityLevel, StableSince, UnstableReason,
VERSION_PLACEHOLDER,
AllowedThroughUnstableModules, ConstStability, DefaultBodyStability, Stability, StabilityLevel,
StableSince, UnstableReason, VERSION_PLACEHOLDER,
};
use rustc_errors::ErrorGuaranteed;
use rustc_session::Session;
Expand All @@ -24,11 +24,16 @@ pub fn find_stability(
item_sp: Span,
) -> Option<(Stability, Span)> {
let mut stab: Option<(Stability, Span)> = None;
let mut allowed_through_unstable_modules = false;
let mut allowed_through_unstable_modules = None;

for attr in attrs {
match attr.name_or_empty() {
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
sym::rustc_allowed_through_unstable_modules => {
allowed_through_unstable_modules = Some(match attr.value_str() {
Some(msg) => AllowedThroughUnstableModules::WithDeprecation(msg),
None => AllowedThroughUnstableModules::WithoutDeprecation,
})
}
sym::unstable => {
if stab.is_some() {
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
Expand Down Expand Up @@ -56,15 +61,15 @@ pub fn find_stability(
}
}

if allowed_through_unstable_modules {
if let Some(allowed_through_unstable_modules) = allowed_through_unstable_modules {
match &mut stab {
Some((
Stability {
level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
level: StabilityLevel::Stable { allowed_through_unstable_modules: in_stab, .. },
..
},
_,
)) => *allowed_through_unstable_modules = true,
)) => *in_stab = Some(allowed_through_unstable_modules),
_ => {
sess.dcx()
.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
Expand Down Expand Up @@ -283,7 +288,7 @@ fn parse_stability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol,

match feature {
Ok(feature) => {
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: None };
Some((feature, level))
}
Err(ErrorGuaranteed { .. }) => None,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
),
rustc_attr!(
rustc_allowed_through_unstable_modules, Normal, template!(Word),
rustc_allowed_through_unstable_modules, Normal, template!(Word, NameValueStr: "deprecation message"),
WarnFollowing, EncodeCrossCrate::No,
"rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
through unstable paths"
Expand Down
21 changes: 12 additions & 9 deletions compiler/rustc_middle/src/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,18 @@ fn late_report_deprecation(
return;
}

let is_in_effect = depr.is_in_effect();
let lint = deprecation_lint(is_in_effect);

// Calculating message for lint involves calling `self.def_path_str`,
// which will by default invoke the expensive `visible_parent_map` query.
// Skip all that work if the lint is allowed anyway.
if tcx.lint_level_at_node(lint, hir_id).0 == Level::Allow {
return;
}

let def_path = with_no_trimmed_paths!(tcx.def_path_str(def_id));
let def_kind = tcx.def_descr(def_id);
let is_in_effect = depr.is_in_effect();

let method_span = method_span.unwrap_or(span);
let suggestion =
Expand All @@ -267,7 +276,7 @@ fn late_report_deprecation(
note: depr.note,
since_kind: deprecated_since_kind(is_in_effect, depr.since),
};
tcx.emit_node_span_lint(deprecation_lint(is_in_effect), hir_id, method_span, diag);
tcx.emit_node_span_lint(lint, hir_id, method_span, diag);
}

/// Result of `TyCtxt::eval_stability`.
Expand Down Expand Up @@ -377,13 +386,7 @@ impl<'tcx> TyCtxt<'tcx> {
// hierarchy.
let depr_attr = &depr_entry.attr;
if !skip || depr_attr.is_since_rustc_version() {
// Calculating message for lint involves calling `self.def_path_str`.
// Which by default to calculate visible path will invoke expensive `visible_parent_map` query.
// So we skip message calculation altogether, if lint is allowed.
let lint = deprecation_lint(depr_attr.is_in_effect());
if self.lint_level_at_node(lint, id).0 != Level::Allow {
late_report_deprecation(self, depr_attr, span, method_span, id, def_id);
}
late_report_deprecation(self, depr_attr, span, method_span, id, def_id);
}
};
}
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,12 +741,14 @@ where
a_data.principal(),
));
} else if let Some(a_principal) = a_data.principal() {
for new_a_principal in
elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty)).skip(1)
for (idx, new_a_principal) in
elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
.enumerate()
.skip(1)
{
responses.extend(self.consider_builtin_upcast_to_principal(
goal,
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting),
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
a_data,
a_region,
b_data,
Expand Down
136 changes: 97 additions & 39 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use std::mem::replace;
use std::num::NonZero;

use rustc_attr_parsing::{
self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince,
UnstableReason, VERSION_PLACEHOLDER,
self as attr, AllowedThroughUnstableModules, ConstStability, DeprecatedSince, Stability,
StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER,
};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
Expand All @@ -20,11 +20,16 @@ use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
use rustc_middle::middle::stability::{
AllowUnstable, Deprecated, DeprecationEntry, EvalResult, Index,
};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::lint;
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
use rustc_session::lint::builtin::{
DEPRECATED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED,
};
use rustc_span::{Span, Symbol, sym};
use tracing::{debug, info};

Expand Down Expand Up @@ -874,42 +879,95 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
},
);

let is_allowed_through_unstable_modules = |def_id| {
self.tcx.lookup_stability(def_id).is_some_and(|stab| match stab.level {
StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
allowed_through_unstable_modules
if item_is_allowed {
// The item itself is allowed; check whether the path there is also allowed.
let is_allowed_through_unstable_modules: Option<AllowedThroughUnstableModules> =
self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level {
StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
allowed_through_unstable_modules
}
_ => None,
});

if is_allowed_through_unstable_modules.is_none() {
// Check parent modules stability as well if the item the path refers to is itself
// stable. We only emit warnings for unstable path segments if the item is stable
// or allowed because stability is often inherited, so the most common case is that
// both the segments and the item are unstable behind the same feature flag.
//
// We check here rather than in `visit_path_segment` to prevent visiting the last
// path segment twice
//
// We include special cases via #[rustc_allowed_through_unstable_modules] for items
// that were accidentally stabilized through unstable paths before this check was
// added, such as `core::intrinsics::transmute`
let parents = path.segments.iter().rev().skip(1);
for path_segment in parents {
if let Some(def_id) = path_segment.res.opt_def_id() {
// use `None` for id to prevent deprecation check
self.tcx.check_stability_allow_unstable(
def_id,
None,
path.span,
None,
if is_unstable_reexport(self.tcx, id) {
AllowUnstable::Yes
} else {
AllowUnstable::No
},
);
}
}
_ => false,
})
};

if item_is_allowed && !is_allowed_through_unstable_modules(def_id) {
// Check parent modules stability as well if the item the path refers to is itself
// stable. We only emit warnings for unstable path segments if the item is stable
// or allowed because stability is often inherited, so the most common case is that
// both the segments and the item are unstable behind the same feature flag.
//
// We check here rather than in `visit_path_segment` to prevent visiting the last
// path segment twice
//
// We include special cases via #[rustc_allowed_through_unstable_modules] for items
// that were accidentally stabilized through unstable paths before this check was
// added, such as `core::intrinsics::transmute`
let parents = path.segments.iter().rev().skip(1);
for path_segment in parents {
if let Some(def_id) = path_segment.res.opt_def_id() {
// use `None` for id to prevent deprecation check
self.tcx.check_stability_allow_unstable(
def_id,
None,
path.span,
None,
if is_unstable_reexport(self.tcx, id) {
AllowUnstable::Yes
} else {
AllowUnstable::No
},
);
} else if let Some(AllowedThroughUnstableModules::WithDeprecation(deprecation)) =
is_allowed_through_unstable_modules
{
// Similar to above, but we cannot use `check_stability_allow_unstable` as that would
// immediately show the stability error. We just want to know the result and disaplay
// our own kind of error.
let parents = path.segments.iter().rev().skip(1);
for path_segment in parents {
if let Some(def_id) = path_segment.res.opt_def_id() {
// use `None` for id to prevent deprecation check
let eval_result = self.tcx.eval_stability_allow_unstable(
def_id,
None,
path.span,
None,
if is_unstable_reexport(self.tcx, id) {
AllowUnstable::Yes
} else {
AllowUnstable::No
},
);
let is_allowed = matches!(eval_result, EvalResult::Allow);
if !is_allowed {
// Calculating message for lint involves calling `self.def_path_str`,
// which will by default invoke the expensive `visible_parent_map` query.
// Skip all that work if the lint is allowed anyway.
if self.tcx.lint_level_at_node(DEPRECATED, id).0
== lint::Level::Allow
{
return;
}
// Show a deprecation message.
let def_path =
with_no_trimmed_paths!(self.tcx.def_path_str(def_id));
let def_kind = self.tcx.def_descr(def_id);
let diag = Deprecated {
sub: None,
kind: def_kind.to_owned(),
path: def_path,
note: Some(deprecation),
since_kind: lint::DeprecatedSinceKind::InEffect,
};
self.tcx.emit_node_span_lint(
DEPRECATED,
id,
method_span.unwrap_or(path.span),
diag,
);
}
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_trait_selection/src/solve/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(a)),
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(b)),
) => a >= b,
(
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(a)),
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(b)),
) => a >= b,
// Prefer dyn candidates over non-dyn candidates. This is necessary to
// handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)?
.expect("did not expect ambiguity during confirmation");

Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting, nested))
Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting(idx), nested))
}

fn confirm_builtin_unsize_candidate(
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
Some(None) => {}
None => return None,
}
// Same for upcasting.
let upcast_bound = candidates
.iter()
.filter_map(|c| {
if let TraitUpcastingUnsizeCandidate(i) = c.candidate { Some(i) } else { None }
})
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
match upcast_bound {
Some(Some(index)) => return Some(TraitUpcastingUnsizeCandidate(index)),
Some(None) => {}
None => return None,
}

// Finally, handle overlapping user-written impls.
let impls = candidates.iter().filter_map(|c| {
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_type_ir/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,9 @@ pub enum BuiltinImplSource {
/// A built-in implementation of `Upcast` for trait objects to other trait objects.
///
/// This can be removed when `feature(dyn_upcasting)` is stabilized, since we only
/// use it to detect when upcasting traits in hir typeck.
TraitUpcasting,
/// use it to detect when upcasting traits in hir typeck. The index is only used
/// for winnowing.
TraitUpcasting(usize),
/// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`.
///
/// This can be removed when `feature(tuple_unsizing)` is stabilized, since we only
Expand Down
Loading
Loading