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 5 pull requests #94200

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 25 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,31 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
}

// Emit errors for non-staged-api crates.
if !self.features.staged_api {
if attr.has_name(sym::rustc_deprecated)
|| attr.has_name(sym::unstable)
|| attr.has_name(sym::stable)
|| attr.has_name(sym::rustc_const_unstable)
|| attr.has_name(sym::rustc_const_stable)
{
struct_span_err!(
self.sess,
attr.span,
E0734,
"stability attributes may not be used outside of the standard library",
)
.emit();
}
} else {
if attr.has_name(sym::deprecated) {
self.sess
.struct_span_err(attr.span, "`#[deprecated]` cannot be used in staged API")
.span_label(attr.span, "use `#[rustc_deprecated]` instead")
.emit();
}
}
}

fn visit_item(&mut self, i: &'a ast::Item) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
this.ecx.read_discriminant(op),
this.path,
err_ub!(InvalidTag(val)) =>
{ "{}", val } expected { "a valid enum tag" },
{ "{:x}", val } expected { "a valid enum tag" },
err_ub!(InvalidUninitBytes(None)) =>
{ "uninitialized bytes" } expected { "a valid enum tag" },
err_unsup!(ReadPointerAsBytes) =>
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ fn get_features(
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
let since = Some(Symbol::intern(since));
features.declared_lang_features.push((name, mi.span(), since));
features.active_features.insert(name);
continue;
}

Expand All @@ -185,10 +186,12 @@ fn get_features(
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
f.set(&mut features, mi.span());
features.declared_lang_features.push((name, mi.span(), None));
features.active_features.insert(name);
continue;
}

features.declared_lib_features.push((name, mi.span()));
features.active_features.insert(name);
}
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use super::{to_nonzero, Feature, State};

use rustc_data_structures::fx::FxHashSet;
use rustc_span::edition::Edition;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
Expand Down Expand Up @@ -47,6 +48,8 @@ macro_rules! declare_features {
pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
/// `#![feature]` attrs for non-language (library) features.
pub declared_lib_features: Vec<(Symbol, Span)>,
/// Features enabled for this crate.
pub active_features: FxHashSet<Symbol>,
$(
$(#[doc = $doc])*
pub $feature: bool
Expand All @@ -58,6 +61,11 @@ macro_rules! declare_features {
$(f(stringify!($feature), self.$feature);)+
}

/// Is the given feature active?
pub fn active(&self, feature: Symbol) -> bool {
self.active_features.contains(&feature)
}

/// Is the given feature enabled?
///
/// Panics if the symbol doesn't correspond to a declared feature.
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,12 +932,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
tcx.ensure().check_mod_const_bodies(module);
});
},
{
sess.time("unused_lib_feature_checking", || {
rustc_passes::stability::check_unused_or_stable_features(tcx)
});
},
{
// We force these querie to run,
// since they might not otherwise get called.
// This marks the corresponding crate-level attributes
// as used, and ensures that their values are valid.
tcx.ensure().limits(());
tcx.ensure().stability_index(());
}
);
});
Expand Down Expand Up @@ -1009,11 +1015,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
tcx.hir()
.par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
},
{
sess.time("unused_lib_feature_checking", || {
rustc_passes::stability::check_unused_or_stable_features(tcx)
});
},
{
sess.time("lint_checking", || {
rustc_lint::check_crate(tcx, || {
Expand Down
12 changes: 3 additions & 9 deletions compiler/rustc_middle/src/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ pub use self::StabilityLevel::*;
use crate::ty::{self, DefIdTree, TyCtxt};
use rustc_ast::NodeId;
use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_feature::GateIssue;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
use rustc_hir::{self, HirId};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
Expand Down Expand Up @@ -63,12 +63,6 @@ pub struct Index<'tcx> {
pub stab_map: FxHashMap<LocalDefId, &'tcx Stability>,
pub const_stab_map: FxHashMap<LocalDefId, &'tcx ConstStability>,
pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,

/// Maps for each crate whether it is part of the staged API.
pub staged_api: FxHashMap<CrateNum, bool>,

/// Features enabled for this crate.
pub active_features: FxHashSet<Symbol>,
}

impl<'tcx> Index<'tcx> {
Expand Down Expand Up @@ -423,7 +417,7 @@ impl<'tcx> TyCtxt<'tcx> {
debug!("stability: skipping span={:?} since it is internal", span);
return EvalResult::Allow;
}
if self.stability().active_features.contains(&feature) {
if self.features().active(feature) {
return EvalResult::Allow;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
InvalidChar(c) => {
write!(f, "interpreting an invalid 32-bit value as a char: 0x{:08x}", c)
}
InvalidTag(val) => write!(f, "enum value has invalid tag: {}", val),
InvalidTag(val) => write!(f, "enum value has invalid tag: {:x}", val),
InvalidFunctionPointer(p) => {
write!(f, "using {:?} as function pointer but it does not point to a function", p)
}
Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_middle/src/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,16 @@ impl<Tag: Provenance> fmt::Display for Scalar<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
Scalar::Int(int) => write!(f, "{:?}", int),
Scalar::Int(int) => write!(f, "{}", int),
}
}
}

impl<Tag: Provenance> fmt::LowerHex for Scalar<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
Scalar::Int(int) => write!(f, "0x{:x}", int),
}
}
}
Expand Down Expand Up @@ -456,11 +465,6 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
// Going through `u64` to check size and truncation.
Ok(Double::from_bits(self.to_u64()?.into()))
}

// FIXME: Replace current `impl Display for Scalar` with `impl LowerHex`.
pub fn rustdoc_display(&self) -> String {
if let Scalar::Int(int) = self { int.to_string() } else { self.to_string() }
}
}

#[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, HashStable, Hash)]
Expand Down Expand Up @@ -494,7 +498,7 @@ impl<Tag: Provenance> fmt::Display for ScalarMaybeUninit<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ScalarMaybeUninit::Uninit => write!(f, "uninitialized bytes"),
ScalarMaybeUninit::Scalar(s) => write!(f, "{}", s),
ScalarMaybeUninit::Scalar(s) => write!(f, "{:x}", s),
}
}
}
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2962,11 +2962,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
};

providers.lookup_stability = |tcx, id| tcx.stability().local_stability(id.expect_local());
providers.lookup_const_stability =
|tcx, id| tcx.stability().local_const_stability(id.expect_local());
providers.lookup_deprecation_entry =
|tcx, id| tcx.stability().local_deprecation_entry(id.expect_local());
providers.extern_mod_stmt_cnum =
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
providers.output_filenames = |tcx, ()| &tcx.output_filenames;
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,8 +1436,7 @@ pub trait PrettyPrinter<'tcx>:
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
p!(write("{:?}", s));
p!(write("{:?}", String::from_utf8_lossy(slice)));
Ok(self)
}
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
Expand Down
101 changes: 24 additions & 77 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.

use rustc_ast::Attribute;
use rustc_attr::{self as attr, ConstStability, Stability};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX};
use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
Expand Down Expand Up @@ -113,12 +112,8 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
let attrs = self.tcx.get_attrs(def_id.to_def_id());
debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
let mut did_error = false;
if !self.tcx.features().staged_api {
did_error = self.forbid_staged_api_attrs(def_id, attrs, inherit_deprecation.clone());
}

let depr = if did_error { None } else { attr::find_deprecation(&self.tcx.sess, attrs) };
let depr = attr::find_deprecation(&self.tcx.sess, attrs);
let mut is_deprecated = false;
if let Some((depr, span)) = &depr {
is_deprecated = true;
Expand Down Expand Up @@ -148,16 +143,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
}

if self.tcx.features().staged_api {
if let Some(a) = attrs.iter().find(|a| a.has_name(sym::deprecated)) {
self.tcx
.sess
.struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API")
.span_label(a.span, "use `#[rustc_deprecated]` instead")
.span_label(item_sp, "")
.emit();
if !self.tcx.features().staged_api {
// Propagate unstability. This can happen even for non-staged-api crates in case
// -Zforce-unstable-if-unmarked is set.
if let Some(stab) = self.parent_stab {
if inherit_deprecation.yes() && stab.level.is_unstable() {
self.index.stab_map.insert(def_id, stab);
}
}
} else {

self.recurse_with_stability_attrs(
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
None,
Expand Down Expand Up @@ -331,47 +325,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
self.parent_const_stab = orig_parent_const_stab;
}
}

// returns true if an error occurred, used to suppress some spurious errors
fn forbid_staged_api_attrs(
&mut self,
def_id: LocalDefId,
attrs: &[Attribute],
inherit_deprecation: InheritDeprecation,
) -> bool {
// Emit errors for non-staged-api crates.
let unstable_attrs = [
sym::unstable,
sym::stable,
sym::rustc_deprecated,
sym::rustc_const_unstable,
sym::rustc_const_stable,
];
let mut has_error = false;
for attr in attrs {
let name = attr.name_or_empty();
if unstable_attrs.contains(&name) {
struct_span_err!(
self.tcx.sess,
attr.span,
E0734,
"stability attributes may not be used outside of the standard library",
)
.emit();
has_error = true;
}
}

// Propagate unstability. This can happen even for non-staged-api crates in case
// -Zforce-unstable-if-unmarked is set.
if let Some(stab) = self.parent_stab {
if inherit_deprecation.yes() && stab.level.is_unstable() {
self.index.stab_map.insert(def_id, stab);
}
}

has_error
}
}

impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
Expand Down Expand Up @@ -656,28 +609,12 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
}

fn stability_index<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
let is_staged_api =
tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api;
let mut staged_api = FxHashMap::default();
staged_api.insert(LOCAL_CRATE, is_staged_api);
let mut index = Index {
staged_api,
stab_map: Default::default(),
const_stab_map: Default::default(),
depr_map: Default::default(),
active_features: Default::default(),
};

let active_lib_features = &tcx.features().declared_lib_features;
let active_lang_features = &tcx.features().declared_lang_features;

// Put the active features into a map for quick lookup.
index.active_features = active_lib_features
.iter()
.map(|&(s, ..)| s)
.chain(active_lang_features.iter().map(|&(s, ..)| s))
.collect();

{
let mut annotator = Annotator {
tcx,
Expand Down Expand Up @@ -730,7 +667,16 @@ fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
}

pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_unstable_api_usage, stability_index, ..*providers };
*providers = Providers {
check_mod_unstable_api_usage,
stability_index,
lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
lookup_deprecation_entry: |tcx, id| {
tcx.stability().local_deprecation_entry(id.expect_local())
},
..*providers
};
}

struct Checker<'tcx> {
Expand Down Expand Up @@ -886,9 +832,10 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
/// were expected to be library features), and the list of features used from
/// libraries, identify activated features that don't exist and error about them.
pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let access_levels = &tcx.privacy_access_levels(());

if tcx.stability().staged_api[&LOCAL_CRATE] {
let is_staged_api =
tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api;
if is_staged_api {
let access_levels = &tcx.privacy_access_levels(());
let mut missing = MissingStabilityAnnotations { tcx, access_levels };
missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
tcx.hir().walk_toplevel_module(&mut missing);
Expand Down
Loading