Auto merge of #97825 - Dylan-DPC:rollup-ya51k1k, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #97058 (Various refactors to the incr comp workproduct handling) - #97301 (Allow unstable items to be re-exported unstably without requiring the feature be enabled) - #97738 (Fix ICEs from zsts within unsized types with non-zero offsets) - #97771 (Remove SIGIO reference on Haiku) - #97808 (Add some unstable target features for the wasm target codegen) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7fe2c4b00d
18 changed files with 284 additions and 115 deletions
|
@ -66,11 +66,7 @@ fn emit_module(
|
||||||
let work_product = if backend_config.disable_incr_cache {
|
let work_product = if backend_config.disable_incr_cache {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
|
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(tcx.sess, &name, &tmp_file)
|
||||||
tcx.sess,
|
|
||||||
&name,
|
|
||||||
&Some(tmp_file.clone()),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ModuleCodegenResult(
|
ModuleCodegenResult(
|
||||||
|
@ -84,21 +80,16 @@ fn reuse_workproduct_for_cgu(
|
||||||
cgu: &CodegenUnit<'_>,
|
cgu: &CodegenUnit<'_>,
|
||||||
work_products: &mut FxHashMap<WorkProductId, WorkProduct>,
|
work_products: &mut FxHashMap<WorkProductId, WorkProduct>,
|
||||||
) -> CompiledModule {
|
) -> CompiledModule {
|
||||||
let mut object = None;
|
let work_product = cgu.previous_work_product(tcx);
|
||||||
let work_product = cgu.work_product(tcx);
|
let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str()));
|
||||||
if let Some(saved_file) = &work_product.saved_file {
|
let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &work_product.saved_file);
|
||||||
let obj_out =
|
if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
|
||||||
tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str()));
|
tcx.sess.err(&format!(
|
||||||
object = Some(obj_out.clone());
|
"unable to copy {} to {}: {}",
|
||||||
let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &saved_file);
|
source_file.display(),
|
||||||
if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
|
obj_out.display(),
|
||||||
tcx.sess.err(&format!(
|
err
|
||||||
"unable to copy {} to {}: {}",
|
));
|
||||||
source_file.display(),
|
|
||||||
obj_out.display(),
|
|
||||||
err
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
work_products.insert(cgu.work_product_id(), work_product);
|
work_products.insert(cgu.work_product_id(), work_product);
|
||||||
|
@ -106,7 +97,7 @@ fn reuse_workproduct_for_cgu(
|
||||||
CompiledModule {
|
CompiledModule {
|
||||||
name: cgu.name().to_string(),
|
name: cgu.name().to_string(),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
object,
|
object: Some(obj_out),
|
||||||
dwarf_object: None,
|
dwarf_object: None,
|
||||||
bytecode: None,
|
bytecode: None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,12 +494,12 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
|
||||||
let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");
|
let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");
|
||||||
|
|
||||||
for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
|
for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
|
||||||
let path = module.object.as_ref().cloned();
|
if let Some(path) = &module.object {
|
||||||
|
if let Some((id, product)) =
|
||||||
if let Some((id, product)) =
|
copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, path)
|
||||||
copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, &path)
|
{
|
||||||
{
|
work_products.insert(id, product);
|
||||||
work_products.insert(id, product);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,35 +853,31 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
||||||
module: CachedModuleCodegen,
|
module: CachedModuleCodegen,
|
||||||
module_config: &ModuleConfig,
|
module_config: &ModuleConfig,
|
||||||
) -> WorkItemResult<B> {
|
) -> WorkItemResult<B> {
|
||||||
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
|
assert!(module_config.emit_obj != EmitObj::None);
|
||||||
let mut object = None;
|
|
||||||
if let Some(saved_file) = module.source.saved_file {
|
|
||||||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name));
|
|
||||||
object = Some(obj_out.clone());
|
|
||||||
let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file);
|
|
||||||
debug!(
|
|
||||||
"copying pre-existing module `{}` from {:?} to {}",
|
|
||||||
module.name,
|
|
||||||
source_file,
|
|
||||||
obj_out.display()
|
|
||||||
);
|
|
||||||
if let Err(err) = link_or_copy(&source_file, &obj_out) {
|
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
|
||||||
diag_handler.err(&format!(
|
|
||||||
"unable to copy {} to {}: {}",
|
|
||||||
source_file.display(),
|
|
||||||
obj_out.display(),
|
|
||||||
err
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None);
|
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
|
||||||
|
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name));
|
||||||
|
let source_file = in_incr_comp_dir(&incr_comp_session_dir, &module.source.saved_file);
|
||||||
|
debug!(
|
||||||
|
"copying pre-existing module `{}` from {:?} to {}",
|
||||||
|
module.name,
|
||||||
|
source_file,
|
||||||
|
obj_out.display()
|
||||||
|
);
|
||||||
|
if let Err(err) = link_or_copy(&source_file, &obj_out) {
|
||||||
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
|
diag_handler.err(&format!(
|
||||||
|
"unable to copy {} to {}: {}",
|
||||||
|
source_file.display(),
|
||||||
|
obj_out.display(),
|
||||||
|
err
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
WorkItemResult::Compiled(CompiledModule {
|
WorkItemResult::Compiled(CompiledModule {
|
||||||
name: module.name,
|
name: module.name,
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
object,
|
object: Some(obj_out),
|
||||||
dwarf_object: None,
|
dwarf_object: None,
|
||||||
bytecode: None,
|
bytecode: None,
|
||||||
})
|
})
|
||||||
|
|
|
@ -216,11 +216,12 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
for i in 0..src_layout.fields.count() {
|
for i in 0..src_layout.fields.count() {
|
||||||
let src_f = src_layout.field(bx.cx(), i);
|
let src_f = src_layout.field(bx.cx(), i);
|
||||||
assert_eq!(src_layout.fields.offset(i).bytes(), 0);
|
|
||||||
assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
|
|
||||||
if src_f.is_zst() {
|
if src_f.is_zst() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_eq!(src_layout.fields.offset(i).bytes(), 0);
|
||||||
|
assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
|
||||||
assert_eq!(src_layout.size, src_f.size);
|
assert_eq!(src_layout.size, src_f.size);
|
||||||
|
|
||||||
let dst_f = dst_layout.field(bx.cx(), i);
|
let dst_f = dst_layout.field(bx.cx(), i);
|
||||||
|
@ -716,7 +717,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
&ongoing_codegen.coordinator_send,
|
&ongoing_codegen.coordinator_send,
|
||||||
CachedModuleCodegen {
|
CachedModuleCodegen {
|
||||||
name: cgu.name().to_string(),
|
name: cgu.name().to_string(),
|
||||||
source: cgu.work_product(tcx),
|
source: cgu.previous_work_product(tcx),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
true
|
true
|
||||||
|
@ -727,7 +728,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
&ongoing_codegen.coordinator_send,
|
&ongoing_codegen.coordinator_send,
|
||||||
CachedModuleCodegen {
|
CachedModuleCodegen {
|
||||||
name: cgu.name().to_string(),
|
name: cgu.name().to_string(),
|
||||||
source: cgu.work_product(tcx),
|
source: cgu.previous_work_product(tcx),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
true
|
true
|
||||||
|
|
|
@ -246,6 +246,9 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||||
("simd128", None),
|
("simd128", None),
|
||||||
("atomics", Some(sym::wasm_target_feature)),
|
("atomics", Some(sym::wasm_target_feature)),
|
||||||
("nontrapping-fptoint", Some(sym::wasm_target_feature)),
|
("nontrapping-fptoint", Some(sym::wasm_target_feature)),
|
||||||
|
("bulk-memory", Some(sym::wasm_target_feature)),
|
||||||
|
("mutable-globals", Some(sym::wasm_target_feature)),
|
||||||
|
("reference-types", Some(sym::wasm_target_feature)),
|
||||||
];
|
];
|
||||||
|
|
||||||
const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];
|
const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];
|
||||||
|
|
|
@ -162,18 +162,16 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||||
|
|
||||||
for swp in work_products {
|
for swp in work_products {
|
||||||
let mut all_files_exist = true;
|
let mut all_files_exist = true;
|
||||||
if let Some(ref file_name) = swp.work_product.saved_file {
|
let path = in_incr_comp_dir_sess(sess, &swp.work_product.saved_file);
|
||||||
let path = in_incr_comp_dir_sess(sess, file_name);
|
if !path.exists() {
|
||||||
if !path.exists() {
|
all_files_exist = false;
|
||||||
all_files_exist = false;
|
|
||||||
|
|
||||||
if sess.opts.debugging_opts.incremental_info {
|
if sess.opts.debugging_opts.incremental_info {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"incremental: could not find file for work \
|
"incremental: could not find file for work \
|
||||||
product: {}",
|
product: {}",
|
||||||
path.display()
|
path.display()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,11 +107,7 @@ pub fn save_work_product_index(
|
||||||
for (id, wp) in previous_work_products.iter() {
|
for (id, wp) in previous_work_products.iter() {
|
||||||
if !new_work_products.contains_key(id) {
|
if !new_work_products.contains_key(id) {
|
||||||
work_product::delete_workproduct_files(sess, wp);
|
work_product::delete_workproduct_files(sess, wp);
|
||||||
debug_assert!(
|
debug_assert!(!in_incr_comp_dir_sess(sess, &wp.saved_file).exists());
|
||||||
wp.saved_file.as_ref().map_or(true, |file_name| {
|
|
||||||
!in_incr_comp_dir_sess(sess, &file_name).exists()
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +115,7 @@ pub fn save_work_product_index(
|
||||||
debug_assert!({
|
debug_assert!({
|
||||||
new_work_products
|
new_work_products
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(_, wp)| wp.saved_file.iter())
|
.map(|(_, wp)| in_incr_comp_dir_sess(sess, &wp.saved_file))
|
||||||
.map(|name| in_incr_comp_dir_sess(sess, name))
|
|
||||||
.all(|path| path.exists())
|
.all(|path| path.exists())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,34 +7,30 @@ use rustc_fs_util::link_or_copy;
|
||||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use std::fs as std_fs;
|
use std::fs as std_fs;
|
||||||
use std::path::PathBuf;
|
use std::path::Path;
|
||||||
|
|
||||||
/// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it.
|
/// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it.
|
||||||
pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
|
pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
cgu_name: &str,
|
cgu_name: &str,
|
||||||
path: &Option<PathBuf>,
|
path: &Path,
|
||||||
) -> Option<(WorkProductId, WorkProduct)> {
|
) -> Option<(WorkProductId, WorkProduct)> {
|
||||||
debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path);
|
debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path);
|
||||||
sess.opts.incremental.as_ref()?;
|
sess.opts.incremental.as_ref()?;
|
||||||
|
|
||||||
let saved_file = if let Some(path) = path {
|
let file_name = format!("{}.o", cgu_name);
|
||||||
let file_name = format!("{}.o", cgu_name);
|
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
|
||||||
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
|
let saved_file = match link_or_copy(path, &path_in_incr_dir) {
|
||||||
match link_or_copy(path, &path_in_incr_dir) {
|
Ok(_) => file_name,
|
||||||
Ok(_) => Some(file_name),
|
Err(err) => {
|
||||||
Err(err) => {
|
sess.warn(&format!(
|
||||||
sess.warn(&format!(
|
"error copying object file `{}` to incremental directory as `{}`: {}",
|
||||||
"error copying object file `{}` to incremental directory as `{}`: {}",
|
path.display(),
|
||||||
path.display(),
|
path_in_incr_dir.display(),
|
||||||
path_in_incr_dir.display(),
|
err
|
||||||
err
|
));
|
||||||
));
|
return None;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file };
|
let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file };
|
||||||
|
@ -45,17 +41,15 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
|
||||||
|
|
||||||
/// Removes files for a given work product.
|
/// Removes files for a given work product.
|
||||||
pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
|
pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
|
||||||
if let Some(ref file_name) = work_product.saved_file {
|
let path = in_incr_comp_dir_sess(sess, &work_product.saved_file);
|
||||||
let path = in_incr_comp_dir_sess(sess, file_name);
|
match std_fs::remove_file(&path) {
|
||||||
match std_fs::remove_file(&path) {
|
Ok(()) => {}
|
||||||
Ok(()) => {}
|
Err(err) => {
|
||||||
Err(err) => {
|
sess.warn(&format!(
|
||||||
sess.warn(&format!(
|
"file-system error deleting outdated file `{}`: {}",
|
||||||
"file-system error deleting outdated file `{}`: {}",
|
path.display(),
|
||||||
path.display(),
|
err
|
||||||
err
|
));
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,9 @@ use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{Applicability, Diagnostic};
|
use rustc_errors::{Applicability, Diagnostic};
|
||||||
use rustc_feature::GateIssue;
|
use rustc_feature::GateIssue;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::{self, HirId};
|
use rustc_hir::{self as hir, HirId};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
|
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
|
||||||
use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
|
use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
|
||||||
|
@ -306,6 +305,14 @@ fn suggestion_for_allocator_api(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An override option for eval_stability.
|
||||||
|
pub enum AllowUnstable {
|
||||||
|
/// Don't emit an unstable error for the item
|
||||||
|
Yes,
|
||||||
|
/// Handle the item normally
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Evaluates the stability of an item.
|
/// Evaluates the stability of an item.
|
||||||
///
|
///
|
||||||
|
@ -322,6 +329,28 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
id: Option<HirId>,
|
id: Option<HirId>,
|
||||||
span: Span,
|
span: Span,
|
||||||
method_span: Option<Span>,
|
method_span: Option<Span>,
|
||||||
|
) -> EvalResult {
|
||||||
|
self.eval_stability_allow_unstable(def_id, id, span, method_span, AllowUnstable::No)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Evaluates the stability of an item.
|
||||||
|
///
|
||||||
|
/// Returns `EvalResult::Allow` if the item is stable, or unstable but the corresponding
|
||||||
|
/// `#![feature]` has been provided. Returns `EvalResult::Deny` which describes the offending
|
||||||
|
/// unstable feature otherwise.
|
||||||
|
///
|
||||||
|
/// If `id` is `Some(_)`, this function will also check if the item at `def_id` has been
|
||||||
|
/// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to
|
||||||
|
/// `id`.
|
||||||
|
///
|
||||||
|
/// Pass `AllowUnstable::Yes` to `allow_unstable` to force an unstable item to be allowed. Deprecation warnings will be emitted normally.
|
||||||
|
pub fn eval_stability_allow_unstable(
|
||||||
|
self,
|
||||||
|
def_id: DefId,
|
||||||
|
id: Option<HirId>,
|
||||||
|
span: Span,
|
||||||
|
method_span: Option<Span>,
|
||||||
|
allow_unstable: AllowUnstable,
|
||||||
) -> EvalResult {
|
) -> EvalResult {
|
||||||
// Deprecated attributes apply in-crate and cross-crate.
|
// Deprecated attributes apply in-crate and cross-crate.
|
||||||
if let Some(id) = id {
|
if let Some(id) = id {
|
||||||
|
@ -419,6 +448,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if matches!(allow_unstable, AllowUnstable::Yes) {
|
||||||
|
return EvalResult::Allow;
|
||||||
|
}
|
||||||
|
|
||||||
let suggestion = suggestion_for_allocator_api(self, def_id, span, feature);
|
let suggestion = suggestion_for_allocator_api(self, def_id, span, feature);
|
||||||
EvalResult::Deny { feature, reason, issue, suggestion, is_soft }
|
EvalResult::Deny { feature, reason, issue, suggestion, is_soft }
|
||||||
}
|
}
|
||||||
|
@ -445,11 +478,38 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
method_span: Option<Span>,
|
method_span: Option<Span>,
|
||||||
) {
|
) {
|
||||||
self.check_optional_stability(def_id, id, span, method_span, |span, def_id| {
|
self.check_stability_allow_unstable(def_id, id, span, method_span, AllowUnstable::No)
|
||||||
// The API could be uncallable for other reasons, for example when a private module
|
}
|
||||||
// was referenced.
|
|
||||||
self.sess.delay_span_bug(span, &format!("encountered unmarked API: {:?}", def_id));
|
/// Checks if an item is stable or error out.
|
||||||
})
|
///
|
||||||
|
/// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not
|
||||||
|
/// exist, emits an error.
|
||||||
|
///
|
||||||
|
/// This function will also check if the item is deprecated.
|
||||||
|
/// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted.
|
||||||
|
///
|
||||||
|
/// Pass `AllowUnstable::Yes` to `allow_unstable` to force an unstable item to be allowed. Deprecation warnings will be emitted normally.
|
||||||
|
pub fn check_stability_allow_unstable(
|
||||||
|
self,
|
||||||
|
def_id: DefId,
|
||||||
|
id: Option<HirId>,
|
||||||
|
span: Span,
|
||||||
|
method_span: Option<Span>,
|
||||||
|
allow_unstable: AllowUnstable,
|
||||||
|
) {
|
||||||
|
self.check_optional_stability(
|
||||||
|
def_id,
|
||||||
|
id,
|
||||||
|
span,
|
||||||
|
method_span,
|
||||||
|
allow_unstable,
|
||||||
|
|span, def_id| {
|
||||||
|
// The API could be uncallable for other reasons, for example when a private module
|
||||||
|
// was referenced.
|
||||||
|
self.sess.delay_span_bug(span, &format!("encountered unmarked API: {:?}", def_id));
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `check_stability`, except that we permit items to have custom behaviour for
|
/// Like `check_stability`, except that we permit items to have custom behaviour for
|
||||||
|
@ -462,6 +522,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
id: Option<HirId>,
|
id: Option<HirId>,
|
||||||
span: Span,
|
span: Span,
|
||||||
method_span: Option<Span>,
|
method_span: Option<Span>,
|
||||||
|
allow_unstable: AllowUnstable,
|
||||||
unmarked: impl FnOnce(Span, DefId),
|
unmarked: impl FnOnce(Span, DefId),
|
||||||
) {
|
) {
|
||||||
let soft_handler = |lint, span, msg: &_| {
|
let soft_handler = |lint, span, msg: &_| {
|
||||||
|
@ -469,7 +530,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
lint.build(msg).emit();
|
lint.build(msg).emit();
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
match self.eval_stability(def_id, id, span, method_span) {
|
match self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable) {
|
||||||
EvalResult::Allow => {}
|
EvalResult::Allow => {}
|
||||||
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable(
|
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable(
|
||||||
self.sess,
|
self.sess,
|
||||||
|
|
|
@ -336,7 +336,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||||
WorkProductId::from_cgu_name(self.name().as_str())
|
WorkProductId::from_cgu_name(self.name().as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn work_product(&self, tcx: TyCtxt<'_>) -> WorkProduct {
|
pub fn previous_work_product(&self, tcx: TyCtxt<'_>) -> WorkProduct {
|
||||||
let work_product_id = self.work_product_id();
|
let work_product_id = self.work_product_id();
|
||||||
tcx.dep_graph
|
tcx.dep_graph
|
||||||
.previous_work_product(&work_product_id)
|
.previous_work_product(&work_product_id)
|
||||||
|
|
|
@ -9,10 +9,10 @@ use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||||
use rustc_hir::hir_id::CRATE_HIR_ID;
|
use rustc_hir::hir_id::CRATE_HIR_ID;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
|
use rustc_hir::{FieldDef, Generics, HirId, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::middle::privacy::AccessLevels;
|
use rustc_middle::middle::privacy::AccessLevels;
|
||||||
use rustc_middle::middle::stability::{DeprecationEntry, Index};
|
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
|
||||||
use rustc_middle::ty::{self, query::Providers, TyCtxt};
|
use rustc_middle::ty::{self, query::Providers, TyCtxt};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
|
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
|
||||||
|
@ -807,12 +807,46 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
||||||
fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
|
fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
|
||||||
if let Some(def_id) = path.res.opt_def_id() {
|
if let Some(def_id) = path.res.opt_def_id() {
|
||||||
let method_span = path.segments.last().map(|s| s.ident.span);
|
let method_span = path.segments.last().map(|s| s.ident.span);
|
||||||
self.tcx.check_stability(def_id, Some(id), path.span, method_span)
|
self.tcx.check_stability_allow_unstable(
|
||||||
|
def_id,
|
||||||
|
Some(id),
|
||||||
|
path.span,
|
||||||
|
method_span,
|
||||||
|
if is_unstable_reexport(self.tcx, id) {
|
||||||
|
AllowUnstable::Yes
|
||||||
|
} else {
|
||||||
|
AllowUnstable::No
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
intravisit::walk_path(self, path)
|
intravisit::walk_path(self, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether a path is a `use` item that has been marked as unstable.
|
||||||
|
///
|
||||||
|
/// See issue #94972 for details on why this is a special case
|
||||||
|
fn is_unstable_reexport<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId) -> bool {
|
||||||
|
// Get the LocalDefId so we can lookup the item to check the kind.
|
||||||
|
let Some(def_id) = tcx.hir().opt_local_def_id(id) else { return false; };
|
||||||
|
|
||||||
|
let Some(stab) = tcx.stability().local_stability(def_id) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if stab.level.is_stable() {
|
||||||
|
// The re-export is not marked as unstable, don't override
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a path that isn't a use, we don't need to do anything special
|
||||||
|
if !matches!(tcx.hir().item(hir::ItemId { def_id }).kind, ItemKind::Use(..)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
struct CheckTraitImplStable<'tcx> {
|
struct CheckTraitImplStable<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
fully_stable: bool,
|
fully_stable: bool,
|
||||||
|
|
|
@ -164,7 +164,6 @@ pub struct WorkProductId {
|
||||||
impl WorkProductId {
|
impl WorkProductId {
|
||||||
pub fn from_cgu_name(cgu_name: &str) -> WorkProductId {
|
pub fn from_cgu_name(cgu_name: &str) -> WorkProductId {
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
cgu_name.len().hash(&mut hasher);
|
|
||||||
cgu_name.hash(&mut hasher);
|
cgu_name.hash(&mut hasher);
|
||||||
WorkProductId { hash: hasher.finish() }
|
WorkProductId { hash: hasher.finish() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -887,7 +887,7 @@ impl<K: DepKind> DepGraph<K> {
|
||||||
pub struct WorkProduct {
|
pub struct WorkProduct {
|
||||||
pub cgu_name: String,
|
pub cgu_name: String,
|
||||||
/// Saved file associated with this CGU.
|
/// Saved file associated with this CGU.
|
||||||
pub saved_file: Option<String>,
|
pub saved_file: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index type for `DepNodeData`'s edges.
|
// Index type for `DepNodeData`'s edges.
|
||||||
|
|
|
@ -24,6 +24,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::{walk_generics, Visitor as _};
|
use rustc_hir::intravisit::{walk_generics, Visitor as _};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{GenericArg, GenericArgs};
|
use rustc_hir::{GenericArg, GenericArgs};
|
||||||
|
use rustc_middle::middle::stability::AllowUnstable;
|
||||||
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
|
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
|
||||||
use rustc_middle::ty::GenericParamDefKind;
|
use rustc_middle::ty::GenericParamDefKind;
|
||||||
use rustc_middle::ty::{self, Const, DefIdTree, EarlyBinder, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, Const, DefIdTree, EarlyBinder, Ty, TyCtxt, TypeFoldable};
|
||||||
|
@ -426,6 +427,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
Some(arg.id()),
|
Some(arg.id()),
|
||||||
arg.span(),
|
arg.span(),
|
||||||
None,
|
None,
|
||||||
|
AllowUnstable::No,
|
||||||
|_, _| {
|
|_, _| {
|
||||||
// Default generic parameters may not be marked
|
// Default generic parameters may not be marked
|
||||||
// with stability attributes, i.e. when the
|
// with stability attributes, i.e. when the
|
||||||
|
|
|
@ -730,6 +730,7 @@ fn signal_string(signal: i32) -> &'static str {
|
||||||
libc::SIGVTALRM => " (SIGVTALRM)",
|
libc::SIGVTALRM => " (SIGVTALRM)",
|
||||||
libc::SIGPROF => " (SIGPROF)",
|
libc::SIGPROF => " (SIGPROF)",
|
||||||
libc::SIGWINCH => " (SIGWINCH)",
|
libc::SIGWINCH => " (SIGWINCH)",
|
||||||
|
#[cfg(not(target_os = "haiku"))]
|
||||||
libc::SIGIO => " (SIGIO)",
|
libc::SIGIO => " (SIGIO)",
|
||||||
libc::SIGSYS => " (SIGSYS)",
|
libc::SIGSYS => " (SIGSYS)",
|
||||||
// For information on Linux signals, run `man 7 signal`
|
// For information on Linux signals, run `man 7 signal`
|
||||||
|
|
30
src/test/ui/stability-attribute/allow-unstable-reexport.rs
Normal file
30
src/test/ui/stability-attribute/allow-unstable-reexport.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Allow an unstable re-export without requiring a feature gate.
|
||||||
|
// #94972
|
||||||
|
|
||||||
|
// aux-build:lint-stability.rs
|
||||||
|
// aux-build:lint-stability-reexport.rs
|
||||||
|
#![feature(staged_api)]
|
||||||
|
#![stable(feature = "lint_stability", since = "1.0.0")]
|
||||||
|
|
||||||
|
extern crate lint_stability;
|
||||||
|
extern crate lint_stability_reexport;
|
||||||
|
|
||||||
|
#[unstable(feature = "unstable_test_feature", issue = "none")]
|
||||||
|
pub use lint_stability::unstable;
|
||||||
|
|
||||||
|
// We want to confirm that using a re-export through another crate behaves
|
||||||
|
// the same way as using an item directly
|
||||||
|
#[unstable(feature = "unstable_test_feature", issue = "none")]
|
||||||
|
pub use lint_stability_reexport::unstable_text;
|
||||||
|
|
||||||
|
// Ensure items which aren't marked as unstable can't re-export unstable items
|
||||||
|
#[stable(feature = "lint_stability", since = "1.0.0")]
|
||||||
|
pub use lint_stability::unstable as unstable2;
|
||||||
|
//~^ ERROR use of unstable library feature 'unstable_test_feature'
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Since we didn't enable the feature in this crate, we still can't
|
||||||
|
// use these items, even though they're in scope from the `use`s which are now allowed.
|
||||||
|
unstable(); //~ ERROR use of unstable library feature 'unstable_test_feature'
|
||||||
|
unstable_text(); //~ ERROR use of unstable library feature 'unstable_test_feature'
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
error[E0658]: use of unstable library feature 'unstable_test_feature'
|
||||||
|
--> $DIR/allow-unstable-reexport.rs:22:9
|
||||||
|
|
|
||||||
|
LL | pub use lint_stability::unstable as unstable2;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: use of unstable library feature 'unstable_test_feature'
|
||||||
|
--> $DIR/allow-unstable-reexport.rs:28:5
|
||||||
|
|
|
||||||
|
LL | unstable();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: use of unstable library feature 'unstable_test_feature': text
|
||||||
|
--> $DIR/allow-unstable-reexport.rs:29:5
|
||||||
|
|
|
||||||
|
LL | unstable_text();
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -0,0 +1,9 @@
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(staged_api)]
|
||||||
|
#![stable(feature = "lint_stability", since = "1.0.0")]
|
||||||
|
|
||||||
|
extern crate lint_stability;
|
||||||
|
|
||||||
|
// Re-exporting without enabling the feature "unstable_test_feature" in this crate
|
||||||
|
#[unstable(feature = "unstable_test_feature", issue = "none")]
|
||||||
|
pub use lint_stability::unstable_text;
|
28
src/test/ui/unsized/issue-97732.rs
Normal file
28
src/test/ui/unsized/issue-97732.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(coerce_unsized)]
|
||||||
|
|
||||||
|
// Ensure that unsizing structs that contain ZSTs at non-zero offsets don't ICE
|
||||||
|
|
||||||
|
use std::ops::CoerceUnsized;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct BoxWithZstTail<T: ?Sized>(Box<T>, ());
|
||||||
|
|
||||||
|
impl<S: ?Sized, T: ?Sized> CoerceUnsized<BoxWithZstTail<T>> for BoxWithZstTail<S> where
|
||||||
|
Box<S>: CoerceUnsized<Box<T>>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noop_dyn_upcast_with_zst_tail(
|
||||||
|
b: BoxWithZstTail<dyn ToString + Send>,
|
||||||
|
) -> BoxWithZstTail<dyn ToString> {
|
||||||
|
b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let original = "foo";
|
||||||
|
let boxed = BoxWithZstTail(Box::new(original) as Box<dyn ToString + Send>, ());
|
||||||
|
let noop_upcasted = noop_dyn_upcast_with_zst_tail(boxed);
|
||||||
|
assert_eq!(original, noop_upcasted.0.to_string());
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue