commit
1812f60f65
726 changed files with 4748 additions and 4026 deletions
49
.github/ISSUE_TEMPLATE/ice.md
vendored
Normal file
49
.github/ISSUE_TEMPLATE/ice.md
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
name: Internal Compiler Error
|
||||
about: Create a report for an internal compiler error in rustc.
|
||||
labels: C-bug, I-ICE, T-compiler
|
||||
---
|
||||
<!--
|
||||
Thank you for finding an Internal Compiler Error! 🧊 If possible, try to provide
|
||||
a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for
|
||||
how to create smaller examples.
|
||||
http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
|
||||
-->
|
||||
|
||||
### Code
|
||||
|
||||
```Rust
|
||||
<code>
|
||||
```
|
||||
|
||||
|
||||
### Meta
|
||||
<!--
|
||||
If you're using the stable version of the compiler, you should also check if the
|
||||
bug also exists in the beta or nightly versions.
|
||||
-->
|
||||
|
||||
`rustc --version --verbose`:
|
||||
```
|
||||
<version>
|
||||
```
|
||||
|
||||
### Error output
|
||||
|
||||
```
|
||||
<output>
|
||||
```
|
||||
|
||||
<!--
|
||||
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
|
||||
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
|
||||
-->
|
||||
<details><summary><strong>Backtrace</strong></summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
<backtrace>
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
6
.github/ISSUE_TEMPLATE/ice.yaml
vendored
6
.github/ISSUE_TEMPLATE/ice.yaml
vendored
|
|
@ -1,5 +1,5 @@
|
|||
name: Internal Compiler Error
|
||||
description: Create a report for an internal compiler error in `rustc`
|
||||
name: Internal Compiler Error (Structured form)
|
||||
description: For now, you'll want to use the other ICE template, as GitHub forms have strict limits on the size of fields so backtraces cannot be pasted directly.
|
||||
labels: ["C-bug", "I-ICE", "T-compiler"]
|
||||
title: "[ICE]: "
|
||||
body:
|
||||
|
|
@ -79,4 +79,4 @@ body:
|
|||
label: Anything else?
|
||||
description: If you have more details you want to give us to reproduce this issue, please add it here
|
||||
validations:
|
||||
required: false
|
||||
required: false
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cargo"
|
||||
version = "0.69.0"
|
||||
version = "0.70.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
|
|
|
|||
|
|
@ -1456,6 +1456,8 @@ pub enum PointerKind {
|
|||
UniqueOwned,
|
||||
}
|
||||
|
||||
/// Note that this information is advisory only, and backends are free to ignore it.
|
||||
/// It can only be used to encode potential optimizations, but no critical information.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PointeeInfo {
|
||||
pub size: Size,
|
||||
|
|
|
|||
|
|
@ -58,23 +58,24 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
|
|||
// In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are
|
||||
// present. However, we first need to strip the empty lines so they don't get in the middle
|
||||
// when we try to compute the "horizontal trim".
|
||||
let lines = if kind == CommentKind::Block {
|
||||
// Whatever happens, we skip the first line.
|
||||
let mut i = lines
|
||||
.get(0)
|
||||
.map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
|
||||
.unwrap_or(0);
|
||||
let mut j = lines.len();
|
||||
let lines = match kind {
|
||||
CommentKind::Block => {
|
||||
// Whatever happens, we skip the first line.
|
||||
let mut i = lines
|
||||
.get(0)
|
||||
.map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
|
||||
.unwrap_or(0);
|
||||
let mut j = lines.len();
|
||||
|
||||
while i < j && lines[i].trim().is_empty() {
|
||||
i += 1;
|
||||
while i < j && lines[i].trim().is_empty() {
|
||||
i += 1;
|
||||
}
|
||||
while j > i && lines[j - 1].trim().is_empty() {
|
||||
j -= 1;
|
||||
}
|
||||
&lines[i..j]
|
||||
}
|
||||
while j > i && lines[j - 1].trim().is_empty() {
|
||||
j -= 1;
|
||||
}
|
||||
&lines[i..j]
|
||||
} else {
|
||||
lines
|
||||
CommentKind::Line => lines,
|
||||
};
|
||||
|
||||
for line in lines {
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ pub fn print_crate<'a>(
|
|||
|
||||
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
|
||||
// root, so this is not needed, and actually breaks things.
|
||||
if edition == Edition::Edition2015 {
|
||||
if edition.rust_2015() {
|
||||
// `#![no_std]`
|
||||
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
|
||||
s.print_attribute(&fake_attr);
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
err.span_help(source_info.span, "try removing `&mut` here");
|
||||
}
|
||||
} else if decl.mutability == Mutability::Not {
|
||||
} else if decl.mutability.is_not() {
|
||||
if matches!(
|
||||
decl.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
|
|
|
|||
|
|
@ -187,6 +187,12 @@ impl Display for RegionName {
|
|||
}
|
||||
}
|
||||
|
||||
impl rustc_errors::IntoDiagnosticArg for RegionName {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
self.to_string().into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
|
||||
self.body.source.def_id().expect_local()
|
||||
|
|
|
|||
|
|
@ -369,6 +369,8 @@ pub(super) fn dump_mir_results<'tcx>(
|
|||
};
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(super) fn dump_annotation<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_errors::{IntoDiagnosticArg, MultiSpan};
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{GenericArg, Ty};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -128,18 +128,6 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for &RegionName {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
format!("{}", self).into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for RegionName {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
format!("{}", self).into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum RequireStaticErr {
|
||||
#[note(borrowck_used_impl_require_static)]
|
||||
|
|
|
|||
|
|
@ -181,9 +181,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
user_ty: ty::UserType<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
// FIXME: Ideally MIR types are normalized, but this is not always true.
|
||||
let mir_ty = self.normalize(mir_ty, Locations::All(span));
|
||||
|
||||
self.fully_perform_op(
|
||||
Locations::All(span),
|
||||
ConstraintCategory::Boring,
|
||||
|
|
@ -217,7 +214,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
// FIXME: Ideally MIR types are normalized, but this is not always true.
|
||||
let mir_ty = self.normalize(mir_ty, Locations::All(span));
|
||||
|
||||
let cause = ObligationCause::dummy_with_span(span);
|
||||
let param_env = self.param_env;
|
||||
let op = |infcx: &'_ _| {
|
||||
|
|
|
|||
|
|
@ -2028,7 +2028,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
if ty_to_mut == Mutability::Mut && ty_mut == Mutability::Not {
|
||||
if ty_to_mut.is_mut() && ty_mut.is_not() {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ unsafe impl Sync for GccContext {}
|
|||
impl WriteBackendMethods for GccCodegenBackend {
|
||||
type Module = GccContext;
|
||||
type TargetMachine = ();
|
||||
type TargetMachineError = ();
|
||||
type ModuleBuffer = ModuleBuffer;
|
||||
type ThinData = ();
|
||||
type ThinBuffer = ThinBuffer;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
|
||||
use crate::errors::DynamicLinkingWithLTO;
|
||||
use crate::errors::{
|
||||
DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib,
|
||||
};
|
||||
use crate::llvm::{self, build_string};
|
||||
use crate::{LlvmCodegenBackend, ModuleLlvm};
|
||||
use object::read::archive::ArchiveFile;
|
||||
|
|
@ -77,15 +79,12 @@ fn prepare_lto(
|
|||
// Make sure we actually can run LTO
|
||||
for crate_type in cgcx.crate_types.iter() {
|
||||
if !crate_type_allows_lto(*crate_type) {
|
||||
let e = diag_handler.fatal(
|
||||
"lto can only be run for executables, cdylibs and \
|
||||
static library outputs",
|
||||
);
|
||||
return Err(e);
|
||||
diag_handler.emit_err(LtoDisallowed);
|
||||
return Err(FatalError);
|
||||
} else if *crate_type == CrateType::Dylib {
|
||||
if !cgcx.opts.unstable_opts.dylib_lto {
|
||||
return Err(diag_handler
|
||||
.fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`"));
|
||||
diag_handler.emit_err(LtoDylib);
|
||||
return Err(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,7 +126,10 @@ fn prepare_lto(
|
|||
let module = SerializedModule::FromRlib(data.to_vec());
|
||||
upstream_modules.push((module, CString::new(name).unwrap()));
|
||||
}
|
||||
Err(msg) => return Err(diag_handler.fatal(&msg)),
|
||||
Err(e) => {
|
||||
diag_handler.emit_err(e);
|
||||
return Err(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -140,7 +142,7 @@ fn prepare_lto(
|
|||
Ok((symbols_below_threshold, upstream_modules))
|
||||
}
|
||||
|
||||
fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> {
|
||||
fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], LtoBitcodeFromRlib> {
|
||||
let mut len = 0;
|
||||
let data =
|
||||
unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) };
|
||||
|
|
@ -155,8 +157,9 @@ fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> {
|
|||
Ok(bc)
|
||||
} else {
|
||||
assert!(len == 0);
|
||||
let msg = llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string());
|
||||
Err(format!("failed to get bitcode from object file for LTO ({})", msg))
|
||||
Err(LtoBitcodeFromRlib {
|
||||
llvm_err: llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -328,10 +331,9 @@ fn fat_lto(
|
|||
});
|
||||
info!("linking {:?}", name);
|
||||
let data = bc_decoded.data();
|
||||
linker.add(data).map_err(|()| {
|
||||
let msg = format!("failed to load bitcode of module {:?}", name);
|
||||
write::llvm_err(diag_handler, &msg)
|
||||
})?;
|
||||
linker
|
||||
.add(data)
|
||||
.map_err(|()| write::llvm_err(diag_handler, LlvmError::LoadBitcode { name }))?;
|
||||
serialized_bitcode.push(bc_decoded);
|
||||
}
|
||||
drop(linker);
|
||||
|
|
@ -489,7 +491,7 @@ fn thin_lto(
|
|||
symbols_below_threshold.as_ptr(),
|
||||
symbols_below_threshold.len() as u32,
|
||||
)
|
||||
.ok_or_else(|| write::llvm_err(diag_handler, "failed to prepare thin LTO context"))?;
|
||||
.ok_or_else(|| write::llvm_err(diag_handler, LlvmError::PrepareThinLtoContext))?;
|
||||
|
||||
let data = ThinData(data);
|
||||
|
||||
|
|
@ -562,8 +564,7 @@ fn thin_lto(
|
|||
// session, overwriting the previous serialized data (if any).
|
||||
if let Some(path) = key_map_path {
|
||||
if let Err(err) = curr_key_map.save_to_file(&path) {
|
||||
let msg = format!("Error while writing ThinLTO key data: {}", err);
|
||||
return Err(write::llvm_err(diag_handler, &msg));
|
||||
return Err(write::llvm_err(diag_handler, LlvmError::WriteThinLtoKey { err }));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -689,8 +690,7 @@ pub unsafe fn optimize_thin_module(
|
|||
|
||||
let module_name = &thin_module.shared.module_names[thin_module.idx];
|
||||
let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap());
|
||||
let tm =
|
||||
(cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, &e))?;
|
||||
let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, e))?;
|
||||
|
||||
// Right now the implementation we've got only works over serialized
|
||||
// modules, so we create a fresh new LLVM context and parse the module
|
||||
|
|
@ -717,8 +717,7 @@ pub unsafe fn optimize_thin_module(
|
|||
let mut cu2 = ptr::null_mut();
|
||||
llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
|
||||
if !cu2.is_null() {
|
||||
let msg = "multiple source DICompileUnits found";
|
||||
return Err(write::llvm_err(&diag_handler, msg));
|
||||
return Err(write::llvm_err(&diag_handler, LlvmError::MultipleSourceDiCompileUnit));
|
||||
}
|
||||
|
||||
// Up next comes the per-module local analyses that we do for Thin LTO.
|
||||
|
|
@ -733,8 +732,7 @@ pub unsafe fn optimize_thin_module(
|
|||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) {
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg));
|
||||
return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
|
||||
}
|
||||
|
|
@ -744,8 +742,7 @@ pub unsafe fn optimize_thin_module(
|
|||
.prof
|
||||
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg));
|
||||
return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
|
||||
}
|
||||
|
|
@ -755,8 +752,7 @@ pub unsafe fn optimize_thin_module(
|
|||
.prof
|
||||
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg));
|
||||
return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
|
||||
}
|
||||
|
|
@ -765,8 +761,7 @@ pub unsafe fn optimize_thin_module(
|
|||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) {
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg));
|
||||
return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
|
||||
}
|
||||
|
|
@ -886,11 +881,7 @@ pub fn parse_module<'a>(
|
|||
diag_handler: &Handler,
|
||||
) -> Result<&'a llvm::Module, FatalError> {
|
||||
unsafe {
|
||||
llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()).ok_or_else(
|
||||
|| {
|
||||
let msg = "failed to parse bitcode for LTO module";
|
||||
write::llvm_err(diag_handler, msg)
|
||||
},
|
||||
)
|
||||
llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr())
|
||||
.ok_or_else(|| write::llvm_err(diag_handler, LlvmError::ParseBitcode))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ use crate::back::profiling::{
|
|||
use crate::base;
|
||||
use crate::common;
|
||||
use crate::consts;
|
||||
use crate::errors::{
|
||||
CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, WithLlvmError, WriteBytecode,
|
||||
};
|
||||
use crate::llvm::{self, DiagnosticInfo, PassManager};
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
|
|
@ -37,10 +40,10 @@ use std::slice;
|
|||
use std::str;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
|
||||
pub fn llvm_err<'a>(handler: &rustc_errors::Handler, err: LlvmError<'a>) -> FatalError {
|
||||
match llvm::last_error() {
|
||||
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
|
||||
None => handler.fatal(msg),
|
||||
Some(llvm_err) => handler.emit_almost_fatal(WithLlvmError(err, llvm_err)),
|
||||
None => handler.emit_almost_fatal(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,10 +88,9 @@ pub fn write_output_file<'ll>(
|
|||
}
|
||||
}
|
||||
|
||||
result.into_result().map_err(|()| {
|
||||
let msg = format!("could not write output to {}", output.display());
|
||||
llvm_err(handler, &msg)
|
||||
})
|
||||
result
|
||||
.into_result()
|
||||
.map_err(|()| llvm_err(handler, LlvmError::WriteOutput { path: output }))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +100,7 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm:
|
|||
// system/tcx is set up.
|
||||
let features = llvm_util::global_llvm_features(sess, false);
|
||||
target_machine_factory(sess, config::OptLevel::No, &features)(config)
|
||||
.unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
|
||||
.unwrap_or_else(|err| llvm_err(sess.diagnostic(), err).raise())
|
||||
}
|
||||
|
||||
pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine {
|
||||
|
|
@ -117,7 +119,7 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut ll
|
|||
tcx.backend_optimization_level(()),
|
||||
tcx.global_backend_features(()),
|
||||
)(config)
|
||||
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
|
||||
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), err).raise())
|
||||
}
|
||||
|
||||
pub fn to_llvm_opt_settings(
|
||||
|
|
@ -240,9 +242,7 @@ pub fn target_machine_factory(
|
|||
)
|
||||
};
|
||||
|
||||
tm.ok_or_else(|| {
|
||||
format!("Could not create LLVM TargetMachine for triple: {}", triple.to_str().unwrap())
|
||||
})
|
||||
tm.ok_or_else(|| LlvmError::CreateTargetMachine { triple: triple.clone() })
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -355,25 +355,28 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
|
|||
};
|
||||
|
||||
if enabled {
|
||||
diag_handler.note_without_error(&format!(
|
||||
"{}:{}:{}: {}: {}",
|
||||
opt.filename, opt.line, opt.column, opt.pass_name, opt.message,
|
||||
));
|
||||
diag_handler.emit_note(FromLlvmOptimizationDiag {
|
||||
filename: &opt.filename,
|
||||
line: opt.line,
|
||||
column: opt.column,
|
||||
pass_name: &opt.pass_name,
|
||||
message: &opt.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
|
||||
let msg = llvm::build_string(|s| {
|
||||
let message = llvm::build_string(|s| {
|
||||
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
|
||||
})
|
||||
.expect("non-UTF8 diagnostic");
|
||||
diag_handler.warn(&msg);
|
||||
diag_handler.emit_warning(FromLlvmDiag { message });
|
||||
}
|
||||
llvm::diagnostic::Unsupported(diagnostic_ref) => {
|
||||
let msg = llvm::build_string(|s| {
|
||||
let message = llvm::build_string(|s| {
|
||||
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
|
||||
})
|
||||
.expect("non-UTF8 diagnostic");
|
||||
diag_handler.err(&msg);
|
||||
diag_handler.emit_err(FromLlvmDiag { message });
|
||||
}
|
||||
llvm::diagnostic::UnknownDiagnostic(..) => {}
|
||||
}
|
||||
|
|
@ -494,7 +497,7 @@ pub(crate) unsafe fn llvm_optimize(
|
|||
llvm_plugins.as_ptr().cast(),
|
||||
llvm_plugins.len(),
|
||||
);
|
||||
result.into_result().map_err(|()| llvm_err(diag_handler, "failed to run LLVM passes"))
|
||||
result.into_result().map_err(|()| llvm_err(diag_handler, LlvmError::RunLlvmPasses))
|
||||
}
|
||||
|
||||
// Unsafe due to LLVM calls.
|
||||
|
|
@ -547,8 +550,7 @@ pub(crate) fn link(
|
|||
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", &*module.name);
|
||||
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
|
||||
linker.add(buffer.data()).map_err(|()| {
|
||||
let msg = format!("failed to serialize module {:?}", module.name);
|
||||
llvm_err(diag_handler, &msg)
|
||||
llvm_err(diag_handler, LlvmError::SerializeModule { name: &module.name })
|
||||
})?;
|
||||
}
|
||||
drop(linker);
|
||||
|
|
@ -626,9 +628,8 @@ pub(crate) unsafe fn codegen(
|
|||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name);
|
||||
if let Err(e) = fs::write(&bc_out, data) {
|
||||
let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e);
|
||||
diag_handler.err(&msg);
|
||||
if let Err(err) = fs::write(&bc_out, data) {
|
||||
diag_handler.emit_err(WriteBytecode { path: &bc_out, err });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -678,10 +679,9 @@ pub(crate) unsafe fn codegen(
|
|||
record_artifact_size(&cgcx.prof, "llvm_ir", &out);
|
||||
}
|
||||
|
||||
result.into_result().map_err(|()| {
|
||||
let msg = format!("failed to write LLVM IR to {}", out.display());
|
||||
llvm_err(diag_handler, &msg)
|
||||
})?;
|
||||
result
|
||||
.into_result()
|
||||
.map_err(|()| llvm_err(diag_handler, LlvmError::WriteIr { path: &out }))?;
|
||||
}
|
||||
|
||||
if config.emit_asm {
|
||||
|
|
@ -749,8 +749,8 @@ pub(crate) unsafe fn codegen(
|
|||
|
||||
EmitObj::Bitcode => {
|
||||
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
|
||||
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
|
||||
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
|
||||
if let Err(err) = link_or_copy(&bc_out, &obj_out) {
|
||||
diag_handler.emit_err(CopyBitcode { err });
|
||||
}
|
||||
|
||||
if !config.emit_bc {
|
||||
|
|
|
|||
|
|
@ -150,17 +150,14 @@ pub unsafe fn create_module<'ll>(
|
|||
target_data_layout =
|
||||
"e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
||||
.to_string();
|
||||
}
|
||||
if sess.target.arch == "wasm32" {
|
||||
} else if sess.target.arch == "wasm32" {
|
||||
target_data_layout = target_data_layout.replace("-p10:8:8-p20:8:8", "");
|
||||
}
|
||||
}
|
||||
if llvm_version < (16, 0, 0) {
|
||||
if sess.target.arch == "s390x" {
|
||||
target_data_layout = target_data_layout.replace("-v128:64", "");
|
||||
}
|
||||
|
||||
if sess.target.arch == "riscv64" {
|
||||
} else if sess.target.arch == "riscv64" {
|
||||
target_data_layout = target_data_layout.replace("-n32:64-", "-n64-");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
use std::borrow::Cow;
|
||||
use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
|
||||
use rustc_errors::fluent;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_errors::Handler;
|
||||
use rustc_errors::IntoDiagnostic;
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_errors::{
|
||||
fluent, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, Handler, IntoDiagnostic,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
|
@ -81,10 +82,18 @@ pub(crate) struct DlltoolFailImportLibrary<'a> {
|
|||
#[note]
|
||||
pub(crate) struct DynamicLinkingWithLTO;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)]
|
||||
pub(crate) struct FailParsingTargetMachineConfigToTargetMachine {
|
||||
pub error: String,
|
||||
pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
|
||||
|
||||
impl<EM: EmissionGuarantee> IntoDiagnostic<'_, EM> for ParseTargetMachineConfig<'_> {
|
||||
fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> {
|
||||
let diag: DiagnosticBuilder<'_, EM> = self.0.into_diagnostic(sess);
|
||||
let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message");
|
||||
let message = sess.eagerly_translate_to_string(message.clone(), diag.args());
|
||||
|
||||
let mut diag = sess.struct_diagnostic(fluent::codegen_llvm_parse_target_machine_config);
|
||||
diag.set_arg("error", message);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct TargetFeatureDisableOrEnable<'a> {
|
||||
|
|
@ -110,3 +119,99 @@ impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
|
|||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_lto_disallowed)]
|
||||
pub(crate) struct LtoDisallowed;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_lto_dylib)]
|
||||
pub(crate) struct LtoDylib;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_lto_bitcode_from_rlib)]
|
||||
pub(crate) struct LtoBitcodeFromRlib {
|
||||
pub llvm_err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub enum LlvmError<'a> {
|
||||
#[diag(codegen_llvm_write_output)]
|
||||
WriteOutput { path: &'a Path },
|
||||
#[diag(codegen_llvm_target_machine)]
|
||||
CreateTargetMachine { triple: SmallCStr },
|
||||
#[diag(codegen_llvm_run_passes)]
|
||||
RunLlvmPasses,
|
||||
#[diag(codegen_llvm_serialize_module)]
|
||||
SerializeModule { name: &'a str },
|
||||
#[diag(codegen_llvm_write_ir)]
|
||||
WriteIr { path: &'a Path },
|
||||
#[diag(codegen_llvm_prepare_thin_lto_context)]
|
||||
PrepareThinLtoContext,
|
||||
#[diag(codegen_llvm_load_bitcode)]
|
||||
LoadBitcode { name: CString },
|
||||
#[diag(codegen_llvm_write_thinlto_key)]
|
||||
WriteThinLtoKey { err: std::io::Error },
|
||||
#[diag(codegen_llvm_multiple_source_dicompileunit)]
|
||||
MultipleSourceDiCompileUnit,
|
||||
#[diag(codegen_llvm_prepare_thin_lto_module)]
|
||||
PrepareThinLtoModule,
|
||||
#[diag(codegen_llvm_parse_bitcode)]
|
||||
ParseBitcode,
|
||||
}
|
||||
|
||||
pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String);
|
||||
|
||||
impl<EM: EmissionGuarantee> IntoDiagnostic<'_, EM> for WithLlvmError<'_> {
|
||||
fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> {
|
||||
use LlvmError::*;
|
||||
let msg_with_llvm_err = match &self.0 {
|
||||
WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err,
|
||||
CreateTargetMachine { .. } => fluent::codegen_llvm_target_machine_with_llvm_err,
|
||||
RunLlvmPasses => fluent::codegen_llvm_run_passes_with_llvm_err,
|
||||
SerializeModule { .. } => fluent::codegen_llvm_serialize_module_with_llvm_err,
|
||||
WriteIr { .. } => fluent::codegen_llvm_write_ir_with_llvm_err,
|
||||
PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err,
|
||||
LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err,
|
||||
WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err,
|
||||
MultipleSourceDiCompileUnit => {
|
||||
fluent::codegen_llvm_multiple_source_dicompileunit_with_llvm_err
|
||||
}
|
||||
PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
|
||||
ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
|
||||
};
|
||||
let mut diag = self.0.into_diagnostic(sess);
|
||||
diag.set_primary_message(msg_with_llvm_err);
|
||||
diag.set_arg("llvm_err", self.1);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_from_llvm_optimization_diag)]
|
||||
pub(crate) struct FromLlvmOptimizationDiag<'a> {
|
||||
pub filename: &'a str,
|
||||
pub line: std::ffi::c_uint,
|
||||
pub column: std::ffi::c_uint,
|
||||
pub pass_name: &'a str,
|
||||
pub message: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_from_llvm_diag)]
|
||||
pub(crate) struct FromLlvmDiag {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_write_bytecode)]
|
||||
pub(crate) struct WriteBytecode<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_copy_bitcode)]
|
||||
pub(crate) struct CopyBitcode {
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(once_cell)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
|
|
@ -22,7 +23,7 @@ extern crate tracing;
|
|||
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
|
||||
use errors::FailParsingTargetMachineConfigToTargetMachine;
|
||||
use errors::ParseTargetMachineConfig;
|
||||
pub use llvm_util::target_features;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||
|
|
@ -169,6 +170,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
type Module = ModuleLlvm;
|
||||
type ModuleBuffer = back::lto::ModuleBuffer;
|
||||
type TargetMachine = &'static mut llvm::TargetMachine;
|
||||
type TargetMachineError = crate::errors::LlvmError<'static>;
|
||||
type ThinData = back::lto::ThinData;
|
||||
type ThinBuffer = back::lto::ThinBuffer;
|
||||
fn print_pass_timings(&self) {
|
||||
|
|
@ -416,8 +418,7 @@ impl ModuleLlvm {
|
|||
let tm = match (cgcx.tm_factory)(tm_factory_config) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e });
|
||||
return Err(FatalError);
|
||||
return Err(handler.emit_almost_fatal(ParseTargetMachineConfig(e)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -305,8 +305,12 @@ impl TargetMachineFactoryConfig {
|
|||
}
|
||||
|
||||
pub type TargetMachineFactoryFn<B> = Arc<
|
||||
dyn Fn(TargetMachineFactoryConfig) -> Result<<B as WriteBackendMethods>::TargetMachine, String>
|
||||
+ Send
|
||||
dyn Fn(
|
||||
TargetMachineFactoryConfig,
|
||||
) -> Result<
|
||||
<B as WriteBackendMethods>::TargetMachine,
|
||||
<B as WriteBackendMethods>::TargetMachineError,
|
||||
> + Send
|
||||
+ Sync,
|
||||
>;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use rustc_middle::dep_graph::WorkProduct;
|
|||
pub trait WriteBackendMethods: 'static + Sized + Clone {
|
||||
type Module: Send + Sync;
|
||||
type TargetMachine;
|
||||
type TargetMachineError;
|
||||
type ModuleBuffer: ModuleBufferMethods;
|
||||
type ThinData: Send + Sync;
|
||||
type ThinBuffer: ThinBufferMethods;
|
||||
|
|
|
|||
|
|
@ -622,10 +622,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
let alloc = alloc.inner();
|
||||
if is_write {
|
||||
// Write access. These are never allowed, but we give a targeted error message.
|
||||
if alloc.mutability == Mutability::Not {
|
||||
Err(err_ub!(WriteToReadOnly(alloc_id)).into())
|
||||
} else {
|
||||
Err(ConstEvalErrKind::ModifiedGlobal.into())
|
||||
match alloc.mutability {
|
||||
Mutability::Not => Err(err_ub!(WriteToReadOnly(alloc_id)).into()),
|
||||
Mutability::Mut => Err(ConstEvalErrKind::ModifiedGlobal.into()),
|
||||
}
|
||||
} else {
|
||||
// Read access. These are usually allowed, with some exceptions.
|
||||
|
|
|
|||
|
|
@ -30,15 +30,15 @@ use super::{
|
|||
use crate::const_eval;
|
||||
|
||||
pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
|
||||
'mir,
|
||||
'tcx,
|
||||
MemoryKind = T,
|
||||
Provenance = AllocId,
|
||||
ExtraFnVal = !,
|
||||
FrameExtra = (),
|
||||
AllocExtra = (),
|
||||
MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
|
||||
>;
|
||||
'mir,
|
||||
'tcx,
|
||||
MemoryKind = T,
|
||||
Provenance = AllocId,
|
||||
ExtraFnVal = !,
|
||||
FrameExtra = (),
|
||||
AllocExtra = (),
|
||||
MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
|
||||
>;
|
||||
|
||||
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
|
||||
/// The ectx from which we intern.
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
.into());
|
||||
};
|
||||
|
||||
if alloc.mutability == Mutability::Not {
|
||||
if alloc.mutability.is_not() {
|
||||
throw_ub_format!("deallocating immutable allocation {alloc_id:?}");
|
||||
}
|
||||
if alloc_kind != kind {
|
||||
|
|
@ -631,7 +631,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
let (_kind, alloc) = self.memory.alloc_map.get_mut(id).unwrap();
|
||||
if alloc.mutability == Mutability::Not {
|
||||
if alloc.mutability.is_not() {
|
||||
throw_ub!(WriteToReadOnly(id))
|
||||
}
|
||||
Ok((alloc, &mut self.machine))
|
||||
|
|
|
|||
|
|
@ -754,7 +754,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
// FIXME(JakobDegen) The validator should check that `self.mir_phase <
|
||||
// DropsLowered`. However, this causes ICEs with generation of drop shims, which
|
||||
// seem to fail to set their `MirPhase` correctly.
|
||||
if *kind == RetagKind::Raw || *kind == RetagKind::TwoPhase {
|
||||
if matches!(kind, RetagKind::Raw | RetagKind::TwoPhase) {
|
||||
self.fail(location, format!("explicit `{:?}` is forbidden", kind));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,10 +95,7 @@ pub trait ForestObligation: Clone + Debug {
|
|||
pub trait ObligationProcessor {
|
||||
type Obligation: ForestObligation;
|
||||
type Error: Debug;
|
||||
type OUT: OutcomeTrait<
|
||||
Obligation = Self::Obligation,
|
||||
Error = Error<Self::Obligation, Self::Error>,
|
||||
>;
|
||||
type OUT: OutcomeTrait<Obligation = Self::Obligation, Error = Error<Self::Obligation, Self::Error>>;
|
||||
|
||||
fn needs_process_obligation(&self, obligation: &Self::Obligation) -> bool;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ use rustc_span::source_map::{FileLoader, FileName};
|
|||
use rustc_span::symbol::sym;
|
||||
use rustc_target::json::ToJson;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::max;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
|
|
@ -1205,29 +1204,20 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
|||
handler.emit_diagnostic(&mut d);
|
||||
}
|
||||
|
||||
let mut xs: Vec<Cow<'static, str>> = vec![
|
||||
"the compiler unexpectedly panicked. this is a bug.".into(),
|
||||
format!("we would appreciate a bug report: {bug_report_url}").into(),
|
||||
format!(
|
||||
"rustc {} running on {}",
|
||||
util::version_str!().unwrap_or("unknown_version"),
|
||||
config::host_triple()
|
||||
)
|
||||
.into(),
|
||||
];
|
||||
handler.emit_note(session_diagnostics::Ice);
|
||||
handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
||||
handler.emit_note(session_diagnostics::IceVersion {
|
||||
version: util::version_str!().unwrap_or("unknown_version"),
|
||||
triple: config::host_triple(),
|
||||
});
|
||||
|
||||
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
|
||||
xs.push(format!("compiler flags: {}", flags.join(" ")).into());
|
||||
|
||||
handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
|
||||
if excluded_cargo_defaults {
|
||||
xs.push("some of the compiler flags provided by cargo are hidden".into());
|
||||
handler.emit_note(session_diagnostics::IceExcludeCargoDefaults);
|
||||
}
|
||||
}
|
||||
|
||||
for note in &xs {
|
||||
handler.note_without_error(note.as_ref());
|
||||
}
|
||||
|
||||
// If backtraces are enabled, also print the query stack
|
||||
let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
|
||||
|
||||
|
|
|
|||
|
|
@ -38,3 +38,30 @@ pub(crate) struct UnprettyDumpFail {
|
|||
pub path: String,
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_ice)]
|
||||
pub(crate) struct Ice;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_ice_bug_report)]
|
||||
pub(crate) struct IceBugReport<'a> {
|
||||
pub bug_report_url: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_ice_version)]
|
||||
pub(crate) struct IceVersion<'a> {
|
||||
pub version: &'a str,
|
||||
pub triple: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_ice_flags)]
|
||||
pub(crate) struct IceFlags {
|
||||
pub flags: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_ice_exclude_cargo_defaults)]
|
||||
pub(crate) struct IceExcludeCargoDefaults;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// /!\ IMPORTANT /!\
|
||||
//
|
||||
// Error messages' format must follow the RFC 1567 available here:
|
||||
// https://github.com/rust-lang/rfcs/pull/1567
|
||||
// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html
|
||||
|
||||
register_diagnostics! {
|
||||
E0001: include_str!("./error_codes/E0001.md"),
|
||||
|
|
@ -510,6 +510,7 @@ E0789: include_str!("./error_codes/E0789.md"),
|
|||
E0790: include_str!("./error_codes/E0790.md"),
|
||||
E0791: include_str!("./error_codes/E0791.md"),
|
||||
E0792: include_str!("./error_codes/E0792.md"),
|
||||
E0793: include_str!("./error_codes/E0793.md"),
|
||||
;
|
||||
// E0006, // merged with E0005
|
||||
// E0008, // cannot bind by-move into a pattern guard
|
||||
|
|
|
|||
64
compiler/rustc_error_codes/src/error_codes/E0793.md
Normal file
64
compiler/rustc_error_codes/src/error_codes/E0793.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
An unaligned references to a field of a [packed] struct got created.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0793
|
||||
#[repr(packed)]
|
||||
pub struct Foo {
|
||||
field1: u64,
|
||||
field2: u8,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let foo = Foo { field1: 0, field2: 0 };
|
||||
// Accessing the field directly is fine.
|
||||
let val = foo.field1;
|
||||
// A reference to a packed field causes a error.
|
||||
let val = &foo.field1; // ERROR
|
||||
// An implicit `&` is added in format strings, causing the same error.
|
||||
println!("{}", foo.field1); // ERROR
|
||||
}
|
||||
```
|
||||
|
||||
Creating a reference to an insufficiently aligned packed field is
|
||||
[undefined behavior] and therefore disallowed. Using an `unsafe` block does not
|
||||
change anything about this. Instead, the code should do a copy of the data in
|
||||
the packed field or use raw pointers and unaligned accesses.
|
||||
|
||||
```
|
||||
#[repr(packed)]
|
||||
pub struct Foo {
|
||||
field1: u64,
|
||||
field2: u8,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let foo = Foo { field1: 0, field2: 0 };
|
||||
|
||||
// Instead of a reference, we can create a raw pointer...
|
||||
let ptr = std::ptr::addr_of!(foo.field1);
|
||||
// ... and then (crucially!) access it in an explicitly unaligned way.
|
||||
let val = unsafe { ptr.read_unaligned() };
|
||||
// This would *NOT* be correct:
|
||||
// let val = unsafe { *ptr }; // Undefined Behavior due to unaligned load!
|
||||
|
||||
// For formatting, we can create a copy to avoid the direct reference.
|
||||
let copy = foo.field1;
|
||||
println!("{}", copy);
|
||||
// Creating a copy can be written in a single line with curly braces.
|
||||
// (This is equivalent to the two lines above.)
|
||||
println!("{}", { foo.field1 });
|
||||
}
|
||||
```
|
||||
|
||||
### Additional information
|
||||
|
||||
Note that this error is specifically about *references* to packed fields.
|
||||
Direct by-value access of those fields is fine, since then the compiler has
|
||||
enough information to generate the correct kind of access.
|
||||
|
||||
See [issue #82523] for more information.
|
||||
|
||||
[packed]: https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers
|
||||
[undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
|
||||
[issue #82523]: https://github.com/rust-lang/rust/issues/82523
|
||||
|
|
@ -39,5 +39,51 @@ codegen_llvm_dynamic_linking_with_lto =
|
|||
cannot prefer dynamic linking when performing LTO
|
||||
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
||||
|
||||
codegen_llvm_fail_parsing_target_machine_config_to_target_machine =
|
||||
codegen_llvm_parse_target_machine_config =
|
||||
failed to parse target machine config to target machine: {$error}
|
||||
|
||||
codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
|
||||
|
||||
codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
|
||||
|
||||
codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
|
||||
|
||||
codegen_llvm_write_output = could not write output to {$path}
|
||||
codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
|
||||
|
||||
codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
|
||||
codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
|
||||
|
||||
codegen_llvm_run_passes = failed to run LLVM passes
|
||||
codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
|
||||
|
||||
codegen_llvm_serialize_module = failed to serialize module {$name}
|
||||
codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
|
||||
|
||||
codegen_llvm_write_ir = failed to write LLVM IR to {$path}
|
||||
codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
|
||||
|
||||
codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
|
||||
codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
|
||||
|
||||
codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
|
||||
codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
|
||||
|
||||
codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
|
||||
codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
|
||||
|
||||
codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
|
||||
codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
|
||||
|
||||
codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
|
||||
codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
|
||||
|
||||
codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
|
||||
codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
|
||||
|
||||
codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name}: {$message}
|
||||
codegen_llvm_from_llvm_diag = {$message}
|
||||
|
||||
codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
|
||||
|
||||
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
|
||||
|
|
|
|||
|
|
@ -11,3 +11,9 @@ driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version
|
|||
driver_rlink_no_a_file = rlink must be a file
|
||||
|
||||
driver_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
|
||||
|
||||
driver_ice = the compiler unexpectedly panicked. this is a bug.
|
||||
driver_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
||||
driver_ice_version = rustc {$version} running on {$triple}
|
||||
driver_ice_flags = compiler flags: {$flags}
|
||||
driver_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
||||
|
|
|
|||
|
|
@ -127,3 +127,5 @@ expand_module_file_not_found =
|
|||
expand_module_multiple_candidates =
|
||||
file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
|
||||
.help = delete or rename one of them to remove the ambiguity
|
||||
|
||||
expand_trace_macro = trace_macro
|
||||
|
|
|
|||
118
compiler/rustc_error_messages/locales/en-US/incremental.ftl
Normal file
118
compiler/rustc_error_messages/locales/en-US/incremental.ftl
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
|
||||
|
||||
incremental_missing_depnode = missing `DepNode` variant
|
||||
|
||||
incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
|
||||
|
||||
incremental_no_path = no path from `{$source}` to `{$target}`
|
||||
|
||||
incremental_ok = OK
|
||||
|
||||
incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
|
||||
|
||||
incremental_missing_query_depgraph =
|
||||
found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
|
||||
|
||||
incremental_malformed_cgu_name =
|
||||
found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
|
||||
|
||||
incremental_no_module_named =
|
||||
no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
|
||||
|
||||
incremental_field_associated_value_expected = associated value expected for `{$name}`
|
||||
|
||||
incremental_no_field = no field `{$name}`
|
||||
|
||||
incremental_assertion_auto =
|
||||
`except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\"
|
||||
|
||||
incremental_undefined_clean_dirty_assertions_item =
|
||||
clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
|
||||
|
||||
incremental_undefined_clean_dirty_assertions =
|
||||
clean/dirty auto-assertions not yet defined for {$kind}
|
||||
|
||||
incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
|
||||
|
||||
incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
|
||||
|
||||
incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
|
||||
|
||||
incremental_not_clean = `{$dep_node_str}` should be clean but is not
|
||||
|
||||
incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
|
||||
|
||||
incremental_unknown_item = unknown item `{$name}`
|
||||
|
||||
incremental_no_cfg = no cfg attribute
|
||||
|
||||
incremental_associated_value_expected_for = associated value expected for `{$ident}`
|
||||
|
||||
incremental_associated_value_expected = expected an associated value
|
||||
|
||||
incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
|
||||
|
||||
incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
|
||||
|
||||
incremental_create_new = failed to create {$name} at `{$path}`: {$err}
|
||||
|
||||
incremental_write_new = failed to write {$name} to `{$path}`: {$err}
|
||||
|
||||
incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
|
||||
|
||||
incremental_create_incr_comp_dir =
|
||||
could not create incremental compilation {$tag} directory `{$path}`: {$err}
|
||||
|
||||
incremental_create_lock =
|
||||
incremental compilation: could not create session directory lock file: {$lock_err}
|
||||
incremental_lock_unsupported =
|
||||
the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
|
||||
incremental_cargo_help_1 =
|
||||
incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
|
||||
incremental_cargo_help_2 =
|
||||
the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
|
||||
|
||||
incremental_delete_lock =
|
||||
error deleting lock file for incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_hard_link_failed =
|
||||
hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
|
||||
|
||||
incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
|
||||
|
||||
incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_invalid_gc_failed =
|
||||
failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_finalized_gc_failed =
|
||||
failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_session_gc_failed =
|
||||
failed to garbage collect incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_assert_not_loaded =
|
||||
we asserted that the incremental cache should not be loaded, but it was loaded
|
||||
|
||||
incremental_assert_loaded =
|
||||
we asserted that an existing incremental cache directory should be successfully loaded, but it was not
|
||||
|
||||
incremental_delete_incompatible =
|
||||
failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
|
||||
|
||||
incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
|
||||
|
||||
incremental_decode_incr_cache = could not decode incremental cache: {$err}
|
||||
|
||||
incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
|
||||
|
||||
incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
|
||||
|
||||
incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
|
||||
|
||||
incremental_copy_workproduct_to_cache =
|
||||
error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
|
||||
|
||||
incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
|
||||
|
|
@ -44,3 +44,13 @@ interface_failed_writing_file =
|
|||
|
||||
interface_proc_macro_crate_panic_abort =
|
||||
building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
|
||||
|
||||
interface_unsupported_crate_type_for_target =
|
||||
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
|
||||
|
||||
interface_multiple_output_types_adaption =
|
||||
due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
|
||||
|
||||
interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
|
||||
|
||||
interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
|
||||
|
|
|
|||
|
|
@ -24,3 +24,9 @@ monomorphize_large_assignments =
|
|||
|
||||
monomorphize_couldnt_dump_mono_stats =
|
||||
unexpected error occurred while dumping monomorphization stats: {$error}
|
||||
|
||||
monomorphize_encountered_error_while_instantiating =
|
||||
the above error was encountered while instantiating `{$formatted_item}`
|
||||
|
||||
monomorphize_unknown_cgu_collection_mode =
|
||||
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
|
||||
|
|
|
|||
|
|
@ -731,3 +731,5 @@ passes_proc_macro_missing_args = mismatched {$kind} signature
|
|||
passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"`
|
||||
|
||||
passes_proc_macro_unsafe = proc macro functions may not be `unsafe`
|
||||
|
||||
passes_skipping_const_checks = skipping const checks
|
||||
|
|
|
|||
|
|
@ -89,3 +89,5 @@ session_int_literal_too_large = integer literal is too large
|
|||
|
||||
session_invalid_int_literal_width = invalid width `{$width}` for integer literal
|
||||
.help = valid widths are 8, 16, 32, 64 and 128
|
||||
|
||||
session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ fluent_messages! {
|
|||
expand => "../locales/en-US/expand.ftl",
|
||||
hir_analysis => "../locales/en-US/hir_analysis.ftl",
|
||||
hir_typeck => "../locales/en-US/hir_typeck.ftl",
|
||||
incremental => "../locales/en-US/incremental.ftl",
|
||||
infer => "../locales/en-US/infer.ftl",
|
||||
interface => "../locales/en-US/interface.ftl",
|
||||
lint => "../locales/en-US/lint.ftl",
|
||||
|
|
|
|||
|
|
@ -1051,6 +1051,7 @@ impl Diagnostic {
|
|||
) -> (
|
||||
&Level,
|
||||
&[(DiagnosticMessage, Style)],
|
||||
Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
|
||||
&Option<DiagnosticId>,
|
||||
&MultiSpan,
|
||||
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
||||
|
|
@ -1059,6 +1060,7 @@ impl Diagnostic {
|
|||
(
|
||||
&self.level,
|
||||
&self.message,
|
||||
self.args().collect(),
|
||||
&self.code,
|
||||
&self.span,
|
||||
&self.suggestions,
|
||||
|
|
|
|||
|
|
@ -408,6 +408,59 @@ impl EmissionGuarantee for ! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> DiagnosticBuilder<'a, rustc_span::fatal_error::FatalError> {
|
||||
/// Convenience function for internal use, clients should use one of the
|
||||
/// `struct_*` methods on [`Handler`].
|
||||
#[track_caller]
|
||||
pub(crate) fn new_almost_fatal(
|
||||
handler: &'a Handler,
|
||||
message: impl Into<DiagnosticMessage>,
|
||||
) -> Self {
|
||||
let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
|
||||
Self::new_diagnostic_almost_fatal(handler, diagnostic)
|
||||
}
|
||||
|
||||
/// Creates a new `DiagnosticBuilder` with an already constructed
|
||||
/// diagnostic.
|
||||
pub(crate) fn new_diagnostic_almost_fatal(
|
||||
handler: &'a Handler,
|
||||
diagnostic: Diagnostic,
|
||||
) -> Self {
|
||||
debug!("Created new diagnostic");
|
||||
Self {
|
||||
inner: DiagnosticBuilderInner {
|
||||
state: DiagnosticBuilderState::Emittable(handler),
|
||||
diagnostic: Box::new(diagnostic),
|
||||
},
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
// First `.emit()` call, the `&Handler` is still available.
|
||||
DiagnosticBuilderState::Emittable(handler) => {
|
||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
|
||||
handler.emit_diagnostic(&mut db.inner.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
// Then fatally error..
|
||||
rustc_span::fatal_error::FatalError
|
||||
}
|
||||
|
||||
fn make_diagnostic_builder(
|
||||
handler: &Handler,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new_almost_fatal(handler, msg)
|
||||
}
|
||||
}
|
||||
|
||||
/// In general, the `DiagnosticBuilder` uses deref to allow access to
|
||||
/// the fields and methods of the embedded `diagnostic` in a
|
||||
/// transparent way. *However,* many of the methods are intended to
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagnosticArgFromDisplay<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + IntoDiagnosticArg> IntoDiagnosticArg for &'a T {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
self.clone().into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! into_diagnostic_arg_using_display {
|
||||
($( $ty:ty ),+ $(,)?) => {
|
||||
$(
|
||||
|
|
@ -153,12 +159,6 @@ impl IntoDiagnosticArg for ast::Path {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for &ast::Path {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for ast::token::Token {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(pprust::token_to_string(&self))
|
||||
|
|
@ -177,6 +177,18 @@ impl IntoDiagnosticArg for type_ir::FloatTy {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for std::ffi::CString {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for rustc_data_structures::small_c_str::SmallCStr {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for Level {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
|
||||
|
|
|
|||
|
|
@ -2113,30 +2113,38 @@ impl EmitterWriter {
|
|||
}
|
||||
}
|
||||
for sugg in suggestions {
|
||||
if sugg.style == SuggestionStyle::CompletelyHidden {
|
||||
// do not display this suggestion, it is meant only for tools
|
||||
} else if sugg.style == SuggestionStyle::HideCodeAlways {
|
||||
if let Err(e) = self.emit_message_default(
|
||||
&MultiSpan::new(),
|
||||
&[(sugg.msg.to_owned(), Style::HeaderMsg)],
|
||||
args,
|
||||
&None,
|
||||
&Level::Help,
|
||||
max_line_num_len,
|
||||
true,
|
||||
None,
|
||||
) {
|
||||
panic!("failed to emit error: {}", e);
|
||||
match sugg.style {
|
||||
SuggestionStyle::CompletelyHidden => {
|
||||
// do not display this suggestion, it is meant only for tools
|
||||
}
|
||||
} else if let Err(e) = self.emit_suggestion_default(
|
||||
span,
|
||||
sugg,
|
||||
args,
|
||||
&Level::Help,
|
||||
max_line_num_len,
|
||||
) {
|
||||
panic!("failed to emit error: {}", e);
|
||||
};
|
||||
SuggestionStyle::HideCodeAlways => {
|
||||
if let Err(e) = self.emit_message_default(
|
||||
&MultiSpan::new(),
|
||||
&[(sugg.msg.to_owned(), Style::HeaderMsg)],
|
||||
args,
|
||||
&None,
|
||||
&Level::Help,
|
||||
max_line_num_len,
|
||||
true,
|
||||
None,
|
||||
) {
|
||||
panic!("failed to emit error: {}", e);
|
||||
}
|
||||
}
|
||||
SuggestionStyle::HideCodeInline
|
||||
| SuggestionStyle::ShowCode
|
||||
| SuggestionStyle::ShowAlways => {
|
||||
if let Err(e) = self.emit_suggestion_default(
|
||||
span,
|
||||
sugg,
|
||||
args,
|
||||
&Level::Help,
|
||||
max_line_num_len,
|
||||
) {
|
||||
panic!("failed to emit error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -617,22 +617,24 @@ impl Handler {
|
|||
}
|
||||
}
|
||||
|
||||
/// Translate `message` eagerly with `args`.
|
||||
/// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
|
||||
pub fn eagerly_translate<'a>(
|
||||
&self,
|
||||
message: DiagnosticMessage,
|
||||
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
|
||||
) -> SubdiagnosticMessage {
|
||||
SubdiagnosticMessage::Eager(self.eagerly_translate_to_string(message, args))
|
||||
}
|
||||
|
||||
/// Translate `message` eagerly with `args` to `String`.
|
||||
pub fn eagerly_translate_to_string<'a>(
|
||||
&self,
|
||||
message: DiagnosticMessage,
|
||||
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
|
||||
) -> String {
|
||||
let inner = self.inner.borrow();
|
||||
let args = crate::translation::to_fluent_args(args);
|
||||
SubdiagnosticMessage::Eager(
|
||||
inner
|
||||
.emitter
|
||||
.translate_message(&message, &args)
|
||||
.map_err(Report::new)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
)
|
||||
inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
|
||||
}
|
||||
|
||||
// This is here to not allow mutation of flags;
|
||||
|
|
@ -1010,6 +1012,7 @@ impl Handler {
|
|||
}
|
||||
|
||||
#[track_caller]
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_note_without_error(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
|
|
@ -1019,6 +1022,7 @@ impl Handler {
|
|||
}
|
||||
|
||||
#[track_caller]
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_note_diag(
|
||||
&self,
|
||||
span: Span,
|
||||
|
|
@ -1030,19 +1034,23 @@ impl Handler {
|
|||
}
|
||||
|
||||
// NOTE: intentionally doesn't raise an error so rustc_codegen_ssa only reports fatal errors in the main thread
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> FatalError {
|
||||
self.inner.borrow_mut().fatal(msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
|
||||
self.inner.borrow_mut().err(msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
let mut db = DiagnosticBuilder::new(self, Warning(None), msg);
|
||||
db.emit();
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
DiagnosticBuilder::new(self, Note, msg).emit();
|
||||
}
|
||||
|
|
@ -1059,6 +1067,7 @@ impl Handler {
|
|||
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
|
||||
}
|
||||
|
||||
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
if self.inner.borrow().has_errors_or_lint_errors() {
|
||||
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
|
||||
|
|
@ -1132,6 +1141,20 @@ impl Handler {
|
|||
self.create_warning(warning).emit()
|
||||
}
|
||||
|
||||
pub fn create_almost_fatal<'a>(
|
||||
&'a self,
|
||||
fatal: impl IntoDiagnostic<'a, FatalError>,
|
||||
) -> DiagnosticBuilder<'a, FatalError> {
|
||||
fatal.into_diagnostic(self)
|
||||
}
|
||||
|
||||
pub fn emit_almost_fatal<'a>(
|
||||
&'a self,
|
||||
fatal: impl IntoDiagnostic<'a, FatalError>,
|
||||
) -> FatalError {
|
||||
self.create_almost_fatal(fatal).emit()
|
||||
}
|
||||
|
||||
pub fn create_fatal<'a>(
|
||||
&'a self,
|
||||
fatal: impl IntoDiagnostic<'a, !>,
|
||||
|
|
@ -1157,6 +1180,17 @@ impl Handler {
|
|||
self.create_bug(bug).emit()
|
||||
}
|
||||
|
||||
pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
|
||||
self.create_note(note).emit()
|
||||
}
|
||||
|
||||
pub fn create_note<'a>(
|
||||
&'a self,
|
||||
note: impl IntoDiagnostic<'a, Noted>,
|
||||
) -> DiagnosticBuilder<'a, Noted> {
|
||||
note.into_diagnostic(self)
|
||||
}
|
||||
|
||||
fn emit_diag_at_span(
|
||||
&self,
|
||||
mut diag: Diagnostic,
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ impl StyledBuffer {
|
|||
pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
|
||||
if let Some(ref mut line) = self.lines.get_mut(line) {
|
||||
if let Some(StyledChar { style: s, .. }) = line.get_mut(col) {
|
||||
if overwrite || *s == Style::NoStyle || *s == Style::Quotation {
|
||||
if overwrite || matches!(s, Style::NoStyle | Style::Quotation) {
|
||||
*s = style;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::errors::{
|
|||
ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
|
||||
AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
|
||||
MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
|
||||
ResolveRelativePath, TakesNoArguments,
|
||||
ResolveRelativePath, TakesNoArguments, TraceMacro,
|
||||
};
|
||||
use crate::expand::{self, AstFragment, Invocation};
|
||||
use crate::module::DirOwnership;
|
||||
|
|
@ -1142,8 +1142,8 @@ impl<'a> ExtCtxt<'a> {
|
|||
self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
|
||||
}
|
||||
pub fn trace_macros_diag(&mut self) {
|
||||
for (sp, notes) in self.expansions.iter() {
|
||||
let mut db = self.sess.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro");
|
||||
for (span, notes) in self.expansions.iter() {
|
||||
let mut db = self.sess.parse_sess.create_note(TraceMacro { span: *span });
|
||||
for note in notes {
|
||||
db.note(note);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,3 +368,10 @@ pub(crate) struct ModuleMultipleCandidates {
|
|||
pub default_path: String,
|
||||
pub secondary_path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_trace_macro)]
|
||||
pub struct TraceMacro {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -503,7 +503,7 @@ impl TtParser {
|
|||
mp.push_match(metavar_idx, seq_depth, MatchedSeq(vec![]));
|
||||
}
|
||||
|
||||
if op == KleeneOp::ZeroOrMore || op == KleeneOp::ZeroOrOne {
|
||||
if matches!(op, KleeneOp::ZeroOrMore | KleeneOp::ZeroOrOne) {
|
||||
// Try zero matches of this sequence, by skipping over it.
|
||||
self.cur_mps.push(MatcherPos {
|
||||
idx: idx_first_after,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ declare_features! (
|
|||
/// Allows `#[target_feature(...)]` on aarch64 platforms
|
||||
(accepted, aarch64_target_feature, "1.61.0", Some(44839), None),
|
||||
/// Allows using the `efiapi` ABI.
|
||||
(accepted, abi_efiapi, "CURRENT_RUSTC_VERSION", Some(65815), None),
|
||||
(accepted, abi_efiapi, "1.68.0", Some(65815), None),
|
||||
/// Allows the sysV64 ABI to be specified on all platforms
|
||||
/// instead of just the platforms on which it is the C ABI.
|
||||
(accepted, abi_sysv64, "1.24.0", Some(36167), None),
|
||||
|
|
@ -129,7 +129,7 @@ declare_features! (
|
|||
/// Allows `crate` in paths.
|
||||
(accepted, crate_in_paths, "1.30.0", Some(45477), None),
|
||||
/// Allows rustc to inject a default alloc_error_handler
|
||||
(accepted, default_alloc_error_handler, "CURRENT_RUSTC_VERSION", Some(66741), None),
|
||||
(accepted, default_alloc_error_handler, "1.68.0", Some(66741), None),
|
||||
/// Allows using assigning a default type to type parameters in algebraic data type definitions.
|
||||
(accepted, default_type_params, "1.0.0", None, None),
|
||||
/// Allows `#[deprecated]` attribute.
|
||||
|
|
@ -164,7 +164,7 @@ declare_features! (
|
|||
/// Allows access to crate names passed via `--extern` through prelude.
|
||||
(accepted, extern_prelude, "1.30.0", Some(44660), None),
|
||||
/// Allows using F16C intrinsics from `core::arch::{x86, x86_64}`.
|
||||
(accepted, f16c_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
|
||||
(accepted, f16c_target_feature, "1.68.0", Some(44839), None),
|
||||
/// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
|
||||
(accepted, field_init_shorthand, "1.17.0", Some(37340), None),
|
||||
/// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940).
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ declare_features! (
|
|||
/// Allows `async {}` expressions in const contexts.
|
||||
(active, const_async_blocks, "1.53.0", Some(85368), None),
|
||||
/// Allows `const || {}` closures in const contexts.
|
||||
(incomplete, const_closures, "CURRENT_RUSTC_VERSION", Some(106003), None),
|
||||
(incomplete, const_closures, "1.68.0", Some(106003), None),
|
||||
/// Allows limiting the evaluation steps of const expressions
|
||||
(active, const_eval_limit, "1.43.0", Some(67217), None),
|
||||
/// Allows the definition of `const extern fn` and `const unsafe extern fn`.
|
||||
|
|
|
|||
|
|
@ -385,10 +385,9 @@ pub fn check_generic_arg_count_for_call(
|
|||
) -> GenericArgCountResult {
|
||||
let empty_args = hir::GenericArgs::none();
|
||||
let gen_args = seg.args.unwrap_or(&empty_args);
|
||||
let gen_pos = if is_method_call == IsMethodCall::Yes {
|
||||
GenericArgPosition::MethodCall
|
||||
} else {
|
||||
GenericArgPosition::Value
|
||||
let gen_pos = match is_method_call {
|
||||
IsMethodCall::Yes => GenericArgPosition::MethodCall,
|
||||
IsMethodCall::No => GenericArgPosition::Value,
|
||||
};
|
||||
let has_self = generics.parent.is_none() && generics.has_self;
|
||||
|
||||
|
|
|
|||
|
|
@ -442,6 +442,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
|
||||
Ok(()) => {}
|
||||
Err(ty_err) => {
|
||||
let ty_err = ty_err.to_string(tcx);
|
||||
tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
|
||||
|
|
@ -605,59 +606,66 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
};
|
||||
check_abi(tcx, it.hir_id(), it.span, abi);
|
||||
|
||||
if abi == Abi::RustIntrinsic {
|
||||
for item in items {
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
intrinsic::check_intrinsic_type(tcx, item);
|
||||
}
|
||||
} else if abi == Abi::PlatformIntrinsic {
|
||||
for item in items {
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
intrinsic::check_platform_intrinsic_type(tcx, item);
|
||||
}
|
||||
} else {
|
||||
for item in items {
|
||||
let def_id = item.id.owner_id.def_id;
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let own_counts = generics.own_counts();
|
||||
if generics.params.len() - own_counts.lifetimes != 0 {
|
||||
let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) {
|
||||
(_, 0) => ("type", "types", Some("u32")),
|
||||
// We don't specify an example value, because we can't generate
|
||||
// a valid value for any type.
|
||||
(0, _) => ("const", "consts", None),
|
||||
_ => ("type or const", "types or consts", None),
|
||||
};
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
item.span,
|
||||
E0044,
|
||||
"foreign items may not have {kinds} parameters",
|
||||
)
|
||||
.span_label(item.span, &format!("can't have {kinds} parameters"))
|
||||
.help(
|
||||
// FIXME: once we start storing spans for type arguments, turn this
|
||||
// into a suggestion.
|
||||
&format!(
|
||||
"replace the {} parameters with concrete {}{}",
|
||||
kinds,
|
||||
kinds_pl,
|
||||
egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
match abi {
|
||||
Abi::RustIntrinsic => {
|
||||
for item in items {
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
intrinsic::check_intrinsic_type(tcx, item);
|
||||
}
|
||||
}
|
||||
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
match &item.kind {
|
||||
hir::ForeignItemKind::Fn(fn_decl, _, _) => {
|
||||
require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
|
||||
Abi::PlatformIntrinsic => {
|
||||
for item in items {
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
intrinsic::check_platform_intrinsic_type(tcx, item);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
for item in items {
|
||||
let def_id = item.id.owner_id.def_id;
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let own_counts = generics.own_counts();
|
||||
if generics.params.len() - own_counts.lifetimes != 0 {
|
||||
let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts)
|
||||
{
|
||||
(_, 0) => ("type", "types", Some("u32")),
|
||||
// We don't specify an example value, because we can't generate
|
||||
// a valid value for any type.
|
||||
(0, _) => ("const", "consts", None),
|
||||
_ => ("type or const", "types or consts", None),
|
||||
};
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
item.span,
|
||||
E0044,
|
||||
"foreign items may not have {kinds} parameters",
|
||||
)
|
||||
.span_label(item.span, &format!("can't have {kinds} parameters"))
|
||||
.help(
|
||||
// FIXME: once we start storing spans for type arguments, turn this
|
||||
// into a suggestion.
|
||||
&format!(
|
||||
"replace the {} parameters with concrete {}{}",
|
||||
kinds,
|
||||
kinds_pl,
|
||||
egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
match &item.kind {
|
||||
hir::ForeignItemKind::Fn(fn_decl, _, _) => {
|
||||
require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
|
||||
}
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1930,7 +1930,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
smallvec::SmallVec::with_capacity(defs.count());
|
||||
InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
let kind = ty::BoundTyKind::Param(param.name);
|
||||
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
|
||||
let bound_var = ty::BoundVariableKind::Ty(kind);
|
||||
bound_vars.push(bound_var);
|
||||
tcx.mk_ty(ty::Bound(
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ use rustc_ast_pretty::pp::{self, Breaks};
|
|||
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::LifetimeParamKind;
|
||||
use rustc_hir::{
|
||||
BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Mutability, Node, Term,
|
||||
};
|
||||
use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term};
|
||||
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
|
||||
|
|
@ -1746,7 +1744,7 @@ impl<'a> State<'a> {
|
|||
if by_ref == ByRef::Yes {
|
||||
self.word_nbsp("ref");
|
||||
}
|
||||
if mutbl == Mutability::Mut {
|
||||
if mutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
self.print_ident(ident);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use rustc_middle::ty::visit::TypeVisitable;
|
|||
use rustc_middle::ty::{self, Ty, TypeSuperVisitable, TypeVisitor};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::ArgKind;
|
||||
|
|
@ -288,21 +289,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let trait_def_id = projection.trait_def_id(tcx);
|
||||
|
||||
let is_fn = tcx.is_fn_trait(trait_def_id);
|
||||
let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span);
|
||||
let is_gen = gen_trait == trait_def_id;
|
||||
|
||||
let gen_trait = tcx.lang_items().gen_trait();
|
||||
let is_gen = gen_trait == Some(trait_def_id);
|
||||
|
||||
if !is_fn && !is_gen {
|
||||
debug!("not fn or generator");
|
||||
return None;
|
||||
}
|
||||
|
||||
if is_gen {
|
||||
// Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
|
||||
// associated item and not yield.
|
||||
let return_assoc_item = self.tcx.associated_item_def_ids(gen_trait)[1];
|
||||
if return_assoc_item != projection.projection_def_id() {
|
||||
debug!("not return assoc item of generator");
|
||||
return None;
|
||||
}
|
||||
// Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
|
||||
// associated item and not yield.
|
||||
if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return {
|
||||
debug!("not `Return` assoc item of `Generator`");
|
||||
return None;
|
||||
}
|
||||
|
||||
let input_tys = if is_fn {
|
||||
|
|
|
|||
|
|
@ -454,8 +454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
|
||||
None => {
|
||||
bug!(
|
||||
"no type for node {}: {} in fcx {}",
|
||||
id,
|
||||
"no type for node {} in fcx {}",
|
||||
self.tcx.hir().node_to_string(id),
|
||||
self.tag()
|
||||
);
|
||||
|
|
|
|||
|
|
@ -155,8 +155,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
None if self.is_tainted_by_errors() => Err(()),
|
||||
None => {
|
||||
bug!(
|
||||
"no type for node {}: {} in mem_categorization",
|
||||
id,
|
||||
"no type for node {} in mem_categorization",
|
||||
self.tcx().hir().node_to_string(id)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1354,13 +1354,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
return Some(Err(MethodError::Ambiguity(sources)));
|
||||
}
|
||||
|
||||
applicable_candidates.pop().map(|(probe, status)| {
|
||||
if status == ProbeResult::Match {
|
||||
applicable_candidates.pop().map(|(probe, status)| match status {
|
||||
ProbeResult::Match => {
|
||||
Ok(probe
|
||||
.to_unadjusted_pick(self_ty, unstable_candidates.cloned().unwrap_or_default()))
|
||||
} else {
|
||||
Err(MethodError::BadReturnType)
|
||||
}
|
||||
ProbeResult::NoMatch | ProbeResult::BadReturnType => Err(MethodError::BadReturnType),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,7 +259,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mode = no_match_data.mode;
|
||||
let tcx = self.tcx;
|
||||
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
|
||||
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
|
||||
let (ty_str, ty_file) = tcx.short_ty_string(rcvr_ty);
|
||||
let short_ty_str = with_forced_trimmed_paths!(rcvr_ty.to_string());
|
||||
let is_method = mode == Mode::MethodCall;
|
||||
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
|
||||
let similar_candidate = no_match_data.similar_candidate;
|
||||
|
|
@ -276,11 +277,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str)
|
||||
|| self.suggest_constraining_numerical_ty(
|
||||
tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
|
||||
)
|
||||
{
|
||||
// We could pass the file for long types into these two, but it isn't strictly necessary
|
||||
// given how targetted they are.
|
||||
if self.suggest_wrapping_range_with_parens(
|
||||
tcx,
|
||||
rcvr_ty,
|
||||
source,
|
||||
span,
|
||||
item_name,
|
||||
&short_ty_str,
|
||||
) || self.suggest_constraining_numerical_ty(
|
||||
tcx,
|
||||
rcvr_ty,
|
||||
source,
|
||||
span,
|
||||
item_kind,
|
||||
item_name,
|
||||
&short_ty_str,
|
||||
) {
|
||||
return None;
|
||||
}
|
||||
span = item_name.span;
|
||||
|
|
@ -319,6 +333,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
rcvr_ty.prefix_string(self.tcx),
|
||||
ty_str_reported,
|
||||
);
|
||||
let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
|
||||
short_ty_str
|
||||
} else {
|
||||
ty_str
|
||||
};
|
||||
if let Some(file) = ty_file {
|
||||
err.note(&format!("the full type name has been written to '{}'", file.display(),));
|
||||
}
|
||||
if rcvr_ty.references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
|
@ -826,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let primary_message = primary_message.unwrap_or_else(|| {
|
||||
format!(
|
||||
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
|
||||
but its trait bounds were not satisfied"
|
||||
but its trait bounds were not satisfied"
|
||||
)
|
||||
});
|
||||
err.set_primary_message(&primary_message);
|
||||
|
|
|
|||
|
|
@ -335,7 +335,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
format!("cannot divide `{lhs_ty}` by `{rhs_ty}`")
|
||||
}
|
||||
hir::BinOpKind::Rem => {
|
||||
format!("cannot mod `{lhs_ty}` by `{rhs_ty}`")
|
||||
format!(
|
||||
"cannot calculate the remainder of `{lhs_ty}` divided by `{rhs_ty}`"
|
||||
)
|
||||
}
|
||||
hir::BinOpKind::BitAnd => {
|
||||
format!("no implementation for `{lhs_ty} & {rhs_ty}`")
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
//! fn baz() { foo(); }
|
||||
//! ```
|
||||
|
||||
use crate::errors;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
|
||||
|
|
@ -133,12 +134,10 @@ impl<'tcx> IfThisChanged<'tcx> {
|
|||
Some(n) => {
|
||||
match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) {
|
||||
Ok(n) => n,
|
||||
Err(()) => {
|
||||
self.tcx.sess.span_fatal(
|
||||
attr.span,
|
||||
&format!("unrecognized DepNode variant {:?}", n),
|
||||
);
|
||||
}
|
||||
Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode {
|
||||
span: attr.span,
|
||||
name: n,
|
||||
}),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -149,16 +148,14 @@ impl<'tcx> IfThisChanged<'tcx> {
|
|||
Some(n) => {
|
||||
match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) {
|
||||
Ok(n) => n,
|
||||
Err(()) => {
|
||||
self.tcx.sess.span_fatal(
|
||||
attr.span,
|
||||
&format!("unrecognized DepNode variant {:?}", n),
|
||||
);
|
||||
}
|
||||
Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode {
|
||||
span: attr.span,
|
||||
name: n,
|
||||
}),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.tcx.sess.span_fatal(attr.span, "missing DepNode variant");
|
||||
self.tcx.sess.emit_fatal(errors::MissingDepNode { span: attr.span });
|
||||
}
|
||||
};
|
||||
self.then_this_would_need.push((
|
||||
|
|
@ -204,7 +201,7 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou
|
|||
// Return early here so as not to construct the query, which is not cheap.
|
||||
if if_this_changed.is_empty() {
|
||||
for &(target_span, _, _, _) in then_this_would_need {
|
||||
tcx.sess.span_err(target_span, "no `#[rustc_if_this_changed]` annotation detected");
|
||||
tcx.sess.emit_err(errors::MissingIfThisChanged { span: target_span });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -213,16 +210,13 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou
|
|||
let dependents = query.transitive_predecessors(source_dep_node);
|
||||
for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need {
|
||||
if !dependents.contains(&target_dep_node) {
|
||||
tcx.sess.span_err(
|
||||
target_span,
|
||||
&format!(
|
||||
"no path from `{}` to `{}`",
|
||||
tcx.def_path_str(source_def_id),
|
||||
target_pass
|
||||
),
|
||||
);
|
||||
tcx.sess.emit_err(errors::NoPath {
|
||||
span: target_span,
|
||||
source: tcx.def_path_str(source_def_id),
|
||||
target: *target_pass,
|
||||
});
|
||||
} else {
|
||||
tcx.sess.span_err(target_span, "OK");
|
||||
tcx.sess.emit_err(errors::Ok { span: target_span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
//! allows for doing a more fine-grained check to see if pre- or post-lto data
|
||||
//! was re-used.
|
||||
|
||||
use crate::errors;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
|
|
@ -66,10 +67,9 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
|||
sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact),
|
||||
sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast),
|
||||
other => {
|
||||
self.tcx.sess.span_fatal(
|
||||
attr.span,
|
||||
&format!("unknown cgu-reuse-kind `{}` specified", other),
|
||||
);
|
||||
self.tcx
|
||||
.sess
|
||||
.emit_fatal(errors::UnknownReuseKind { span: attr.span, kind: other });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -77,10 +77,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
|||
};
|
||||
|
||||
if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
|
||||
self.tcx.sess.span_fatal(
|
||||
attr.span,
|
||||
"found CGU-reuse attribute but `-Zquery-dep-graph` was not specified",
|
||||
);
|
||||
self.tcx.sess.emit_fatal(errors::MissingQueryDepGraph { span: attr.span });
|
||||
}
|
||||
|
||||
if !self.check_config(attr) {
|
||||
|
|
@ -92,13 +89,11 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
|||
let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string();
|
||||
|
||||
if !user_path.starts_with(&crate_name) {
|
||||
let msg = format!(
|
||||
"Found malformed codegen unit name `{}`. \
|
||||
Codegen units names must always start with the name of the \
|
||||
crate (`{}` in this case).",
|
||||
user_path, crate_name
|
||||
);
|
||||
self.tcx.sess.span_fatal(attr.span, &msg);
|
||||
self.tcx.sess.emit_fatal(errors::MalformedCguName {
|
||||
span: attr.span,
|
||||
user_path,
|
||||
crate_name,
|
||||
});
|
||||
}
|
||||
|
||||
// Split of the "special suffix" if there is one.
|
||||
|
|
@ -125,15 +120,12 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
|||
let mut cgu_names: Vec<&str> =
|
||||
self.available_cgus.iter().map(|cgu| cgu.as_str()).collect();
|
||||
cgu_names.sort();
|
||||
self.tcx.sess.span_err(
|
||||
attr.span,
|
||||
&format!(
|
||||
"no module named `{}` (mangled: {}). Available modules: {}",
|
||||
user_path,
|
||||
cgu_name,
|
||||
cgu_names.join(", ")
|
||||
),
|
||||
);
|
||||
self.tcx.sess.emit_err(errors::NoModuleNamed {
|
||||
span: attr.span,
|
||||
user_path,
|
||||
cgu_name,
|
||||
cgu_names: cgu_names.join(", "),
|
||||
});
|
||||
}
|
||||
|
||||
self.tcx.sess.cgu_reuse_tracker.set_expectation(
|
||||
|
|
@ -151,15 +143,15 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
|||
if let Some(value) = item.value_str() {
|
||||
return value;
|
||||
} else {
|
||||
self.tcx.sess.span_fatal(
|
||||
item.span(),
|
||||
&format!("associated value expected for `{}`", name),
|
||||
);
|
||||
self.tcx.sess.emit_fatal(errors::FieldAssociatedValueExpected {
|
||||
span: item.span(),
|
||||
name,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx.sess.span_fatal(attr.span, &format!("no field `{}`", name));
|
||||
self.tcx.sess.emit_fatal(errors::NoField { span: attr.span, name });
|
||||
}
|
||||
|
||||
/// Scan for a `cfg="foo"` attribute and check whether we have a
|
||||
|
|
|
|||
364
compiler/rustc_incremental/src/errors.rs
Normal file
364
compiler/rustc_incremental/src/errors.rs
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unrecognized_depnode)]
|
||||
pub struct UnrecognizedDepNode {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_missing_depnode)]
|
||||
pub struct MissingDepNode {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_missing_if_this_changed)]
|
||||
pub struct MissingIfThisChanged {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_ok)]
|
||||
pub struct Ok {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_path)]
|
||||
pub struct NoPath {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub target: Symbol,
|
||||
pub source: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unknown_reuse_kind)]
|
||||
pub struct UnknownReuseKind {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_missing_query_depgraph)]
|
||||
pub struct MissingQueryDepGraph {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_malformed_cgu_name)]
|
||||
pub struct MalformedCguName {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub user_path: String,
|
||||
pub crate_name: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_module_named)]
|
||||
pub struct NoModuleNamed<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub user_path: &'a str,
|
||||
pub cgu_name: Symbol,
|
||||
pub cgu_names: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_field_associated_value_expected)]
|
||||
pub struct FieldAssociatedValueExpected {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_field)]
|
||||
pub struct NoField {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_assertion_auto)]
|
||||
pub struct AssertionAuto<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: &'a str,
|
||||
pub e: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_undefined_clean_dirty_assertions_item)]
|
||||
pub struct UndefinedCleanDirtyItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_undefined_clean_dirty_assertions)]
|
||||
pub struct UndefinedCleanDirty {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_repeated_depnode_label)]
|
||||
pub struct RepeatedDepNodeLabel<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub label: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unrecognized_depnode_label)]
|
||||
pub struct UnrecognizedDepNodeLabel<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub label: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_not_dirty)]
|
||||
pub struct NotDirty<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub dep_node_str: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_not_clean)]
|
||||
pub struct NotClean<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub dep_node_str: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_not_loaded)]
|
||||
pub struct NotLoaded<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub dep_node_str: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unknown_item)]
|
||||
pub struct UnknownItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_cfg)]
|
||||
pub struct NoCfg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_associated_value_expected_for)]
|
||||
pub struct AssociatedValueExpectedFor {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_associated_value_expected)]
|
||||
pub struct AssociatedValueExpected {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unchecked_clean)]
|
||||
pub struct UncheckedClean {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_old)]
|
||||
pub struct DeleteOld<'a> {
|
||||
pub name: &'a str,
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_new)]
|
||||
pub struct CreateNew<'a> {
|
||||
pub name: &'a str,
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_write_new)]
|
||||
pub struct WriteNew<'a> {
|
||||
pub name: &'a str,
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_canonicalize_path)]
|
||||
pub struct CanonicalizePath {
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_incr_comp_dir)]
|
||||
pub struct CreateIncrCompDir<'a> {
|
||||
pub tag: &'a str,
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_lock)]
|
||||
pub struct CreateLock<'a> {
|
||||
pub lock_err: std::io::Error,
|
||||
pub session_dir: &'a Path,
|
||||
#[note(incremental_lock_unsupported)]
|
||||
pub is_unsupported_lock: Option<()>,
|
||||
#[help(incremental_cargo_help_1)]
|
||||
#[help(incremental_cargo_help_2)]
|
||||
pub is_cargo: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_lock)]
|
||||
pub struct DeleteLock<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_hard_link_failed)]
|
||||
pub struct HardLinkFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_partial)]
|
||||
pub struct DeletePartial<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_full)]
|
||||
pub struct DeleteFull<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_finalize)]
|
||||
pub struct Finalize<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_invalid_gc_failed)]
|
||||
pub struct InvalidGcFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_finalized_gc_failed)]
|
||||
pub struct FinalizedGcFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_session_gc_failed)]
|
||||
pub struct SessionGcFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_assert_not_loaded)]
|
||||
pub struct AssertNotLoaded;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_assert_loaded)]
|
||||
pub struct AssertLoaded;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_incompatible)]
|
||||
pub struct DeleteIncompatible {
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_load_dep_graph)]
|
||||
pub struct LoadDepGraph {
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_decode_incr_cache)]
|
||||
pub struct DecodeIncrCache {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_write_dep_graph)]
|
||||
pub struct WriteDepGraph<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_move_dep_graph)]
|
||||
pub struct MoveDepGraph<'a> {
|
||||
pub from: &'a Path,
|
||||
pub to: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_dep_graph)]
|
||||
pub struct CreateDepGraph<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_copy_workproduct_to_cache)]
|
||||
pub struct CopyWorkProductToCache<'a> {
|
||||
pub from: &'a Path,
|
||||
pub to: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_workproduct)]
|
||||
pub struct DeleteWorkProduct<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
#![deny(missing_docs)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(never_type)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
|
|
@ -12,6 +15,7 @@ extern crate tracing;
|
|||
|
||||
mod assert_dep_graph;
|
||||
pub mod assert_module_sources;
|
||||
mod errors;
|
||||
mod persist;
|
||||
|
||||
use assert_dep_graph::assert_dep_graph;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
//! Errors are reported if we are in the suitable configuration but
|
||||
//! the required condition is not met.
|
||||
|
||||
use crate::errors;
|
||||
use rustc_ast::{self as ast, Attribute, NestedMetaItem};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
|
|
@ -196,11 +197,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
let loaded_from_disk = self.loaded_from_disk(attr);
|
||||
for e in except.iter() {
|
||||
if !auto.remove(e) {
|
||||
let msg = format!(
|
||||
"`except` specified DepNodes that can not be affected for \"{}\": \"{}\"",
|
||||
name, e
|
||||
);
|
||||
self.tcx.sess.span_fatal(attr.span, &msg);
|
||||
self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e });
|
||||
}
|
||||
}
|
||||
Assertion { clean: auto, dirty: except, loaded_from_disk }
|
||||
|
|
@ -282,14 +279,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
// An implementation, eg `impl<A> Trait for Foo { .. }`
|
||||
HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL),
|
||||
|
||||
_ => self.tcx.sess.span_fatal(
|
||||
attr.span,
|
||||
&format!(
|
||||
"clean/dirty auto-assertions not yet defined \
|
||||
for Node::Item.node={:?}",
|
||||
item.kind
|
||||
),
|
||||
),
|
||||
_ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirtyItem {
|
||||
span: attr.span,
|
||||
kind: format!("{:?}", item.kind),
|
||||
}),
|
||||
}
|
||||
}
|
||||
HirNode::TraitItem(item) => match item.kind {
|
||||
|
|
@ -302,10 +295,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
|
||||
ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
|
||||
},
|
||||
_ => self.tcx.sess.span_fatal(
|
||||
attr.span,
|
||||
&format!("clean/dirty auto-assertions not yet defined for {:?}", node),
|
||||
),
|
||||
_ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirty {
|
||||
span: attr.span,
|
||||
kind: format!("{:?}", node),
|
||||
}),
|
||||
};
|
||||
let labels =
|
||||
Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string())));
|
||||
|
|
@ -318,16 +311,15 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
let label = label.trim();
|
||||
if DepNode::has_label_string(label) {
|
||||
if out.contains(label) {
|
||||
self.tcx.sess.span_fatal(
|
||||
item.span(),
|
||||
&format!("dep-node label `{}` is repeated", label),
|
||||
);
|
||||
self.tcx
|
||||
.sess
|
||||
.emit_fatal(errors::RepeatedDepNodeLabel { span: item.span(), label });
|
||||
}
|
||||
out.insert(label.to_string());
|
||||
} else {
|
||||
self.tcx
|
||||
.sess
|
||||
.span_fatal(item.span(), &format!("dep-node label `{}` not recognized", label));
|
||||
.emit_fatal(errors::UnrecognizedDepNodeLabel { span: item.span(), label });
|
||||
}
|
||||
}
|
||||
out
|
||||
|
|
@ -348,7 +340,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
let dep_node_str = self.dep_node_str(&dep_node);
|
||||
self.tcx
|
||||
.sess
|
||||
.span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str));
|
||||
.emit_err(errors::NotDirty { span: item_span, dep_node_str: &dep_node_str });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -359,7 +351,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
let dep_node_str = self.dep_node_str(&dep_node);
|
||||
self.tcx
|
||||
.sess
|
||||
.span_err(item_span, &format!("`{}` should be clean but is not", dep_node_str));
|
||||
.emit_err(errors::NotClean { span: item_span, dep_node_str: &dep_node_str });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -368,10 +360,9 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
|
||||
if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) {
|
||||
let dep_node_str = self.dep_node_str(&dep_node);
|
||||
self.tcx.sess.span_err(
|
||||
item_span,
|
||||
&format!("`{}` should have been loaded from disk but it was not", dep_node_str),
|
||||
);
|
||||
self.tcx
|
||||
.sess
|
||||
.emit_err(errors::NotLoaded { span: item_span, dep_node_str: &dep_node_str });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -412,12 +403,12 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
|
|||
debug!("check_config: searching for cfg {:?}", value);
|
||||
cfg = Some(config.contains(&(value, None)));
|
||||
} else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) {
|
||||
tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty()));
|
||||
tcx.sess.emit_err(errors::UnknownItem { span: attr.span, name: item.name_or_empty() });
|
||||
}
|
||||
}
|
||||
|
||||
match cfg {
|
||||
None => tcx.sess.span_fatal(attr.span, "no cfg attribute"),
|
||||
None => tcx.sess.emit_fatal(errors::NoCfg { span: attr.span }),
|
||||
Some(c) => c,
|
||||
}
|
||||
}
|
||||
|
|
@ -426,13 +417,11 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
|
|||
if let Some(value) = item.value_str() {
|
||||
value
|
||||
} else {
|
||||
let msg = if let Some(ident) = item.ident() {
|
||||
format!("associated value expected for `{}`", ident)
|
||||
if let Some(ident) = item.ident() {
|
||||
tcx.sess.emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident });
|
||||
} else {
|
||||
"expected an associated value".to_string()
|
||||
};
|
||||
|
||||
tcx.sess.span_fatal(item.span(), &msg);
|
||||
tcx.sess.emit_fatal(errors::AssociatedValueExpected { span: item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -456,7 +445,7 @@ impl<'tcx> FindAllAttrs<'tcx> {
|
|||
fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet<ast::AttrId>) {
|
||||
for attr in &self.found_attrs {
|
||||
if !checked_attrs.contains(&attr.id) {
|
||||
self.tcx.sess.span_err(attr.span, "found unchecked `#[rustc_clean]` attribute");
|
||||
self.tcx.sess.emit_err(errors::UncheckedClean { span: attr.span });
|
||||
checked_attrs.insert(attr.id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,15 @@
|
|||
//! compiler versions don't change frequently for the typical user, being
|
||||
//! conservative here practically has no downside.
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::{self, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::errors;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
use rustc_serialize::Encoder;
|
||||
use rustc_session::Session;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::{self, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// The first few bytes of files generated by incremental compilation.
|
||||
const FILE_MAGIC: &[u8] = b"RSIC";
|
||||
|
|
@ -60,12 +60,7 @@ where
|
|||
}
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => (),
|
||||
Err(err) => {
|
||||
sess.err(&format!(
|
||||
"unable to delete old {} at `{}`: {}",
|
||||
name,
|
||||
path_buf.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_err(errors::DeleteOld { name, path: path_buf, err });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -73,7 +68,7 @@ where
|
|||
let mut encoder = match FileEncoder::new(&path_buf) {
|
||||
Ok(encoder) => encoder,
|
||||
Err(err) => {
|
||||
sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
|
||||
sess.emit_err(errors::CreateNew { name, path: path_buf, err });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
@ -90,7 +85,7 @@ where
|
|||
debug!("save: data written to disk successfully");
|
||||
}
|
||||
Err(err) => {
|
||||
sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
|
||||
sess.emit_err(errors::WriteNew { name, path: path_buf, err });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
//! unsupported file system and emit a warning in that case. This is not yet
|
||||
//! implemented.
|
||||
|
||||
use crate::errors;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::{base_n, flock};
|
||||
|
|
@ -225,12 +226,7 @@ pub fn prepare_session_directory(
|
|||
let crate_dir = match crate_dir.canonicalize() {
|
||||
Ok(v) => v,
|
||||
Err(err) => {
|
||||
let reported = sess.err(&format!(
|
||||
"incremental compilation: error canonicalizing path `{}`: {}",
|
||||
crate_dir.display(),
|
||||
err
|
||||
));
|
||||
return Err(reported);
|
||||
return Err(sess.emit_err(errors::CanonicalizePath { path: crate_dir, err }));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -273,14 +269,7 @@ pub fn prepare_session_directory(
|
|||
debug!("successfully copied data from: {}", source_directory.display());
|
||||
|
||||
if !allows_links {
|
||||
sess.warn(&format!(
|
||||
"Hard linking files in the incremental \
|
||||
compilation cache failed. Copying files \
|
||||
instead. Consider moving the cache \
|
||||
directory to a file system which supports \
|
||||
hard linking in session dir `{}`",
|
||||
session_dir.display()
|
||||
));
|
||||
sess.emit_warning(errors::HardLinkFailed { path: &session_dir });
|
||||
}
|
||||
|
||||
sess.init_incr_comp_session(session_dir, directory_lock, true);
|
||||
|
|
@ -295,12 +284,7 @@ pub fn prepare_session_directory(
|
|||
// Try to remove the session directory we just allocated. We don't
|
||||
// know if there's any garbage in it from the failed copy action.
|
||||
if let Err(err) = safe_remove_dir_all(&session_dir) {
|
||||
sess.warn(&format!(
|
||||
"Failed to delete partly initialized \
|
||||
session dir `{}`: {}",
|
||||
session_dir.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::DeletePartial { path: &session_dir, err });
|
||||
}
|
||||
|
||||
delete_session_dir_lock_file(sess, &lock_file_path);
|
||||
|
|
@ -332,12 +316,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
|
|||
);
|
||||
|
||||
if let Err(err) = safe_remove_dir_all(&*incr_comp_session_dir) {
|
||||
sess.warn(&format!(
|
||||
"Error deleting incremental compilation \
|
||||
session directory `{}`: {}",
|
||||
incr_comp_session_dir.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::DeleteFull { path: &incr_comp_session_dir, err });
|
||||
}
|
||||
|
||||
let lock_file_path = lock_file_path(&*incr_comp_session_dir);
|
||||
|
|
@ -380,12 +359,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
|
|||
}
|
||||
Err(e) => {
|
||||
// Warn about the error. However, no need to abort compilation now.
|
||||
sess.warn(&format!(
|
||||
"Error finalizing incremental compilation \
|
||||
session directory `{}`: {}",
|
||||
incr_comp_session_dir.display(),
|
||||
e
|
||||
));
|
||||
sess.emit_warning(errors::Finalize { path: &incr_comp_session_dir, err: e });
|
||||
|
||||
debug!("finalize_session_directory() - error, marking as invalid");
|
||||
// Drop the file lock, so we can garage collect
|
||||
|
|
@ -488,16 +462,7 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGua
|
|||
debug!("{} directory created successfully", dir_tag);
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
let reported = sess.err(&format!(
|
||||
"Could not create incremental compilation {} \
|
||||
directory `{}`: {}",
|
||||
dir_tag,
|
||||
path.display(),
|
||||
err
|
||||
));
|
||||
Err(reported)
|
||||
}
|
||||
Err(err) => Err(sess.emit_err(errors::CreateIncrCompDir { tag: dir_tag, path, err })),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -518,46 +483,20 @@ fn lock_directory(
|
|||
// the lock should be exclusive
|
||||
Ok(lock) => Ok((lock, lock_file_path)),
|
||||
Err(lock_err) => {
|
||||
let mut err = sess.struct_err(&format!(
|
||||
"incremental compilation: could not create \
|
||||
session directory lock file: {}",
|
||||
lock_err
|
||||
));
|
||||
if flock::Lock::error_unsupported(&lock_err) {
|
||||
err.note(&format!(
|
||||
"the filesystem for the incremental path at {} \
|
||||
does not appear to support locking, consider changing the \
|
||||
incremental path to a filesystem that supports locking \
|
||||
or disable incremental compilation",
|
||||
session_dir.display()
|
||||
));
|
||||
if std::env::var_os("CARGO").is_some() {
|
||||
err.help(
|
||||
"incremental compilation can be disabled by setting the \
|
||||
environment variable CARGO_INCREMENTAL=0 (see \
|
||||
https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)",
|
||||
);
|
||||
err.help(
|
||||
"the entire build directory can be changed to a different \
|
||||
filesystem by setting the environment variable CARGO_TARGET_DIR \
|
||||
to a different path (see \
|
||||
https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)",
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err.emit())
|
||||
let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err).then_some(());
|
||||
Err(sess.emit_err(errors::CreateLock {
|
||||
lock_err,
|
||||
session_dir,
|
||||
is_unsupported_lock,
|
||||
is_cargo: std::env::var_os("CARGO").map(|_| ()),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) {
|
||||
if let Err(err) = safe_remove_file(&lock_file_path) {
|
||||
sess.warn(&format!(
|
||||
"Error deleting lock file for incremental \
|
||||
compilation session directory `{}`: {}",
|
||||
lock_file_path.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::DeleteLock { path: lock_file_path, err });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -774,12 +713,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
|
|||
if !lock_file_to_session_dir.values().any(|dir| *dir == directory_name) {
|
||||
let path = crate_directory.join(directory_name);
|
||||
if let Err(err) = safe_remove_dir_all(&path) {
|
||||
sess.warn(&format!(
|
||||
"Failed to garbage collect invalid incremental \
|
||||
compilation session directory `{}`: {}",
|
||||
path.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::InvalidGcFailed { path: &path, err });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -885,12 +819,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
|
|||
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
|
||||
|
||||
if let Err(err) = safe_remove_dir_all(&path) {
|
||||
sess.warn(&format!(
|
||||
"Failed to garbage collect finalized incremental \
|
||||
compilation session directory `{}`: {}",
|
||||
path.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::FinalizedGcFailed { path: &path, err });
|
||||
} else {
|
||||
delete_session_dir_lock_file(sess, &lock_file_path(&path));
|
||||
}
|
||||
|
|
@ -907,11 +836,7 @@ fn delete_old(sess: &Session, path: &Path) {
|
|||
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
|
||||
|
||||
if let Err(err) = safe_remove_dir_all(&path) {
|
||||
sess.warn(&format!(
|
||||
"Failed to garbage collect incremental compilation session directory `{}`: {}",
|
||||
path.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::SessionGcFailed { path: &path, err });
|
||||
} else {
|
||||
delete_session_dir_lock_file(sess, &lock_file_path(&path));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//! Code to save/load the dep-graph from files.
|
||||
|
||||
use crate::errors;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
|
||||
|
|
@ -8,7 +9,7 @@ use rustc_serialize::opaque::MemDecoder;
|
|||
use rustc_serialize::Decodable;
|
||||
use rustc_session::config::IncrementalStateAssertion;
|
||||
use rustc_session::Session;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::data::*;
|
||||
use super::file_format;
|
||||
|
|
@ -27,11 +28,10 @@ pub enum LoadResult<T> {
|
|||
},
|
||||
/// The file either didn't exist or was produced by an incompatible compiler version.
|
||||
DataOutOfDate,
|
||||
/// An error occurred.
|
||||
Error {
|
||||
#[allow(missing_docs)]
|
||||
message: String,
|
||||
},
|
||||
/// Loading the dep graph failed.
|
||||
LoadDepGraph(PathBuf, std::io::Error),
|
||||
/// Decoding loaded incremental cache failed.
|
||||
DecodeIncrCache(Box<dyn std::any::Any + Send>),
|
||||
}
|
||||
|
||||
impl<T: Default> LoadResult<T> {
|
||||
|
|
@ -40,36 +40,31 @@ impl<T: Default> LoadResult<T> {
|
|||
// Check for errors when using `-Zassert-incremental-state`
|
||||
match (sess.opts.assert_incr_state, &self) {
|
||||
(Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => {
|
||||
sess.fatal(
|
||||
"We asserted that the incremental cache should not be loaded, \
|
||||
but it was loaded.",
|
||||
);
|
||||
sess.emit_fatal(errors::AssertNotLoaded);
|
||||
}
|
||||
(
|
||||
Some(IncrementalStateAssertion::Loaded),
|
||||
LoadResult::Error { .. } | LoadResult::DataOutOfDate,
|
||||
LoadResult::LoadDepGraph(..)
|
||||
| LoadResult::DecodeIncrCache(..)
|
||||
| LoadResult::DataOutOfDate,
|
||||
) => {
|
||||
sess.fatal(
|
||||
"We asserted that an existing incremental cache directory should \
|
||||
be successfully loaded, but it was not.",
|
||||
);
|
||||
sess.emit_fatal(errors::AssertLoaded);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match self {
|
||||
LoadResult::Error { message } => {
|
||||
sess.warn(&message);
|
||||
LoadResult::LoadDepGraph(path, err) => {
|
||||
sess.emit_warning(errors::LoadDepGraph { path, err });
|
||||
Default::default()
|
||||
}
|
||||
LoadResult::DecodeIncrCache(err) => {
|
||||
sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") });
|
||||
Default::default()
|
||||
}
|
||||
LoadResult::DataOutOfDate => {
|
||||
if let Err(err) = delete_all_session_dir_contents(sess) {
|
||||
sess.err(&format!(
|
||||
"Failed to delete invalidated or incompatible \
|
||||
incremental compilation session directory contents `{}`: {}.",
|
||||
dep_graph_path(sess).display(),
|
||||
err
|
||||
));
|
||||
sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err });
|
||||
}
|
||||
Default::default()
|
||||
}
|
||||
|
|
@ -90,9 +85,7 @@ fn load_data(
|
|||
// compiler version. Neither is an error.
|
||||
LoadResult::DataOutOfDate
|
||||
}
|
||||
Err(err) => LoadResult::Error {
|
||||
message: format!("could not load dep-graph from `{}`: {}", path.display(), err),
|
||||
},
|
||||
Err(err) => LoadResult::LoadDepGraph(path.to_path_buf(), err),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,9 +107,9 @@ impl<T> MaybeAsync<LoadResult<T>> {
|
|||
pub fn open(self) -> LoadResult<T> {
|
||||
match self {
|
||||
MaybeAsync::Sync(result) => result,
|
||||
MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error {
|
||||
message: format!("could not decode incremental cache: {:?}", e),
|
||||
}),
|
||||
MaybeAsync::Async(handle) => {
|
||||
handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +178,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
|||
|
||||
match load_data(report_incremental_info, &path, nightly_build) {
|
||||
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
|
||||
LoadResult::Error { message } => LoadResult::Error { message },
|
||||
LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
|
||||
LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
|
||||
LoadResult::Ok { data: (bytes, start_pos) } => {
|
||||
let mut decoder = MemDecoder::new(&bytes, start_pos);
|
||||
let prev_commandline_args_hash = u64::decode(&mut decoder);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::errors;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::join;
|
||||
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
|
||||
|
|
@ -59,19 +60,14 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
|
|||
move || {
|
||||
sess.time("incr_comp_persist_dep_graph", || {
|
||||
if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) {
|
||||
sess.err(&format!(
|
||||
"failed to write dependency graph to `{}`: {}",
|
||||
staging_dep_graph_path.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_err(errors::WriteDepGraph { path: &staging_dep_graph_path, err });
|
||||
}
|
||||
if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) {
|
||||
sess.err(&format!(
|
||||
"failed to move dependency graph from `{}` to `{}`: {}",
|
||||
staging_dep_graph_path.display(),
|
||||
dep_graph_path.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_err(errors::MoveDepGraph {
|
||||
from: &staging_dep_graph_path,
|
||||
to: &dep_graph_path,
|
||||
err,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
@ -163,11 +159,7 @@ pub fn build_dep_graph(
|
|||
let mut encoder = match FileEncoder::new(&path_buf) {
|
||||
Ok(encoder) => encoder,
|
||||
Err(err) => {
|
||||
sess.err(&format!(
|
||||
"failed to create dependency graph at `{}`: {}",
|
||||
path_buf.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_err(errors::CreateDepGraph { path: &path_buf, err });
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
//!
|
||||
//! [work products]: WorkProduct
|
||||
|
||||
use crate::errors;
|
||||
use crate::persist::fs::*;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_fs_util::link_or_copy;
|
||||
|
|
@ -28,12 +29,11 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
|
|||
let _ = saved_files.insert(ext.to_string(), file_name);
|
||||
}
|
||||
Err(err) => {
|
||||
sess.warn(&format!(
|
||||
"error copying object file `{}` to incremental directory as `{}`: {}",
|
||||
path.display(),
|
||||
path_in_incr_dir.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::CopyWorkProductToCache {
|
||||
from: &path,
|
||||
to: &path_in_incr_dir,
|
||||
err,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,11 +49,7 @@ pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
|
|||
for (_, path) in &work_product.saved_files {
|
||||
let path = in_incr_comp_dir_sess(sess, path);
|
||||
if let Err(err) = std_fs::remove_file(&path) {
|
||||
sess.warn(&format!(
|
||||
"file-system error deleting outdated file `{}`: {}",
|
||||
path.display(),
|
||||
err
|
||||
));
|
||||
sess.emit_warning(errors::DeleteWorkProduct { path: &path, err });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
|||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{
|
||||
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
|
||||
|
|
@ -1612,16 +1613,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
{
|
||||
format!("expected this to be `{}`", expected)
|
||||
} else {
|
||||
terr.to_string()
|
||||
terr.to_string(self.tcx).to_string()
|
||||
};
|
||||
label_or_note(sp, &terr);
|
||||
label_or_note(span, &msg);
|
||||
} else {
|
||||
label_or_note(span, &terr.to_string());
|
||||
label_or_note(span, &terr.to_string(self.tcx));
|
||||
label_or_note(sp, &msg);
|
||||
}
|
||||
} else {
|
||||
label_or_note(span, &terr.to_string());
|
||||
if let Some(values) = values
|
||||
&& let Some((e, f)) = values.ty()
|
||||
&& let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
|
||||
{
|
||||
let e = self.tcx.erase_regions(e);
|
||||
let f = self.tcx.erase_regions(f);
|
||||
let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
|
||||
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
|
||||
if expected == found {
|
||||
label_or_note(span, &terr.to_string(self.tcx));
|
||||
} else {
|
||||
label_or_note(span, &format!("expected {expected}, found {found}"));
|
||||
}
|
||||
} else {
|
||||
label_or_note(span, &terr.to_string(self.tcx));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((expected, found, exp_p, found_p)) = expected_found {
|
||||
|
|
@ -1849,6 +1865,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
self.check_and_note_conflicting_crates(diag, terr);
|
||||
|
||||
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
|
||||
if let Some(exp_found) = exp_found
|
||||
&& let exp_found = TypeError::Sorts(exp_found)
|
||||
&& exp_found != terr
|
||||
{
|
||||
self.note_and_explain_type_err(
|
||||
diag,
|
||||
exp_found,
|
||||
cause,
|
||||
span,
|
||||
cause.body_id.to_def_id(),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
|
||||
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
|
||||
|
|
|
|||
|
|
@ -137,25 +137,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
diag.help(
|
||||
"given a type parameter `T` and a method `foo`:
|
||||
```
|
||||
trait Trait<T> { fn foo(&tcx) -> T; }
|
||||
trait Trait<T> { fn foo(&self) -> T; }
|
||||
```
|
||||
the only ways to implement method `foo` are:
|
||||
- constrain `T` with an explicit type:
|
||||
```
|
||||
impl Trait<String> for X {
|
||||
fn foo(&tcx) -> String { String::new() }
|
||||
fn foo(&self) -> String { String::new() }
|
||||
}
|
||||
```
|
||||
- add a trait bound to `T` and call a method on that trait that returns `Self`:
|
||||
```
|
||||
impl<T: std::default::Default> Trait<T> for X {
|
||||
fn foo(&tcx) -> T { <T as std::default::Default>::default() }
|
||||
fn foo(&self) -> T { <T as std::default::Default>::default() }
|
||||
}
|
||||
```
|
||||
- change `foo` to return an argument of type `T`:
|
||||
```
|
||||
impl<T> Trait<T> for X {
|
||||
fn foo(&tcx, x: T) -> T { x }
|
||||
fn foo(&self, x: T) -> T { x }
|
||||
}
|
||||
```",
|
||||
);
|
||||
|
|
@ -218,6 +218,13 @@ impl<T> Trait<T> for X {
|
|||
);
|
||||
}
|
||||
}
|
||||
(ty::FnPtr(_), ty::FnDef(def, _))
|
||||
if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
|
||||
diag.note(
|
||||
"when the arguments and return types match, functions can be coerced \
|
||||
to function pointers",
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
debug!(
|
||||
|
|
@ -389,14 +396,14 @@ impl<T> Trait<T> for X {
|
|||
```
|
||||
trait Trait {
|
||||
type T;
|
||||
fn foo(&tcx) -> Self::T;
|
||||
fn foo(&self) -> Self::T;
|
||||
}
|
||||
```
|
||||
the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
|
||||
```
|
||||
impl Trait for X {
|
||||
type T = String;
|
||||
fn foo(&tcx) -> Self::T { String::new() }
|
||||
fn foo(&self) -> Self::T { String::new() }
|
||||
}
|
||||
```",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
(msg, sug)
|
||||
}
|
||||
};
|
||||
diag.span_suggestion(span, msg, sug, Applicability::MaybeIncorrect);
|
||||
diag.span_suggestion_verbose(span, msg, sug, Applicability::MaybeIncorrect);
|
||||
}
|
||||
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
|
||||
let expected_sig =
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
types: &mut |bound_ty: ty::BoundTy| {
|
||||
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
|
||||
universe: next_universe,
|
||||
name: bound_ty.var,
|
||||
name: bound_ty.kind,
|
||||
}))
|
||||
},
|
||||
consts: &mut |bound_var: ty::BoundVar, ty| {
|
||||
|
|
|
|||
|
|
@ -2044,7 +2044,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
|
|||
) -> SubstsRef<'tcx> {
|
||||
struct ReplaceParamAndInferWithPlaceholder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
idx: usize,
|
||||
idx: u32,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
|
||||
|
|
@ -2056,7 +2056,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
|
|||
if let ty::Infer(_) = t.kind() {
|
||||
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
|
||||
universe: ty::UniverseIndex::ROOT,
|
||||
name: ty::BoundVar::from_usize({
|
||||
name: ty::BoundTyKind::Anon({
|
||||
let idx = self.idx;
|
||||
self.idx += 1;
|
||||
idx
|
||||
|
|
@ -2077,7 +2077,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
|
|||
self.tcx.mk_const(
|
||||
ty::PlaceholderConst {
|
||||
universe: ty::UniverseIndex::ROOT,
|
||||
name: ty::BoundVar::from_usize({
|
||||
name: ty::BoundVar::from_u32({
|
||||
let idx = self.idx;
|
||||
self.idx += 1;
|
||||
idx
|
||||
|
|
|
|||
|
|
@ -49,9 +49,6 @@ rustc_target = { path = "../rustc_target" }
|
|||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||
rustc_ty_utils = { path = "../rustc_ty_utils" }
|
||||
|
||||
[dev-dependencies]
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
|
||||
[features]
|
||||
llvm = ['rustc_codegen_llvm']
|
||||
rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler', 'rustc_errors/rustc_use_parallel_compiler']
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use rustc_macros::Diagnostic;
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::spec::TargetTriple;
|
||||
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
|
@ -91,3 +93,22 @@ pub struct FailedWritingFile<'a> {
|
|||
#[derive(Diagnostic)]
|
||||
#[diag(interface_proc_macro_crate_panic_abort)]
|
||||
pub struct ProcMacroCratePanicAbort;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_unsupported_crate_type_for_target)]
|
||||
pub struct UnsupportedCrateTypeForTarget<'a> {
|
||||
pub crate_type: CrateType,
|
||||
pub target_triple: &'a TargetTriple,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_multiple_output_types_adaption)]
|
||||
pub struct MultipleOutputTypesAdaption;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_ignoring_extra_filename)]
|
||||
pub struct IgnoringExtraFilename;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_ignoring_out_dir)]
|
||||
pub struct IgnoringOutDir;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::errors;
|
||||
use info;
|
||||
use libloading::Library;
|
||||
use rustc_ast as ast;
|
||||
|
|
@ -472,16 +473,15 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C
|
|||
}
|
||||
|
||||
base.retain(|crate_type| {
|
||||
let res = !output::invalid_output_for_target(session, *crate_type);
|
||||
|
||||
if !res {
|
||||
session.warn(&format!(
|
||||
"dropping unsupported crate type `{}` for target `{}`",
|
||||
*crate_type, session.opts.target_triple
|
||||
));
|
||||
if output::invalid_output_for_target(session, *crate_type) {
|
||||
session.emit_warning(errors::UnsupportedCrateTypeForTarget {
|
||||
crate_type: *crate_type,
|
||||
target_triple: &session.opts.target_triple,
|
||||
});
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
||||
res
|
||||
});
|
||||
|
||||
base
|
||||
|
|
@ -517,19 +517,16 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
|
|||
let unnamed_output_types =
|
||||
sess.opts.output_types.values().filter(|a| a.is_none()).count();
|
||||
let ofile = if unnamed_output_types > 1 {
|
||||
sess.warn(
|
||||
"due to multiple output types requested, the explicitly specified \
|
||||
output file name will be adapted for each output type",
|
||||
);
|
||||
sess.emit_warning(errors::MultipleOutputTypesAdaption);
|
||||
None
|
||||
} else {
|
||||
if !sess.opts.cg.extra_filename.is_empty() {
|
||||
sess.warn("ignoring -C extra-filename flag due to -o flag");
|
||||
sess.emit_warning(errors::IgnoringExtraFilename);
|
||||
}
|
||||
Some(out_file.clone())
|
||||
};
|
||||
if sess.io.output_dir != None {
|
||||
sess.warn("ignoring --out-dir flag due to -o flag");
|
||||
sess.emit_warning(errors::IgnoringOutDir);
|
||||
}
|
||||
|
||||
OutputFilenames::new(
|
||||
|
|
|
|||
|
|
@ -580,27 +580,28 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
|
||||
// If the method is an impl for a trait, don't doc.
|
||||
let context = method_context(cx, impl_item.owner_id.def_id);
|
||||
if context == MethodLateContext::TraitImpl {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the method is an impl for an item with docs_hidden, don't doc.
|
||||
if context == MethodLateContext::PlainImpl {
|
||||
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
|
||||
let impl_ty = cx.tcx.type_of(parent);
|
||||
let outerdef = match impl_ty.kind() {
|
||||
ty::Adt(def, _) => Some(def.did()),
|
||||
ty::Foreign(def_id) => Some(*def_id),
|
||||
_ => None,
|
||||
};
|
||||
let is_hidden = match outerdef {
|
||||
Some(id) => cx.tcx.is_doc_hidden(id),
|
||||
None => false,
|
||||
};
|
||||
if is_hidden {
|
||||
return;
|
||||
match context {
|
||||
// If the method is an impl for a trait, don't doc.
|
||||
MethodLateContext::TraitImpl => return,
|
||||
MethodLateContext::TraitAutoImpl => {}
|
||||
// If the method is an impl for an item with docs_hidden, don't doc.
|
||||
MethodLateContext::PlainImpl => {
|
||||
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
|
||||
let impl_ty = cx.tcx.type_of(parent);
|
||||
let outerdef = match impl_ty.kind() {
|
||||
ty::Adt(def, _) => Some(def.did()),
|
||||
ty::Foreign(def_id) => Some(*def_id),
|
||||
_ => None,
|
||||
};
|
||||
let is_hidden = match outerdef {
|
||||
Some(id) => cx.tcx.is_doc_hidden(id),
|
||||
None => false,
|
||||
};
|
||||
if is_hidden {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -324,7 +324,6 @@ fn register_builtins(store: &mut LintStore) {
|
|||
store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
|
||||
store.register_renamed("redundant_semicolon", "redundant_semicolons");
|
||||
store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
|
||||
store.register_renamed("safe_packed_borrows", "unaligned_references");
|
||||
store.register_renamed("disjoint_capture_migration", "rust_2021_incompatible_closure_captures");
|
||||
store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns");
|
||||
store.register_renamed("non_fmt_panic", "non_fmt_panics");
|
||||
|
|
@ -487,6 +486,16 @@ fn register_builtins(store: &mut LintStore) {
|
|||
"converted into hard error, see issue #71800 \
|
||||
<https://github.com/rust-lang/rust/issues/71800> for more information",
|
||||
);
|
||||
store.register_removed(
|
||||
"safe_packed_borrows",
|
||||
"converted into hard error, see issue #82523 \
|
||||
<https://github.com/rust-lang/rust/issues/82523> for more information",
|
||||
);
|
||||
store.register_removed(
|
||||
"unaligned_references",
|
||||
"converted into hard error, see issue #82523 \
|
||||
<https://github.com/rust-lang/rust/issues/82523> for more information",
|
||||
);
|
||||
}
|
||||
|
||||
fn register_internals(store: &mut LintStore) {
|
||||
|
|
|
|||
|
|
@ -1187,51 +1187,6 @@ declare_lint! {
|
|||
"lints that have been renamed or removed"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unaligned_references` lint detects unaligned references to fields
|
||||
/// of [packed] structs.
|
||||
///
|
||||
/// [packed]: https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #[repr(packed)]
|
||||
/// pub struct Foo {
|
||||
/// field1: u64,
|
||||
/// field2: u8,
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// let foo = Foo { field1: 0, field2: 0 };
|
||||
/// let _ = &foo.field1;
|
||||
/// println!("{}", foo.field1); // An implicit `&` is added here, triggering the lint.
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Creating a reference to an insufficiently aligned packed field is [undefined behavior] and
|
||||
/// should be disallowed. Using an `unsafe` block does not change anything about this. Instead,
|
||||
/// the code should do a copy of the data in the packed field or use raw pointers and unaligned
|
||||
/// accesses. See [issue #82523] for more information.
|
||||
///
|
||||
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
|
||||
/// [issue #82523]: https://github.com/rust-lang/rust/issues/82523
|
||||
pub UNALIGNED_REFERENCES,
|
||||
Deny,
|
||||
"detects unaligned references to fields of packed structs",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #82523 <https://github.com/rust-lang/rust/issues/82523>",
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
|
||||
};
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `const_item_mutation` lint detects attempts to mutate a `const`
|
||||
/// item.
|
||||
|
|
@ -3308,7 +3263,6 @@ declare_lint_pass! {
|
|||
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
||||
INVALID_TYPE_PARAM_DEFAULT,
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
UNALIGNED_REFERENCES,
|
||||
CONST_ITEM_MUTATION,
|
||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
MISSING_FRAGMENT_SPECIFIER,
|
||||
|
|
|
|||
|
|
@ -113,37 +113,37 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
|||
CrateType::Staticlib => Linkage::Static,
|
||||
};
|
||||
|
||||
if preferred_linkage == Linkage::NotLinked {
|
||||
match preferred_linkage {
|
||||
// If the crate is not linked, there are no link-time dependencies.
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
if preferred_linkage == Linkage::Static {
|
||||
// Attempt static linkage first. For dylibs and executables, we may be
|
||||
// able to retry below with dynamic linkage.
|
||||
if let Some(v) = attempt_static(tcx) {
|
||||
return v;
|
||||
}
|
||||
|
||||
// Staticlibs and static executables must have all static dependencies.
|
||||
// If any are not found, generate some nice pretty errors.
|
||||
if ty == CrateType::Staticlib
|
||||
|| (ty == CrateType::Executable
|
||||
&& sess.crt_static(Some(ty))
|
||||
&& !sess.target.crt_static_allows_dylibs)
|
||||
{
|
||||
for &cnum in tcx.crates(()).iter() {
|
||||
if tcx.dep_kind(cnum).macros_only() {
|
||||
continue;
|
||||
}
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.rlib.is_some() {
|
||||
continue;
|
||||
}
|
||||
sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
|
||||
Linkage::NotLinked => return Vec::new(),
|
||||
Linkage::Static => {
|
||||
// Attempt static linkage first. For dylibs and executables, we may be
|
||||
// able to retry below with dynamic linkage.
|
||||
if let Some(v) = attempt_static(tcx) {
|
||||
return v;
|
||||
}
|
||||
|
||||
// Staticlibs and static executables must have all static dependencies.
|
||||
// If any are not found, generate some nice pretty errors.
|
||||
if ty == CrateType::Staticlib
|
||||
|| (ty == CrateType::Executable
|
||||
&& sess.crt_static(Some(ty))
|
||||
&& !sess.target.crt_static_allows_dylibs)
|
||||
{
|
||||
for &cnum in tcx.crates(()).iter() {
|
||||
if tcx.dep_kind(cnum).macros_only() {
|
||||
continue;
|
||||
}
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.rlib.is_some() {
|
||||
continue;
|
||||
}
|
||||
sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
|
||||
}
|
||||
return Vec::new();
|
||||
}
|
||||
return Vec::new();
|
||||
}
|
||||
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
|
||||
}
|
||||
|
||||
let mut formats = FxHashMap::default();
|
||||
|
|
@ -283,12 +283,9 @@ fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
|
|||
let mut ret = tcx
|
||||
.crates(())
|
||||
.iter()
|
||||
.map(|&cnum| {
|
||||
if tcx.dep_kind(cnum) == CrateDepKind::Explicit {
|
||||
Linkage::Static
|
||||
} else {
|
||||
Linkage::NotLinked
|
||||
}
|
||||
.map(|&cnum| match tcx.dep_kind(cnum) {
|
||||
CrateDepKind::Explicit => Linkage::Static,
|
||||
CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ impl<'tcx> Collector<'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
|
||||
if matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1415,7 +1415,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
if encode_opt {
|
||||
record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
|
||||
|
||||
if let DefKind::Generator = self.tcx.def_kind(def_id) && tcx.sess.opts.unstable_opts.drop_tracking_mir {
|
||||
if tcx.sess.opts.unstable_opts.drop_tracking_mir && let DefKind::Generator = self.tcx.def_kind(def_id) {
|
||||
record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ impl<'hir> Map<'hir> {
|
|||
#[track_caller]
|
||||
pub fn parent_id(self, hir_id: HirId) -> HirId {
|
||||
self.opt_parent_id(hir_id)
|
||||
.unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
|
||||
.unwrap_or_else(|| bug!("No parent for node {}", self.node_to_string(hir_id)))
|
||||
}
|
||||
|
||||
pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
|
||||
|
|
@ -1191,12 +1191,10 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
|
|||
}
|
||||
|
||||
fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
||||
let id_str = format!(" (hir_id={})", id);
|
||||
|
||||
let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id.to_def_id());
|
||||
|
||||
let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
|
||||
let node_str = |prefix| format!("{} {}{}", prefix, span_str(), id_str);
|
||||
let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
|
||||
|
||||
match map.find(id) {
|
||||
Some(Node::Item(item)) => {
|
||||
|
|
@ -1225,10 +1223,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
ItemKind::TraitAlias(..) => "trait alias",
|
||||
ItemKind::Impl { .. } => "impl",
|
||||
};
|
||||
format!("{} {}{}", item_str, path_str(item.owner_id.def_id), id_str)
|
||||
format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
|
||||
}
|
||||
Some(Node::ForeignItem(item)) => {
|
||||
format!("foreign item {}{}", path_str(item.owner_id.def_id), id_str)
|
||||
format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
|
||||
}
|
||||
Some(Node::ImplItem(ii)) => {
|
||||
let kind = match ii.kind {
|
||||
|
|
@ -1236,7 +1234,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
ImplItemKind::Fn(..) => "method",
|
||||
ImplItemKind::Type(_) => "assoc type",
|
||||
};
|
||||
format!("{} {} in {}{}", kind, ii.ident, path_str(ii.owner_id.def_id), id_str)
|
||||
format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
|
||||
}
|
||||
Some(Node::TraitItem(ti)) => {
|
||||
let kind = match ti.kind {
|
||||
|
|
@ -1245,13 +1243,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
TraitItemKind::Type(..) => "assoc type",
|
||||
};
|
||||
|
||||
format!("{} {} in {}{}", kind, ti.ident, path_str(ti.owner_id.def_id), id_str)
|
||||
format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
|
||||
}
|
||||
Some(Node::Variant(ref variant)) => {
|
||||
format!("variant {} in {}{}", variant.ident, path_str(variant.def_id), id_str)
|
||||
format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
|
||||
}
|
||||
Some(Node::Field(ref field)) => {
|
||||
format!("field {} in {}{}", field.ident, path_str(field.def_id), id_str)
|
||||
format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
|
||||
}
|
||||
Some(Node::AnonConst(_)) => node_str("const"),
|
||||
Some(Node::Expr(_)) => node_str("expr"),
|
||||
|
|
@ -1269,16 +1267,15 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
Some(Node::Infer(_)) => node_str("infer"),
|
||||
Some(Node::Local(_)) => node_str("local"),
|
||||
Some(Node::Ctor(ctor)) => format!(
|
||||
"ctor {}{}",
|
||||
"{id} (ctor {})",
|
||||
ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
|
||||
id_str
|
||||
),
|
||||
Some(Node::Lifetime(_)) => node_str("lifetime"),
|
||||
Some(Node::GenericParam(ref param)) => {
|
||||
format!("generic_param {}{}", path_str(param.def_id), id_str)
|
||||
format!("{id} (generic_param {})", path_str(param.def_id))
|
||||
}
|
||||
Some(Node::Crate(..)) => String::from("root_crate"),
|
||||
None => format!("unknown node{}", id_str),
|
||||
Some(Node::Crate(..)) => String::from("(root_crate)"),
|
||||
None => format!("{id} (unknown node)"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,10 @@ impl Debug for CoverageKind {
|
|||
"Expression({:?}) = {} {} {}",
|
||||
id.index(),
|
||||
lhs.index(),
|
||||
if *op == Op::Add { "+" } else { "-" },
|
||||
match op {
|
||||
Op::Add => "+",
|
||||
Op::Subtract => "-",
|
||||
},
|
||||
rhs.index(),
|
||||
),
|
||||
Unreachable => write!(fmt, "Unreachable"),
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ fn write_graph_label<'tcx, W: std::fmt::Write>(
|
|||
let decl = &body.local_decls[local];
|
||||
|
||||
write!(w, "let ")?;
|
||||
if decl.mutability == Mutability::Mut {
|
||||
if decl.mutability.is_mut() {
|
||||
write!(w, "mut ")?;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -416,11 +416,7 @@ impl<'tcx> Body<'tcx> {
|
|||
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
|
||||
let local = Local::new(index);
|
||||
let decl = &self.local_decls[local];
|
||||
if decl.is_user_variable() && decl.mutability == Mutability::Mut {
|
||||
Some(local)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
(decl.is_user_variable() && decl.mutability.is_mut()).then(|| local)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -580,7 +580,7 @@ fn write_scope_tree(
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut_str = if local_decl.mutability == Mutability::Mut { "mut " } else { "" };
|
||||
let mut_str = local_decl.mutability.prefix_str();
|
||||
|
||||
let mut indented_decl =
|
||||
format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty);
|
||||
|
|
|
|||
|
|
@ -2171,7 +2171,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.late_bound_vars_map(id.owner)
|
||||
.and_then(|map| map.get(&id.local_id).cloned())
|
||||
.unwrap_or_else(|| {
|
||||
bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
|
||||
bug!("No bound vars found for {}", self.hir().node_to_string(id))
|
||||
})
|
||||
.iter(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@ use rustc_span::symbol::Symbol;
|
|||
use rustc_target::spec::abi;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)]
|
||||
|
|
@ -30,7 +28,7 @@ impl<T> ExpectedFound<T> {
|
|||
}
|
||||
|
||||
// Data structures used in type unification
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, PartialEq, Eq)]
|
||||
#[rustc_pass_by_value]
|
||||
pub enum TypeError<'tcx> {
|
||||
Mismatch,
|
||||
|
|
@ -87,20 +85,16 @@ impl TypeError<'_> {
|
|||
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
|
||||
/// afterwards to present additional details, particularly when it comes to lifetime-related
|
||||
/// errors.
|
||||
impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl<'tcx> TypeError<'tcx> {
|
||||
pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
use self::TypeError::*;
|
||||
fn report_maybe_different(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
expected: &str,
|
||||
found: &str,
|
||||
) -> fmt::Result {
|
||||
fn report_maybe_different(expected: &str, found: &str) -> String {
|
||||
// A naive approach to making sure that we're not reporting silly errors such as:
|
||||
// (expected closure, found closure).
|
||||
if expected == found {
|
||||
write!(f, "expected {}, found a different {}", expected, found)
|
||||
format!("expected {}, found a different {}", expected, found)
|
||||
} else {
|
||||
write!(f, "expected {}, found {}", expected, found)
|
||||
format!("expected {}, found {}", expected, found)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,64 +103,63 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
|||
_ => String::new(),
|
||||
};
|
||||
|
||||
match *self {
|
||||
CyclicTy(_) => write!(f, "cyclic type of infinite size"),
|
||||
CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
|
||||
Mismatch => write!(f, "types differ"),
|
||||
match self {
|
||||
CyclicTy(_) => "cyclic type of infinite size".into(),
|
||||
CyclicConst(_) => "encountered a self-referencing constant".into(),
|
||||
Mismatch => "types differ".into(),
|
||||
ConstnessMismatch(values) => {
|
||||
write!(f, "expected {} bound, found {} bound", values.expected, values.found)
|
||||
format!("expected {} bound, found {} bound", values.expected, values.found).into()
|
||||
}
|
||||
PolarityMismatch(values) => {
|
||||
write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
|
||||
format!("expected {} polarity, found {} polarity", values.expected, values.found)
|
||||
.into()
|
||||
}
|
||||
UnsafetyMismatch(values) => {
|
||||
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found).into()
|
||||
}
|
||||
AbiMismatch(values) => {
|
||||
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found).into()
|
||||
}
|
||||
ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
|
||||
TupleSize(values) => write!(
|
||||
f,
|
||||
ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
|
||||
TupleSize(values) => format!(
|
||||
"expected a tuple with {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
values.found,
|
||||
pluralize!(values.found)
|
||||
),
|
||||
FixedArraySize(values) => write!(
|
||||
f,
|
||||
)
|
||||
.into(),
|
||||
FixedArraySize(values) => format!(
|
||||
"expected an array with a fixed size of {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
values.found,
|
||||
pluralize!(values.found)
|
||||
),
|
||||
ArgCount => write!(f, "incorrect number of function parameters"),
|
||||
FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
|
||||
RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
|
||||
)
|
||||
.into(),
|
||||
ArgCount => "incorrect number of function parameters".into(),
|
||||
FieldMisMatch(adt, field) => format!("field type mismatch: {}.{}", adt, field).into(),
|
||||
RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
|
||||
// Actually naming the region here is a bit confusing because context is lacking
|
||||
RegionsInsufficientlyPolymorphic(..) => {
|
||||
write!(f, "one type is more general than the other")
|
||||
"one type is more general than the other".into()
|
||||
}
|
||||
RegionsOverlyPolymorphic(br, _) => write!(
|
||||
f,
|
||||
RegionsOverlyPolymorphic(br, _) => format!(
|
||||
"expected concrete lifetime, found bound lifetime parameter{}",
|
||||
br_string(br)
|
||||
),
|
||||
RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
|
||||
ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
|
||||
let (mut expected, mut found) = with_forced_trimmed_paths!((
|
||||
values.expected.sort_string(tcx),
|
||||
values.found.sort_string(tcx),
|
||||
));
|
||||
)
|
||||
.into(),
|
||||
RegionsPlaceholderMismatch => "one type is more general than the other".into(),
|
||||
ArgumentSorts(values, _) | Sorts(values) => {
|
||||
let mut expected = values.expected.sort_string(tcx);
|
||||
let mut found = values.found.sort_string(tcx);
|
||||
if expected == found {
|
||||
expected = values.expected.sort_string(tcx);
|
||||
found = values.found.sort_string(tcx);
|
||||
}
|
||||
report_maybe_different(f, &expected, &found)
|
||||
}),
|
||||
Traits(values) => ty::tls::with(|tcx| {
|
||||
report_maybe_different(&expected, &found).into()
|
||||
}
|
||||
Traits(values) => {
|
||||
let (mut expected, mut found) = with_forced_trimmed_paths!((
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found),
|
||||
|
|
@ -175,12 +168,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
|||
expected = tcx.def_path_str(values.expected);
|
||||
found = tcx.def_path_str(values.found);
|
||||
}
|
||||
report_maybe_different(
|
||||
f,
|
||||
&format!("trait `{expected}`"),
|
||||
&format!("trait `{found}`"),
|
||||
)
|
||||
}),
|
||||
report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
|
||||
.into()
|
||||
}
|
||||
IntMismatch(ref values) => {
|
||||
let expected = match values.expected {
|
||||
ty::IntVarValue::IntType(ty) => ty.name_str(),
|
||||
|
|
@ -190,43 +180,38 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
|||
ty::IntVarValue::IntType(ty) => ty.name_str(),
|
||||
ty::IntVarValue::UintType(ty) => ty.name_str(),
|
||||
};
|
||||
write!(f, "expected `{}`, found `{}`", expected, found)
|
||||
format!("expected `{}`, found `{}`", expected, found).into()
|
||||
}
|
||||
FloatMismatch(ref values) => {
|
||||
write!(
|
||||
f,
|
||||
"expected `{}`, found `{}`",
|
||||
values.expected.name_str(),
|
||||
values.found.name_str()
|
||||
)
|
||||
}
|
||||
VariadicMismatch(ref values) => write!(
|
||||
f,
|
||||
FloatMismatch(ref values) => format!(
|
||||
"expected `{}`, found `{}`",
|
||||
values.expected.name_str(),
|
||||
values.found.name_str()
|
||||
)
|
||||
.into(),
|
||||
VariadicMismatch(ref values) => format!(
|
||||
"expected {} fn, found {} function",
|
||||
if values.expected { "variadic" } else { "non-variadic" },
|
||||
if values.found { "variadic" } else { "non-variadic" }
|
||||
),
|
||||
ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
|
||||
write!(
|
||||
f,
|
||||
"expected {}, found {}",
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found)
|
||||
)
|
||||
}),
|
||||
)
|
||||
.into(),
|
||||
ProjectionMismatched(ref values) => format!(
|
||||
"expected `{}`, found `{}`",
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found)
|
||||
)
|
||||
.into(),
|
||||
ExistentialMismatch(ref values) => report_maybe_different(
|
||||
f,
|
||||
&format!("trait `{}`", values.expected),
|
||||
&format!("trait `{}`", values.found),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
ConstMismatch(ref values) => {
|
||||
write!(f, "expected `{}`, found `{}`", values.expected, values.found)
|
||||
format!("expected `{}`, found `{}`", values.expected, values.found).into()
|
||||
}
|
||||
IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
|
||||
TargetFeatureCast(_) => {
|
||||
"cannot coerce functions with `#[target_feature]` to safe function pointers".into()
|
||||
}
|
||||
IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"),
|
||||
TargetFeatureCast(_) => write!(
|
||||
f,
|
||||
"cannot coerce functions with `#[target_feature]` to safe function pointers"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -259,60 +244,9 @@ impl<'tcx> TypeError<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> Ty<'tcx> {
|
||||
pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
|
||||
pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
match *self.kind() {
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
|
||||
format!("`{}`", self).into()
|
||||
}
|
||||
ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
|
||||
|
||||
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
|
||||
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
|
||||
ty::Array(t, n) => {
|
||||
if t.is_simple_ty() {
|
||||
return format!("array `{}`", self).into();
|
||||
}
|
||||
|
||||
let n = tcx.lift(n).unwrap();
|
||||
if let ty::ConstKind::Value(v) = n.kind() {
|
||||
if let Some(n) = v.try_to_machine_usize(tcx) {
|
||||
return format!("array of {} element{}", n, pluralize!(n)).into();
|
||||
}
|
||||
}
|
||||
"array".into()
|
||||
}
|
||||
ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
|
||||
ty::Slice(_) => "slice".into(),
|
||||
ty::RawPtr(tymut) => {
|
||||
let tymut_string = match tymut.mutbl {
|
||||
hir::Mutability::Mut => tymut.to_string(),
|
||||
hir::Mutability::Not => format!("const {}", tymut.ty),
|
||||
};
|
||||
|
||||
if tymut_string != "_" && (tymut.ty.is_simple_text() || tymut_string.len() < "const raw pointer".len()) {
|
||||
format!("`*{}`", tymut_string).into()
|
||||
} else {
|
||||
// Unknown type name, it's long or has type arguments
|
||||
"raw pointer".into()
|
||||
}
|
||||
},
|
||||
ty::Ref(_, ty, mutbl) => {
|
||||
let tymut = ty::TypeAndMut { ty, mutbl };
|
||||
let tymut_string = tymut.to_string();
|
||||
|
||||
if tymut_string != "_"
|
||||
&& (ty.is_simple_text() || tymut_string.len() < "mutable reference".len())
|
||||
{
|
||||
format!("`&{}`", tymut_string).into()
|
||||
} else {
|
||||
// Unknown type name, it's long or has type arguments
|
||||
match mutbl {
|
||||
hir::Mutability::Mut => "mutable reference",
|
||||
_ => "reference",
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
|
||||
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
|
||||
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
|
||||
|
|
@ -320,14 +254,13 @@ impl<'tcx> Ty<'tcx> {
|
|||
},
|
||||
ty::FnPtr(_) => "fn pointer".into(),
|
||||
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
|
||||
format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
|
||||
format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into()
|
||||
}
|
||||
ty::Dynamic(..) => "trait object".into(),
|
||||
ty::Closure(..) => "closure".into(),
|
||||
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::GeneratorWitnessMIR(..) => "generator witness".into(),
|
||||
ty::Tuple(..) => "tuple".into(),
|
||||
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
|
||||
ty::Infer(ty::IntVar(_)) => "integer".into(),
|
||||
ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
|
||||
|
|
@ -337,9 +270,14 @@ impl<'tcx> Ty<'tcx> {
|
|||
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
|
||||
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
|
||||
ty::Alias(ty::Projection, _) => "associated type".into(),
|
||||
ty::Param(p) => format!("type parameter `{}`", p).into(),
|
||||
ty::Param(p) => format!("type parameter `{p}`").into(),
|
||||
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
|
||||
ty::Error(_) => "type error".into(),
|
||||
_ => {
|
||||
let width = tcx.sess.diagnostic_width();
|
||||
let length_limit = std::cmp::max(width / 4, 15);
|
||||
format!("`{}`", tcx.ty_string_with_limit(self, length_limit)).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -386,16 +324,14 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
|
||||
let width = self.sess.diagnostic_width();
|
||||
let length_limit = width.saturating_sub(30);
|
||||
pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
|
||||
let mut type_limit = 50;
|
||||
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
|
||||
.pretty_print_type(ty)
|
||||
.expect("could not write to `String`")
|
||||
.into_buffer();
|
||||
if regular.len() <= width {
|
||||
return (regular, None);
|
||||
if regular.len() <= length_limit {
|
||||
return regular;
|
||||
}
|
||||
let mut short;
|
||||
loop {
|
||||
|
|
@ -415,6 +351,20 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
type_limit -= 1;
|
||||
}
|
||||
short
|
||||
}
|
||||
|
||||
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
|
||||
let width = self.sess.diagnostic_width();
|
||||
let length_limit = width.saturating_sub(30);
|
||||
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
|
||||
.pretty_print_type(ty)
|
||||
.expect("could not write to `String`")
|
||||
.into_buffer();
|
||||
if regular.len() <= width {
|
||||
return (regular, None);
|
||||
}
|
||||
let short = self.ty_string_with_limit(ty, length_limit);
|
||||
if regular == short {
|
||||
return (regular, None);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -610,7 +610,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let index = entry.index();
|
||||
let var = ty::BoundVar::from_usize(index);
|
||||
let kind = entry
|
||||
.or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
|
||||
.or_insert_with(|| {
|
||||
ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32))
|
||||
})
|
||||
.expect_ty();
|
||||
self.tcx.mk_ty(ty::Bound(ty::INNERMOST, BoundTy { var, kind }))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1369,7 +1369,7 @@ pub struct Placeholder<T> {
|
|||
|
||||
pub type PlaceholderRegion = Placeholder<BoundRegionKind>;
|
||||
|
||||
pub type PlaceholderType = Placeholder<BoundVar>;
|
||||
pub type PlaceholderType = Placeholder<BoundTyKind>;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
|
||||
|
|
|
|||
|
|
@ -698,8 +698,10 @@ pub trait PrettyPrinter<'tcx>:
|
|||
ty::Error(_) => p!("[type error]"),
|
||||
ty::Param(ref param_ty) => p!(print(param_ty)),
|
||||
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
|
||||
ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
|
||||
ty::BoundTyKind::Param(p) => p!(write("{}", p)),
|
||||
ty::BoundTyKind::Anon(bv) => {
|
||||
self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
|
||||
}
|
||||
ty::BoundTyKind::Param(_, s) => p!(write("{}", s)),
|
||||
},
|
||||
ty::Adt(def, substs) => {
|
||||
p!(print_def_path(def.did(), substs));
|
||||
|
|
@ -1084,9 +1086,11 @@ pub trait PrettyPrinter<'tcx>:
|
|||
write!(self, "Sized")?;
|
||||
}
|
||||
|
||||
for re in lifetimes {
|
||||
write!(self, " + ")?;
|
||||
self = self.print_region(re)?;
|
||||
if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
|
||||
for re in lifetimes {
|
||||
write!(self, " + ")?;
|
||||
self = self.print_region(re)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
|
|
@ -2070,6 +2074,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
return true;
|
||||
}
|
||||
|
||||
if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
|
||||
|
||||
match *region {
|
||||
|
|
@ -2346,6 +2354,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
} else {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get());
|
||||
// Closure used in `RegionFolder` to create names for anonymous late-bound
|
||||
// regions. We use two `DebruijnIndex`es (one for the currently folded
|
||||
// late-bound region and the other for the binder level) to determine
|
||||
|
|
@ -2400,8 +2409,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
start_or_continue(&mut self, "for<", ", ");
|
||||
do_continue(&mut self, name);
|
||||
if !trim_path {
|
||||
start_or_continue(&mut self, "for<", ", ");
|
||||
do_continue(&mut self, name);
|
||||
}
|
||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
|
||||
};
|
||||
let mut folder = RegionFolder {
|
||||
|
|
@ -2412,7 +2423,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
};
|
||||
let new_value = value.clone().skip_binder().fold_with(&mut folder);
|
||||
let region_map = folder.region_map;
|
||||
start_or_continue(&mut self, "", "> ");
|
||||
if !trim_path {
|
||||
start_or_continue(&mut self, "", "> ");
|
||||
}
|
||||
(new_value, region_map)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ TrivialTypeTraversalAndLiftImpls! {
|
|||
crate::ty::AssocKind,
|
||||
crate::ty::AliasKind,
|
||||
crate::ty::Placeholder<crate::ty::BoundRegionKind>,
|
||||
crate::ty::Placeholder<crate::ty::BoundTyKind>,
|
||||
crate::ty::ClosureKind,
|
||||
crate::ty::FreeRegion,
|
||||
crate::ty::InferTy,
|
||||
|
|
|
|||
|
|
@ -1504,13 +1504,22 @@ pub struct BoundTy {
|
|||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundTyKind {
|
||||
Anon,
|
||||
Param(Symbol),
|
||||
Anon(u32),
|
||||
Param(DefId, Symbol),
|
||||
}
|
||||
|
||||
impl BoundTyKind {
|
||||
pub fn expect_anon(self) -> u32 {
|
||||
match self {
|
||||
BoundTyKind::Anon(i) => i,
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BoundVar> for BoundTy {
|
||||
fn from(var: BoundVar) -> Self {
|
||||
BoundTy { var, kind: BoundTyKind::Anon }
|
||||
BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
|||
|
||||
pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
self.node_type_opt(id).unwrap_or_else(|| {
|
||||
bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
|
||||
bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -551,9 +551,8 @@ fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
|||
fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
ty::tls::with(|tcx| {
|
||||
bug!(
|
||||
"node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
|
||||
"node {} cannot be placed in TypeckResults with hir_owner {:?}",
|
||||
tcx.hir().node_to_string(hir_id),
|
||||
hir_id.owner,
|
||||
hir_owner
|
||||
)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let expr_ty = expr.ty;
|
||||
let temp = {
|
||||
let mut local_decl = LocalDecl::new(expr_ty, expr_span);
|
||||
if mutability == Mutability::Not {
|
||||
if mutability.is_not() {
|
||||
local_decl = local_decl.immutable();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_errors::struct_span_err;
|
||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::lint::builtin::UNALIGNED_REFERENCES;
|
||||
|
||||
use crate::util;
|
||||
use crate::MirLint;
|
||||
|
|
@ -49,31 +49,22 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
|
|||
// shouldn't do.
|
||||
unreachable!();
|
||||
} else {
|
||||
let source_info = self.source_info;
|
||||
let lint_root = self.body.source_scopes[source_info.scope]
|
||||
.local_data
|
||||
.as_ref()
|
||||
.assert_crate_local()
|
||||
.lint_root;
|
||||
self.tcx.struct_span_lint_hir(
|
||||
UNALIGNED_REFERENCES,
|
||||
lint_root,
|
||||
source_info.span,
|
||||
"reference to packed field is unaligned",
|
||||
|lint| {
|
||||
lint
|
||||
.note(
|
||||
"fields of packed structs are not properly aligned, and creating \
|
||||
a misaligned reference is undefined behavior (even if that \
|
||||
reference is never dereferenced)",
|
||||
)
|
||||
.help(
|
||||
"copy the field contents to a local variable, or replace the \
|
||||
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
|
||||
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
|
||||
)
|
||||
},
|
||||
);
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
self.source_info.span,
|
||||
E0793,
|
||||
"reference to packed field is unaligned"
|
||||
)
|
||||
.note(
|
||||
"fields of packed structs are not properly aligned, and creating \
|
||||
a misaligned reference is undefined behavior (even if that \
|
||||
reference is never dereferenced)",
|
||||
).help(
|
||||
"copy the field contents to a local variable, or replace the \
|
||||
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
|
||||
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use std::cell::Cell;
|
|||
|
||||
use either::Right;
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_const_eval::const_eval::CheckAlignment;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def::DefKind;
|
||||
|
|
@ -289,7 +288,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||
}
|
||||
// If the static allocation is mutable, then we can't const prop it as its content
|
||||
// might be different at runtime.
|
||||
if alloc.inner().mutability == Mutability::Mut {
|
||||
if alloc.inner().mutability.is_mut() {
|
||||
throw_machine_stop_str!("can't access mutable globals in ConstProp");
|
||||
}
|
||||
|
||||
|
|
@ -528,7 +527,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?));
|
||||
let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?));
|
||||
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
|
||||
if op == BinOp::Shr || op == BinOp::Shl {
|
||||
if matches!(op, BinOp::Shr | BinOp::Shl) {
|
||||
let r = r.clone()?;
|
||||
// We need the type of the LHS. We cannot use `place_layout` as that is the type
|
||||
// of the result, which for checked binops is not the same!
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?)
|
||||
});
|
||||
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
|
||||
if op == BinOp::Shr || op == BinOp::Shl {
|
||||
if matches!(op, BinOp::Shr | BinOp::Shl) {
|
||||
let r = r.clone()?;
|
||||
// We need the type of the LHS. We cannot use `place_layout` as that is the type
|
||||
// of the result, which for checked binops is not the same!
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue