Auto merge of #104215 - Manishearth:rollup-5r957ad, r=Manishearth

Rollup of 9 pull requests

Successful merges:

 - #101005 (Migrate rustc_codegen_llvm to SessionDiagnostics)
 - #103307 (Add context to compiler error message)
 - #103464 (Add support for custom mir)
 - #103929 (Cleanup Apple-related code in rustc_target)
 - #104015 (Remove linuxkernel targets)
 - #104020 (Limit efiapi calling convention to supported arches)
 - #104156 (Cleanups in autoderef impl)
 - #104171 (Update books)
 - #104184 (Fix `rustdoc --version` when used with download-rustc)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-11-09 23:19:55 +00:00
commit 34115d040b
143 changed files with 1786 additions and 699 deletions

View File

@ -1557,7 +1557,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
let mut err = self.temporary_value_borrowed_for_too_long(proper_span);
err.span_label(proper_span, "creates a temporary which is freed while still in use");
err.span_label(proper_span, "creates a temporary value which is freed while still in use");
err.span_label(drop_span, "temporary value is freed at the end of this statement");
match explanation {

View File

@ -18,6 +18,7 @@ extern crate tracing;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::vec_map::VecMap;
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
@ -129,6 +130,19 @@ fn mir_borrowck<'tcx>(
) -> &'tcx BorrowCheckResult<'tcx> {
let (input_body, promoted) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
if input_body.borrow().should_skip() {
debug!("Skipping borrowck because of injected body");
// Let's make up a borrowck result! Fun times!
let result = BorrowCheckResult {
concrete_opaque_types: VecMap::new(),
closure_requirements: None,
used_mut_upvars: SmallVec::new(),
tainted_by_errors: None,
};
return tcx.arena.alloc(result);
}
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
let infcx =

View File

@ -59,7 +59,7 @@ impl DebugContext {
let producer = format!(
"cg_clif (rustc {}, cranelift {})",
rustc_interface::util::version_str().unwrap_or("unknown version"),
rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
cranelift_codegen::VERSION,
);
let comp_dir = tcx

View File

@ -12,6 +12,7 @@ use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtec
use smallvec::SmallVec;
use crate::attributes;
use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable};
use crate::llvm::AttributePlace::Function;
use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
use crate::llvm_util;
@ -82,7 +83,7 @@ pub fn sanitize_attrs<'ll>(
let mte_feature =
features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..]));
if let None | Some("-mte") = mte_feature {
cx.tcx.sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
cx.tcx.sess.emit_err(SanitizerMemtagRequiresMte);
}
attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx));
@ -393,13 +394,14 @@ pub fn from_fn_attrs<'ll, 'tcx>(
.get_attrs(instance.def_id(), sym::target_feature)
.next()
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
let msg = format!(
"the target features {} must all be either enabled or disabled together",
f.join(", ")
);
let mut err = cx.tcx.sess.struct_span_err(span, &msg);
err.help("add the missing features in a `target_feature` attribute");
err.emit();
cx.tcx
.sess
.create_err(TargetFeatureDisableOrEnable {
features: f,
span: Some(span),
missing_features: Some(MissingFeatures),
})
.emit();
return;
}

View File

@ -12,6 +12,10 @@ use std::str;
use object::read::macho::FatArch;
use crate::common;
use crate::errors::{
ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary,
ErrorWritingDEFFile, UnknownArchiveKind,
};
use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
@ -147,7 +151,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
fn build(mut self: Box<Self>, output: &Path) -> bool {
match self.build_with_llvm(output) {
Ok(any_members) => any_members,
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
Err(e) => self.sess.emit_fatal(ArchiveBuildFailure { error: e }),
}
}
}
@ -217,7 +221,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
match std::fs::write(&def_file_path, def_file_content) {
Ok(_) => {}
Err(e) => {
sess.fatal(&format!("Error writing .DEF file: {}", e));
sess.emit_fatal(ErrorWritingDEFFile { error: e });
}
};
@ -239,13 +243,14 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
match result {
Err(e) => {
sess.fatal(&format!("Error calling dlltool: {}", e));
sess.emit_fatal(ErrorCallingDllTool { error: e });
}
Ok(output) if !output.status.success() => {
sess.emit_fatal(DlltoolFailImportLibrary {
stdout: String::from_utf8_lossy(&output.stdout),
stderr: String::from_utf8_lossy(&output.stderr),
})
}
Ok(output) if !output.status.success() => sess.fatal(&format!(
"Dlltool could not create import library: {}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
)),
_ => {}
}
} else {
@ -293,11 +298,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
};
if result == crate::llvm::LLVMRustResult::Failure {
sess.fatal(&format!(
"Error creating import library for {}: {}",
sess.emit_fatal(ErrorCreatingImportLibrary {
lib_name,
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
));
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
});
}
};
@ -308,9 +312,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
impl<'a> LlvmArchiveBuilder<'a> {
fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
let kind = &*self.sess.target.archive_format;
let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
});
let kind = kind
.parse::<ArchiveKind>()
.map_err(|_| kind)
.unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind }));
let mut additions = mem::take(&mut self.additions);
let mut strings = Vec::new();

View File

@ -1,4 +1,5 @@
use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
use crate::errors::DynamicLinkingWithLTO;
use crate::llvm::{self, build_string};
use crate::{LlvmCodegenBackend, ModuleLlvm};
use object::read::archive::ArchiveFile;
@ -90,13 +91,7 @@ fn prepare_lto(
}
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
diag_handler
.struct_err("cannot prefer dynamic linking when performing LTO")
.note(
"only 'staticlib', 'bin', and 'cdylib' outputs are \
supported with LTO",
)
.emit();
diag_handler.emit_err(DynamicLinkingWithLTO);
return Err(FatalError);
}

View File

@ -1,6 +1,7 @@
use crate::base;
use crate::common::{self, CodegenCx};
use crate::debuginfo;
use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
use crate::llvm::{self, True};
use crate::llvm_util;
use crate::type_::Type;
@ -146,7 +147,7 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align:
match Align::from_bits(min) {
Ok(min) => align = align.max(min),
Err(err) => {
cx.sess().err(&format!("invalid minimum global alignment: {}", err));
cx.sess().emit_err(InvalidMinimumAlignment { err });
}
}
}
@ -174,10 +175,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
cx.layout_of(mt.ty).llvm_type(cx)
} else {
cx.sess().span_fatal(
cx.tcx.def_span(def_id),
"must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
)
cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
@ -193,10 +191,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(sym);
let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
cx.sess().span_fatal(
cx.tcx.def_span(def_id),
&format!("symbol `{}` is already defined", &sym),
)
cx.sess().emit_fatal(SymbolAlreadyDefined {
span: cx.tcx.def_span(def_id),
symbol_name: sym,
})
});
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
llvm::LLVMSetInitializer(g2, g1);

View File

@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model;
use crate::callee::get_fn;
use crate::coverageinfo;
use crate::debuginfo;
use crate::errors::BranchProtectionRequiresAArch64;
use crate::llvm;
use crate::llvm_util;
use crate::type_::Type;
@ -26,6 +27,7 @@ use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
use rustc_session::Session;
use rustc_span::source_map::Span;
use rustc_span::source_map::Spanned;
use rustc_target::abi::{
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
};
@ -275,7 +277,7 @@ pub unsafe fn create_module<'ll>(
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
if sess.target.arch != "aarch64" {
sess.err("-Zbranch-protection is only supported on aarch64");
sess.emit_err(BranchProtectionRequiresAArch64);
} else {
llvm::LLVMRustAddModuleFlag(
llmod,
@ -951,7 +953,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
#[inline]
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
if let LayoutError::SizeOverflow(_) = err {
self.sess().span_fatal(span, &err.to_string())
self.sess().emit_fatal(Spanned { span, node: err })
} else {
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
}
@ -969,7 +971,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
fn_abi_request: FnAbiRequest<'tcx>,
) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
self.sess().span_fatal(span, &err.to_string())
self.sess().emit_fatal(Spanned { span, node: err })
} else {
match fn_abi_request {
FnAbiRequest::OfFnPtr { sig, extra_args } => {

View File

@ -1,5 +1,6 @@
use crate::common::CodegenCx;
use crate::coverageinfo;
use crate::errors::InstrumentCoverageRequiresLLVM12;
use crate::llvm;
use llvm::coverageinfo::CounterMappingRegion;
@ -37,7 +38,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
// LLVM 12.
let version = coverageinfo::mapping_version();
if version < 4 {
tcx.sess.fatal("rustc option `-C instrument-coverage` requires LLVM 12 or higher.");
tcx.sess.emit_fatal(InstrumentCoverageRequiresLLVM12);
}
debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());

View File

@ -0,0 +1,139 @@
use std::borrow::Cow;
use rustc_errors::fluent;
use rustc_errors::DiagnosticBuilder;
use rustc_errors::ErrorGuaranteed;
use rustc_errors::Handler;
use rustc_errors::IntoDiagnostic;
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span;
#[derive(Diagnostic)]
#[diag(codegen_llvm_unknown_ctarget_feature_prefix)]
#[note]
pub(crate) struct UnknownCTargetFeaturePrefix<'a> {
pub feature: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_unknown_ctarget_feature)]
#[note]
pub(crate) struct UnknownCTargetFeature<'a> {
pub feature: &'a str,
#[subdiagnostic]
pub rust_feature: PossibleFeature<'a>,
}
#[derive(Subdiagnostic)]
pub(crate) enum PossibleFeature<'a> {
#[help(possible_feature)]
Some { rust_feature: &'a str },
#[help(consider_filing_feature_request)]
None,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_error_creating_import_library)]
pub(crate) struct ErrorCreatingImportLibrary<'a> {
pub lib_name: &'a str,
pub error: String,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_instrument_coverage_requires_llvm_12)]
pub(crate) struct InstrumentCoverageRequiresLLVM12;
#[derive(Diagnostic)]
#[diag(codegen_llvm_symbol_already_defined)]
pub(crate) struct SymbolAlreadyDefined<'a> {
#[primary_span]
pub span: Span,
pub symbol_name: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_branch_protection_requires_aarch64)]
pub(crate) struct BranchProtectionRequiresAArch64;
#[derive(Diagnostic)]
#[diag(codegen_llvm_invalid_minimum_alignment)]
pub(crate) struct InvalidMinimumAlignment {
pub err: String,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_linkage_const_or_mut_type)]
pub(crate) struct LinkageConstOrMutType {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
pub(crate) struct SanitizerMemtagRequiresMte;
#[derive(Diagnostic)]
#[diag(codegen_llvm_archive_build_failure)]
pub(crate) struct ArchiveBuildFailure {
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_error_writing_def_file)]
pub(crate) struct ErrorWritingDEFFile {
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_error_calling_dlltool)]
pub(crate) struct ErrorCallingDllTool {
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_dlltool_fail_import_library)]
pub(crate) struct DlltoolFailImportLibrary<'a> {
pub stdout: Cow<'a, str>,
pub stderr: Cow<'a, str>,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_unknown_archive_kind)]
pub(crate) struct UnknownArchiveKind<'a> {
pub kind: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_dynamic_linking_with_lto)]
#[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 TargetFeatureDisableOrEnable<'a> {
pub features: &'a [&'a str],
pub span: Option<Span>,
pub missing_features: Option<MissingFeatures>,
}
#[derive(Subdiagnostic)]
#[help(codegen_llvm_missing_features)]
pub(crate) struct MissingFeatures;
impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable);
if let Some(span) = self.span {
diag.set_span(span);
};
if let Some(missing_features) = self.missing_features {
diag.subdiagnostic(missing_features);
}
diag.set_arg("features", self.features.join(", "));
diag
}
}

View File

@ -12,6 +12,8 @@
#![feature(iter_intersperse)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;
@ -20,6 +22,7 @@ extern crate tracing;
use back::write::{create_informational_target_machine, create_target_machine};
use errors::FailParsingTargetMachineConfigToTargetMachine;
pub use llvm_util::target_features;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
@ -62,6 +65,7 @@ mod context;
mod coverageinfo;
mod debuginfo;
mod declare;
mod errors;
mod intrinsic;
// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
@ -412,7 +416,7 @@ impl ModuleLlvm {
let tm = match (cgcx.tm_factory)(tm_factory_config) {
Ok(m) => m,
Err(e) => {
handler.struct_err(&e).emit();
handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e });
return Err(FatalError);
}
};

View File

@ -1,4 +1,8 @@
use crate::back::write::create_informational_target_machine;
use crate::errors::{
PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
UnknownCTargetFeaturePrefix,
};
use crate::llvm;
use libc::c_int;
use rustc_codegen_ssa::target_features::{
@ -434,12 +438,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
Some(c @ '+' | c @ '-') => c,
Some(_) => {
if diagnostics {
let mut diag = sess.struct_warn(&format!(
"unknown feature specified for `-Ctarget-feature`: `{}`",
s
));
diag.note("features must begin with a `+` to enable or `-` to disable it");
diag.emit();
sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s });
}
return None;
}
@ -456,17 +455,15 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
None
}
});
let mut diag = sess.struct_warn(&format!(
"unknown feature specified for `-Ctarget-feature`: `{}`",
feature
));
diag.note("it is still passed through to the codegen backend");
if let Some(rust_feature) = rust_feature {
diag.help(&format!("you might have meant: `{}`", rust_feature));
} else {
diag.note("consider filing a feature request");
let unknown_feature = if let Some(rust_feature) = rust_feature {
UnknownCTargetFeature {
feature,
rust_feature: PossibleFeature::Some { rust_feature },
}
diag.emit();
} else {
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
};
sess.emit_warning(unknown_feature);
}
if diagnostics {
@ -492,10 +489,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
features.extend(feats);
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
sess.err(&format!(
"target features {} must all be enabled or disabled together",
f.join(", ")
));
sess.emit_err(TargetFeatureDisableOrEnable {
features: f,
span: None,
missing_features: None,
});
}
features

View File

@ -1,6 +1,7 @@
use crate::attributes;
use crate::base;
use crate::context::CodegenCx;
use crate::errors::SymbolAlreadyDefined;
use crate::llvm;
use crate::type_of::LayoutLlvmExt;
use rustc_codegen_ssa::traits::*;
@ -25,10 +26,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
let llty = self.layout_of(ty).llvm_type(self);
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
self.sess().span_fatal(
self.tcx.def_span(def_id),
&format!("symbol `{}` is already defined", symbol_name),
)
self.sess()
.emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name })
});
unsafe {

View File

@ -15,10 +15,8 @@ use rustc_data_structures::profiling::TimingGuard;
use rustc_data_structures::profiling::VerboseTimingGuard;
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::Emitter;
use rustc_errors::{
translation::{to_fluent_args, Translate},
DiagnosticId, FatalError, Handler, Level,
};
use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
use rustc_errors::{DiagnosticMessage, Style};
use rustc_fs_util::link_or_copy;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_incremental::{
@ -38,6 +36,7 @@ use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
use rustc_target::spec::{MergeFunctions, SanitizerSet};
use std::any::Any;
use std::borrow::Cow;
use std::fs;
use std::io;
use std::marker::PhantomData;
@ -969,8 +968,11 @@ pub enum Message<B: WriteBackendMethods> {
CodegenAborted,
}
type DiagnosticArgName<'source> = Cow<'source, str>;
struct Diagnostic {
msg: String,
msg: Vec<(DiagnosticMessage, Style)>,
args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
code: Option<DiagnosticId>,
lvl: Level,
}
@ -1743,15 +1745,18 @@ impl Translate for SharedEmitter {
impl Emitter for SharedEmitter {
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
let fluent_args = to_fluent_args(diag.args());
let args: FxHashMap<Cow<'_, str>, rustc_errors::DiagnosticArgValue<'_>> =
diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
msg: self.translate_messages(&diag.message, &fluent_args).to_string(),
msg: diag.message.clone(),
args: args.clone(),
code: diag.code.clone(),
lvl: diag.level(),
})));
for child in &diag.children {
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
msg: self.translate_messages(&child.message, &fluent_args).to_string(),
msg: child.message.clone(),
args: args.clone(),
code: None,
lvl: child.level,
})));
@ -1782,10 +1787,11 @@ impl SharedEmitterMain {
match message {
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
let handler = sess.diagnostic();
let mut d = rustc_errors::Diagnostic::new(diag.lvl, &diag.msg);
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg);
if let Some(code) = diag.code {
d.code(code);
}
d.replace_args(diag.args);
handler.emit_diagnostic(&mut d);
}
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {

View File

@ -6,6 +6,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(once_cell)]
#![feature(decl_macro)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
@ -753,20 +754,41 @@ fn print_crate_info(
}
/// Prints version information
pub fn version(binary: &str, matches: &getopts::Matches) {
let verbose = matches.opt_present("verbose");
println!("{} {}", binary, util::version_str().unwrap_or("unknown version"));
if verbose {
///
/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
pub macro version($binary: literal, $matches: expr) {
fn unw(x: Option<&str>) -> &str {
x.unwrap_or("unknown")
}
$crate::version_at_macro_invocation(
$binary,
$matches,
unw(option_env!("CFG_VERSION")),
unw(option_env!("CFG_VER_HASH")),
unw(option_env!("CFG_VER_DATE")),
unw(option_env!("CFG_RELEASE")),
)
}
#[doc(hidden)] // use the macro instead
pub fn version_at_macro_invocation(
binary: &str,
matches: &getopts::Matches,
version: &str,
commit_hash: &str,
commit_date: &str,
release: &str,
) {
let verbose = matches.opt_present("verbose");
println!("{} {}", binary, version);
if verbose {
println!("binary: {}", binary);
println!("commit-hash: {}", unw(util::commit_hash_str()));
println!("commit-date: {}", unw(util::commit_date_str()));
println!("commit-hash: {}", commit_hash);
println!("commit-date: {}", commit_date);
println!("host: {}", config::host_triple());
println!("release: {}", unw(util::release_str()));
println!("release: {}", release);
let debug_flags = matches.opt_strs("Z");
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
@ -1082,7 +1104,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
}
if matches.opt_present("version") {
version("rustc", &matches);
version!("rustc", &matches);
return None;
}
@ -1227,7 +1249,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
format!("we would appreciate a bug report: {}", bug_report_url).into(),
format!(
"rustc {} running on {}",
util::version_str().unwrap_or("unknown_version"),
util::version_str!().unwrap_or("unknown_version"),
config::host_triple()
)
.into(),

View File

@ -0,0 +1,58 @@
codegen_llvm_unknown_ctarget_feature =
unknown feature specified for `-Ctarget-feature`: `{$feature}`
.note = it is still passed through to the codegen backend
.possible_feature = you might have meant: `{$rust_feature}`
.consider_filing_feature_request = consider filing a feature request
codegen_llvm_unknown_ctarget_feature_prefix =
unknown feature specified for `-Ctarget-feature`: `{$feature}`
.note = features must begin with a `+` to enable or `-` to disable it
codegen_llvm_error_creating_import_library =
Error creating import library for {$lib_name}: {$error}
codegen_llvm_instrument_coverage_requires_llvm_12 =
rustc option `-C instrument-coverage` requires LLVM 12 or higher.
codegen_llvm_symbol_already_defined =
symbol `{$symbol_name}` is already defined
codegen_llvm_branch_protection_requires_aarch64 =
-Zbranch-protection is only supported on aarch64
codegen_llvm_invalid_minimum_alignment =
invalid minimum global alignment: {$err}
codegen_llvm_linkage_const_or_mut_type =
must have type `*const T` or `*mut T` due to `#[linkage]` attribute
codegen_llvm_sanitizer_memtag_requires_mte =
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
codegen_llvm_archive_build_failure =
failed to build archive: {$error}
codegen_llvm_error_writing_def_file =
Error writing .DEF file: {$error}
codegen_llvm_error_calling_dlltool =
Error calling dlltool: {$error}
codegen_llvm_dlltool_fail_import_library =
Dlltool could not create import library: {$stdout}\n{$stderr}
codegen_llvm_unknown_archive_kind =
Don't know how to build archive of type: {$kind}
codegen_llvm_target_feature_disable_or_enable =
the target features {$features} must all be either enabled or disabled together
codegen_llvm_missing_features =
add the missing features in a `target_feature` attribute
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 =
failed to parse target machine config to target machine: {$error}

View File

@ -42,6 +42,7 @@ fluent_messages! {
borrowck => "../locales/en-US/borrowck.ftl",
builtin_macros => "../locales/en-US/builtin_macros.ftl",
codegen_gcc => "../locales/en-US/codegen_gcc.ftl",
codegen_llvm => "../locales/en-US/codegen_llvm.ftl",
codegen_ssa => "../locales/en-US/codegen_ssa.ftl",
compiletest => "../locales/en-US/compiletest.ftl",
const_eval => "../locales/en-US/const_eval.ftl",

View File

@ -44,6 +44,15 @@ pub trait IntoDiagnosticArg {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>;
}
impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
match self {
DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())),
DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n),
}
}
}
impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
fn into(self) -> FluentValue<'source> {
match self {
@ -204,6 +213,22 @@ impl Diagnostic {
Diagnostic::new_with_code(level, None, message)
}
#[track_caller]
pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self {
Diagnostic {
level,
message: messages,
code: None,
span: MultiSpan::new(),
children: vec![],
suggestions: Ok(vec![]),
args: Default::default(),
sort_span: DUMMY_SP,
is_lint: false,
emitted_at: DiagnosticLocation::caller(),
}
}
#[track_caller]
pub fn new_with_code<M: Into<DiagnosticMessage>>(
level: Level,
@ -931,6 +956,13 @@ impl Diagnostic {
self
}
pub fn replace_args(
&mut self,
args: FxHashMap<DiagnosticArgName<'static>, DiagnosticArgValue<'static>>,
) {
self.args = args;
}
pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] {
&self.message
}

View File

@ -107,6 +107,12 @@ impl IntoDiagnosticArg for String {
}
}
impl<'a> IntoDiagnosticArg for Cow<'a, str> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Owned(self.into_owned()))
}
}
impl<'a> IntoDiagnosticArg for &'a Path {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))

View File

@ -152,6 +152,8 @@ declare_features! (
(active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
/// Allows identifying the `compiler_builtins` crate.
(active, compiler_builtins, "1.13.0", None, None),
/// Allows writing custom MIR
(active, custom_mir, "1.65.0", None, None),
/// Outputs useful `assert!` messages
(active, generic_assert, "1.63.0", None, None),
/// Allows using the `rust-intrinsic`'s "ABI".

View File

@ -810,6 +810,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk),
gated!(
custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#),
ErrorFollowing, "the `#[custom_mir]` attribute is just used for the Rust test suite",
),
rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing),

View File

@ -1708,8 +1708,7 @@ fn receiver_is_valid<'tcx>(
return true;
}
let mut autoderef =
Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty, span);
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty);
// The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
if arbitrary_self_types_enabled {

View File

@ -12,18 +12,7 @@ use std::iter;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
}
/// Like `autoderef`, but provides a custom `Span` to use for calls to
/// an overloaded `Deref` operator
pub fn autoderef_overloaded_span(
&'a self,
span: Span,
base_ty: Ty<'tcx>,
overloaded_span: Span,
) -> Autoderef<'a, 'tcx> {
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
}
pub fn try_overloaded_deref(
@ -55,11 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|InferOk { value: method, obligations: o }| {
obligations.extend(o);
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
Some(OverloadedDeref {
region,
mutbl,
span: autoderef.overloaded_span(),
})
Some(OverloadedDeref { region, mutbl, span: autoderef.span() })
} else {
None
}

View File

@ -151,8 +151,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
) -> Ty<'tcx> {
// Commit the autoderefs by calling `autoderef` again, but this
// time writing the results into the various typeck results.
let mut autoderef =
self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span);
let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty);
let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
return self.tcx.ty_error_with_message(
rustc_span::DUMMY_SP,

View File

@ -475,8 +475,7 @@ fn method_autoderef_steps<'tcx>(
let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
let ParamEnvAnd { param_env, value: self_ty } = goal;
let mut autoderef =
Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP)
let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty)
.include_raw_pointers()
.silence_errors();
let mut reached_raw_pointer = false;

View File

@ -19,7 +19,6 @@ use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, DUMMY_SP};
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::traits::{ObligationCause, Pattern};
use ty::VariantDef;
@ -2132,7 +2131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
{
err.help("the semantics of slice patterns changed recently; see issue #62254");
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
} else if self.autoderef(span, expected_ty)
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
&& let (Some(span), true) = (ti.span, ti.origin_expr)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)

View File

@ -1,4 +1,5 @@
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(internal_output_capture)]
#![feature(thread_spawn_unchecked)]
#![feature(once_cell)]

View File

@ -327,7 +327,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
let mut file: Option<PathBuf> = None;
let expected_names = &[
format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")),
format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")),
format!("rustc_codegen_{}", backend_name),
];
for entry in d.filter_map(|e| e.ok()) {
@ -554,22 +554,12 @@ pub fn build_output_filenames(
}
}
/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
pub fn version_str() -> Option<&'static str> {
/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" when invoked by an in-tree tool.
pub macro version_str() {
option_env!("CFG_VERSION")
}
/// Returns a version string such as "0.12.0-dev".
pub fn release_str() -> Option<&'static str> {
option_env!("CFG_RELEASE")
}
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
pub fn commit_hash_str() -> Option<&'static str> {
option_env!("CFG_VER_HASH")
}
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
pub fn commit_date_str() -> Option<&'static str> {
option_env!("CFG_VER_DATE")
/// Returns the version string for `rustc` itself (which may be different from a tool version).
pub fn rustc_version_str() -> Option<&'static str> {
version_str!()
}

View File

@ -138,6 +138,48 @@ impl MirPhase {
}
}
}
/// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
pub fn parse(dialect: String, phase: Option<String>) -> Self {
match &*dialect.to_ascii_lowercase() {
"built" => {
assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR");
MirPhase::Built
}
"analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
"runtime" => Self::Runtime(RuntimePhase::parse(phase)),
_ => panic!("Unknown MIR dialect {}", dialect),
}
}
}
impl AnalysisPhase {
pub fn parse(phase: Option<String>) -> Self {
let Some(phase) = phase else {
return Self::Initial;
};
match &*phase.to_ascii_lowercase() {
"initial" => Self::Initial,
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
_ => panic!("Unknown analysis phase {}", phase),
}
}
}
impl RuntimePhase {
pub fn parse(phase: Option<String>) -> Self {
let Some(phase) = phase else {
return Self::Initial;
};
match &*phase.to_ascii_lowercase() {
"initial" => Self::Initial,
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
"optimized" => Self::Optimized,
_ => panic!("Unknown runtime phase {}", phase),
}
}
}
impl Display for MirPhase {
@ -293,6 +335,13 @@ pub struct Body<'tcx> {
/// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this.
pub is_polymorphic: bool,
/// The phase at which this MIR should be "injected" into the compilation process.
///
/// Everything that comes before this `MirPhase` should be skipped.
///
/// This is only `Some` if the function that this body comes from was annotated with `rustc_custom_mir`.
pub injection_phase: Option<MirPhase>,
pub tainted_by_errors: Option<ErrorGuaranteed>,
}
@ -339,6 +388,7 @@ impl<'tcx> Body<'tcx> {
span,
required_consts: Vec::new(),
is_polymorphic: false,
injection_phase: None,
tainted_by_errors,
};
body.is_polymorphic = body.has_non_region_param();
@ -366,6 +416,7 @@ impl<'tcx> Body<'tcx> {
required_consts: Vec::new(),
var_debug_info: Vec::new(),
is_polymorphic: false,
injection_phase: None,
tainted_by_errors: None,
};
body.is_polymorphic = body.has_non_region_param();
@ -508,6 +559,14 @@ impl<'tcx> Body<'tcx> {
pub fn generator_kind(&self) -> Option<GeneratorKind> {
self.generator.as_ref().map(|generator| generator.generator_kind)
}
#[inline]
pub fn should_skip(&self) -> bool {
let Some(injection_phase) = self.injection_phase else {
return false;
};
injection_phase > self.phase
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]

View File

@ -189,8 +189,8 @@ pub enum LayoutError<'tcx> {
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
}
impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
impl IntoDiagnostic<'_, !> for LayoutError<'_> {
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
let mut diag = handler.struct_fatal("");
match self {
@ -1126,8 +1126,8 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> {
}
}
impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> {
fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> {
impl IntoDiagnostic<'_, !> for FnAbiError<'_> {
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
handler.struct_fatal(self.to_string())
}
}

View File

@ -0,0 +1,155 @@
//! Provides the implementation of the `custom_mir` attribute.
//!
//! Up until MIR building, this attribute has absolutely no effect. The `mir!` macro is a normal
//! decl macro that expands like any other, and the code goes through parsing, name resolution and
//! type checking like all other code. In MIR building we finally detect whether this attribute is
//! present, and if so we branch off into this module, which implements the attribute by
//! implementing a custom lowering from THIR to MIR.
//!
//! The result of this lowering is returned "normally" from the `mir_built` query, with the only
//! notable difference being that the `injected` field in the body is set. Various components of the
//! MIR pipeline, like borrowck and the pass manager will then consult this field (via
//! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user
//! specified.
//!
//! This file defines the general framework for the custom parsing. The parsing for all the
//! "top-level" constructs can be found in the `parse` submodule, while the parsing for statements,
//! terminators, and everything below can be found in the `parse::instruction` submodule.
//!
use rustc_ast::Attribute;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_index::vec::IndexVec;
use rustc_middle::{
mir::*,
thir::*,
ty::{Ty, TyCtxt},
};
use rustc_span::Span;
mod parse;
pub(super) fn build_custom_mir<'tcx>(
tcx: TyCtxt<'tcx>,
did: DefId,
thir: &Thir<'tcx>,
expr: ExprId,
params: &IndexVec<ParamId, Param<'tcx>>,
return_ty: Ty<'tcx>,
return_ty_span: Span,
span: Span,
attr: &Attribute,
) -> Body<'tcx> {
let mut body = Body {
basic_blocks: BasicBlocks::new(IndexVec::new()),
source: MirSource::item(did),
phase: MirPhase::Built,
source_scopes: IndexVec::new(),
generator: None,
local_decls: LocalDecls::new(),
user_type_annotations: IndexVec::new(),
arg_count: params.len(),
spread_arg: None,
var_debug_info: Vec::new(),
span,
required_consts: Vec::new(),
is_polymorphic: false,
tainted_by_errors: None,
injection_phase: None,
pass_count: 1,
};
body.local_decls.push(LocalDecl::new(return_ty, return_ty_span));
body.basic_blocks_mut().push(BasicBlockData::new(None));
body.source_scopes.push(SourceScopeData {
span,
parent_scope: None,
inlined: None,
inlined_parent_scope: None,
local_data: ClearCrossCrate::Clear,
});
body.injection_phase = Some(parse_attribute(attr));
let mut pctxt = ParseCtxt {
tcx,
thir,
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
body: &mut body,
local_map: FxHashMap::default(),
block_map: FxHashMap::default(),
};
let res = (|| {
pctxt.parse_args(&params)?;
pctxt.parse_body(expr)
})();
if let Err(err) = res {
tcx.sess.diagnostic().span_fatal(
err.span,
format!("Could not parse {}, found: {:?}", err.expected, err.item_description),
)
}
body
}
fn parse_attribute(attr: &Attribute) -> MirPhase {
let meta_items = attr.meta_item_list().unwrap();
let mut dialect: Option<String> = None;
let mut phase: Option<String> = None;
for nested in meta_items {
let name = nested.name_or_empty();
let value = nested.value_str().unwrap().as_str().to_string();
match name.as_str() {
"dialect" => {
assert!(dialect.is_none());
dialect = Some(value);
}
"phase" => {
assert!(phase.is_none());
phase = Some(value);
}
other => {
panic!("Unexpected key {}", other);
}
}
}
let Some(dialect) = dialect else {
assert!(phase.is_none());
return MirPhase::Built;
};
MirPhase::parse(dialect, phase)
}
struct ParseCtxt<'tcx, 'body> {
tcx: TyCtxt<'tcx>,
thir: &'body Thir<'tcx>,
source_info: SourceInfo,
body: &'body mut Body<'tcx>,
local_map: FxHashMap<LocalVarId, Local>,
block_map: FxHashMap<LocalVarId, BasicBlock>,
}
struct ParseError {
span: Span,
item_description: String,
expected: String,
}
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
fn expr_error(&self, expr: ExprId, expected: &'static str) -> ParseError {
let expr = &self.thir[expr];
ParseError {
span: expr.span,
item_description: format!("{:?}", expr.kind),
expected: expected.to_string(),
}
}
}
type PResult<T> = Result<T, ParseError>;

View File

@ -0,0 +1,245 @@
use rustc_index::vec::IndexVec;
use rustc_middle::{mir::*, thir::*, ty::Ty};
use rustc_span::Span;
use super::{PResult, ParseCtxt, ParseError};
mod instruction;
/// Helper macro for parsing custom MIR.
///
/// Example usage looks something like:
/// ```rust,ignore (incomplete example)
/// parse_by_kind!(
/// self, // : &ParseCtxt
/// expr_id, // what you're matching against
/// "assignment", // the thing you're trying to parse
/// @call("mir_assign", args) => { args[0] }, // match invocations of the `mir_assign` special function
/// ExprKind::Assign { lhs, .. } => { lhs }, // match thir assignment expressions
/// // no need for fallthrough case - reasonable error is automatically generated
/// )
/// ```
macro_rules! parse_by_kind {
(
$self:ident,
$expr_id:expr,
$expected:literal,
$(
@call($name:literal, $args:ident) => $call_expr:expr,
)*
$(
$pat:pat => $expr:expr,
)*
) => {{
let expr_id = $self.preparse($expr_id);
let expr = &$self.thir[expr_id];
match &expr.kind {
$(
ExprKind::Call { ty, fun: _, args: $args, .. } if {
match ty.kind() {
ty::FnDef(did, _) => {
$self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did)
}
_ => false,
}
} => $call_expr,
)*
$(
$pat => $expr,
)*
#[allow(unreachable_patterns)]
_ => return Err($self.expr_error(expr_id, $expected))
}
}};
}
pub(crate) use parse_by_kind;
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
/// Expressions should only ever be matched on after preparsing them. This removes extra scopes
/// we don't care about.
fn preparse(&self, expr_id: ExprId) -> ExprId {
let expr = &self.thir[expr_id];
match expr.kind {
ExprKind::Scope { value, .. } => self.preparse(value),
_ => expr_id,
}
}
fn statement_as_expr(&self, stmt_id: StmtId) -> PResult<ExprId> {
match &self.thir[stmt_id].kind {
StmtKind::Expr { expr, .. } => Ok(*expr),
kind @ StmtKind::Let { pattern, .. } => {
return Err(ParseError {
span: pattern.span,
item_description: format!("{:?}", kind),
expected: "expression".to_string(),
});
}
}
}
pub fn parse_args(&mut self, params: &IndexVec<ParamId, Param<'tcx>>) -> PResult<()> {
for param in params.iter() {
let (var, span) = {
let pat = param.pat.as_ref().unwrap();
match &pat.kind {
PatKind::Binding { var, .. } => (*var, pat.span),
_ => {
return Err(ParseError {
span: pat.span,
item_description: format!("{:?}", pat.kind),
expected: "local".to_string(),
});
}
}
};
let decl = LocalDecl::new(param.ty, span);
let local = self.body.local_decls.push(decl);
self.local_map.insert(var, local);
}
Ok(())
}
/// Bodies are of the form:
///
/// ```text
/// {
/// let bb1: BasicBlock;
/// let bb2: BasicBlock;
/// {
/// let RET: _;
/// let local1;
/// let local2;
///
/// {
/// { // entry block
/// statement1;
/// terminator1
/// };
///
/// bb1 = {
/// statement2;
/// terminator2
/// };
///
/// bb2 = {
/// statement3;
/// terminator3
/// }
///
/// RET
/// }
/// }
/// }
/// ```
///
/// This allows us to easily parse the basic blocks declarations, local declarations, and
/// basic block definitions in order.
pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
let body = parse_by_kind!(self, expr_id, "whole body",
ExprKind::Block { block } => self.thir[*block].expr.unwrap(),
);
let (block_decls, rest) = parse_by_kind!(self, body, "body with block decls",
ExprKind::Block { block } => {
let block = &self.thir[*block];
(&block.stmts, block.expr.unwrap())
},
);
self.parse_block_decls(block_decls.iter().copied())?;
let (local_decls, rest) = parse_by_kind!(self, rest, "body with local decls",
ExprKind::Block { block } => {
let block = &self.thir[*block];
(&block.stmts, block.expr.unwrap())
},
);
self.parse_local_decls(local_decls.iter().copied())?;
let block_defs = parse_by_kind!(self, rest, "body with block defs",
ExprKind::Block { block } => &self.thir[*block].stmts,
);
for (i, block_def) in block_defs.iter().enumerate() {
let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?;
self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block;
}
Ok(())
}
fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
for stmt in stmts {
let (var, _, _) = self.parse_let_statement(stmt)?;
let data = BasicBlockData::new(None);
let block = self.body.basic_blocks_mut().push(data);
self.block_map.insert(var, block);
}
Ok(())
}
fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?;
self.local_map.insert(ret_var, Local::from_u32(0));
for stmt in stmts {
let (var, ty, span) = self.parse_let_statement(stmt)?;
let decl = LocalDecl::new(ty, span);
let local = self.body.local_decls.push(decl);
self.local_map.insert(var, local);
}
Ok(())
}
fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
let pattern = match &self.thir[stmt_id].kind {
StmtKind::Let { pattern, .. } => pattern,
StmtKind::Expr { expr, .. } => {
return Err(self.expr_error(*expr, "let statement"));
}
};
self.parse_var(pattern)
}
fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
// Make sure we throw out any `AscribeUserType` we find
loop {
match &pat.kind {
PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)),
PatKind::AscribeUserType { subpattern, .. } => {
pat = subpattern;
}
_ => {
break Err(ParseError {
span: pat.span,
item_description: format!("{:?}", pat.kind),
expected: "local".to_string(),
});
}
}
}
}
fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> {
let block = parse_by_kind!(self, expr_id, "basic block",
ExprKind::Block { block } => &self.thir[*block],
);
let mut data = BasicBlockData::new(None);
for stmt_id in &*block.stmts {
let stmt = self.statement_as_expr(*stmt_id)?;
let statement = self.parse_statement(stmt)?;
data.statements.push(Statement { source_info: self.source_info, kind: statement });
}
let Some(trailing) = block.expr else {
return Err(self.expr_error(expr_id, "terminator"))
};
let terminator = self.parse_terminator(trailing)?;
data.terminator = Some(Terminator { source_info: self.source_info, kind: terminator });
Ok(data)
}
}

View File

@ -0,0 +1,72 @@
use rustc_middle::{mir::*, thir::*, ty};
use super::{parse_by_kind, PResult, ParseCtxt};
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
parse_by_kind!(self, expr_id, "statement",
@call("mir_retag", args) => {
Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
},
@call("mir_retag_raw", args) => {
Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?)))
},
ExprKind::Assign { lhs, rhs } => {
let lhs = self.parse_place(*lhs)?;
let rhs = self.parse_rvalue(*rhs)?;
Ok(StatementKind::Assign(Box::new((lhs, rhs))))
},
)
}
pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
parse_by_kind!(self, expr_id, "terminator",
@call("mir_return", _args) => {
Ok(TerminatorKind::Return)
},
@call("mir_goto", args) => {
Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
},
)
}
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, "rvalue",
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),
ExprKind::AddressOf { mutability, arg } => Ok(
Rvalue::AddressOf(*mutability, self.parse_place(*arg)?)
),
_ => self.parse_operand(expr_id).map(Rvalue::Use),
)
}
fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
parse_by_kind!(self, expr_id, "operand",
@call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move),
_ => self.parse_place(expr_id).map(Operand::Copy),
)
}
fn parse_place(&self, expr_id: ExprId) -> PResult<Place<'tcx>> {
parse_by_kind!(self, expr_id, "place",
ExprKind::Deref { arg } => Ok(
self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx)
),
_ => self.parse_local(expr_id).map(Place::from),
)
}
fn parse_local(&self, expr_id: ExprId) -> PResult<Local> {
parse_by_kind!(self, expr_id, "local",
ExprKind::VarRef { id } => Ok(self.local_map[id]),
)
}
fn parse_block(&self, expr_id: ExprId) -> PResult<BasicBlock> {
parse_by_kind!(self, expr_id, "basic block",
ExprKind::VarRef { id } => Ok(self.block_map[id]),
)
}
}

View File

@ -481,6 +481,22 @@ fn construct_fn<'tcx>(
(None, fn_sig.output())
};
if let Some(custom_mir_attr) =
tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
{
return custom::build_custom_mir(
tcx,
fn_def.did.to_def_id(),
thir,
expr,
arguments,
return_ty,
return_ty_span,
span,
custom_mir_attr,
);
}
let infcx = tcx.infer_ctxt().build();
let mut builder = Builder::new(
thir,
@ -1033,6 +1049,7 @@ pub(crate) fn parse_float_into_scalar(
mod block;
mod cfg;
mod custom;
mod expr;
mod matches;
mod misc;

View File

@ -51,11 +51,17 @@ impl<'tcx> Cx<'tcx> {
trace!(?expr.ty);
// Now apply adjustments, if any.
if self.apply_adjustments {
for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
trace!(?expr, ?adjustment);
let span = expr.span;
expr =
self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
expr = self.apply_adjustment(
hir_expr,
expr,
adjustment,
adjustment_span.unwrap_or(span),
);
}
}
trace!(?expr.ty, "after adjustments");

View File

@ -80,6 +80,9 @@ struct Cx<'tcx> {
/// for the receiver.
adjustment_span: Option<(HirId, Span)>,
/// False to indicate that adjustments should not be applied. Only used for `custom_mir`
apply_adjustments: bool,
/// The `DefId` of the owner of this body.
body_owner: DefId,
}
@ -87,6 +90,8 @@ struct Cx<'tcx> {
impl<'tcx> Cx<'tcx> {
fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
let typeck_results = tcx.typeck_opt_const_arg(def);
let did = def.did;
let hir = tcx.hir();
Cx {
tcx,
thir: Thir::new(),
@ -94,8 +99,12 @@ impl<'tcx> Cx<'tcx> {
region_scope_tree: tcx.region_scope_tree(def.did),
typeck_results,
rvalue_scopes: &typeck_results.rvalue_scopes,
body_owner: def.did.to_def_id(),
body_owner: did.to_def_id(),
adjustment_span: None,
apply_adjustments: hir
.attrs(hir.local_def_id_to_hir_id(did))
.iter()
.all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
}
}

View File

@ -471,6 +471,14 @@ fn unsafety_check_result<'tcx>(
// `mir_built` force this.
let body = &tcx.mir_built(def).borrow();
if body.should_skip() {
return tcx.arena.alloc(UnsafetyCheckResult {
violations: Vec::new(),
used_unsafe_blocks: FxHashSet::default(),
unused_unsafes: Some(Vec::new()),
});
}
let param_env = tcx.param_env(def.did);
let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);

View File

@ -96,22 +96,24 @@ fn run_passes_inner<'tcx>(
phase_change: Option<MirPhase>,
validate_each: bool,
) {
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir;
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip();
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
trace!(?overridden_passes);
if !body.should_skip() {
for pass in passes {
let name = pass.name();
let overridden =
overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| {
let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(
|(_name, polarity)| {
trace!(
pass = %name,
"{} as requested by flag",
if *polarity { "Running" } else { "Not running" },
);
*polarity
});
},
);
if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) {
continue;
}
@ -136,6 +138,7 @@ fn run_passes_inner<'tcx>(
body.pass_count += 1;
}
}
if let Some(new_phase) = phase_change {
if body.phase >= new_phase {

View File

@ -584,6 +584,7 @@ symbols! {
custom_attribute,
custom_derive,
custom_inner_attributes,
custom_mir,
custom_test_frameworks,
d,
d32,

View File

@ -1,26 +1,25 @@
use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let arch = "arm64";
let mut base = super::apple_base::opts("macos", arch, "");
let arch = Arch::Arm64;
let mut base = opts("macos", arch);
base.cpu = "apple-a14".into();
base.max_atomic_width = Some(128);
// FIXME: The leak sanitizer currently fails the tests, see #88132.
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
base.link_env_remove.to_mut().extend(macos_link_env_remove());
Target {
// Clang automatically chooses a more specific target based on
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
// correctly, we do too.
let llvm_target = super::apple_base::macos_llvm_target(arch);
Target {
llvm_target: llvm_target.into(),
llvm_target: macos_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
arch: arch.target_arch(),
options: TargetOptions {
mcount: "\u{1}mcount".into(),
frame_pointer: FramePointer::NonLeaf,

View File

@ -1,19 +1,17 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{ios_llvm_target, opts, Arch};
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::Arm64;
Target {
// Clang automatically chooses a more specific target based on
// IPHONEOS_DEPLOYMENT_TARGET.
// This is required for the target to pick the right
// MACH-O commands, so we do too.
let arch = "arm64";
let llvm_target = super::apple_base::ios_llvm_target(arch);
Target {
llvm_target: llvm_target.into(),
llvm_target: ios_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
@ -30,7 +28,7 @@ pub fn target() -> Target {
darwinpcs\0\
-Os\0"
.into(),
..opts("ios", Arch::Arm64)
..opts("ios", arch)
},
}
}

View File

@ -1,17 +1,18 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, Arch};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
pub fn target() -> Target {
let llvm_target = "arm64-apple-ios14.0-macabi";
let mut base = opts("ios", Arch::Arm64_macabi);
let arch = Arch::Arm64_macabi;
let mut base = opts("ios", arch);
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
Target {
llvm_target: llvm_target.into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12".into(),
max_atomic_width: Some(128),

View File

@ -1,21 +1,17 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
let base = opts("ios", Arch::Arm64_sim);
let arch = Arch::Arm64_sim;
Target {
// Clang automatically chooses a more specific target based on
// IPHONEOS_DEPLOYMENT_TARGET.
// This is required for the simulator target to pick the right
// MACH-O commands, so we do too.
let arch = "arm64";
let llvm_target = super::apple_base::ios_sim_llvm_target(arch);
Target {
llvm_target: llvm_target.into(),
llvm_target: ios_sim_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
@ -32,7 +28,7 @@ pub fn target() -> Target {
darwinpcs\0\
-Os\0"
.into(),
..base
..opts("ios", arch)
},
}
}

View File

@ -1,18 +1,19 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, Arch};
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::Arm64;
Target {
llvm_target: "arm64-apple-tvos".into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
forces_embed_bitcode: true,
frame_pointer: FramePointer::NonLeaf,
..opts("tvos", Arch::Arm64)
..opts("tvos", arch)
},
}
}

View File

@ -1,21 +1,17 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, watchos_sim_llvm_target, Arch};
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
let base = opts("watchos", Arch::Arm64_sim);
let arch = Arch::Arm64_sim;
Target {
// Clang automatically chooses a more specific target based on
// WATCHOS_DEPLOYMENT_TARGET.
// This is required for the simulator target to pick the right
// MACH-O commands, so we do too.
let arch = "arm64";
let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
Target {
llvm_target: llvm_target.into(),
llvm_target: watchos_sim_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
@ -32,7 +28,7 @@ pub fn target() -> Target {
darwinpcs\0\
-Os\0"
.into(),
..base
..opts("watchos", arch)
},
}
}

View File

@ -3,7 +3,88 @@ use std::{borrow::Cow, env};
use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs};
use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, TargetOptions};
fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs {
#[cfg(test)]
#[path = "apple/tests.rs"]
mod tests;
use Arch::*;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
Armv7,
Armv7k,
Armv7s,
Arm64,
Arm64_32,
I386,
I686,
X86_64,
X86_64_sim,
X86_64_macabi,
Arm64_macabi,
Arm64_sim,
}
impl Arch {
pub fn target_name(self) -> &'static str {
match self {
Armv7 => "armv7",
Armv7k => "armv7k",
Armv7s => "armv7s",
Arm64 | Arm64_macabi | Arm64_sim => "arm64",
Arm64_32 => "arm64_32",
I386 => "i386",
I686 => "i686",
X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
}
}
pub fn target_arch(self) -> Cow<'static, str> {
Cow::Borrowed(match self {
Armv7 | Armv7k | Armv7s => "arm",
Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
I386 | I686 => "x86",
X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
})
}
fn target_abi(self) -> &'static str {
match self {
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 => "",
X86_64_macabi | Arm64_macabi => "macabi",
// x86_64-apple-ios is a simulator target, even though it isn't
// declared that way in the target like the other ones...
Arm64_sim | X86_64_sim => "sim",
}
}
fn target_cpu(self) -> &'static str {
match self {
Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
Armv7k => "cortex-a8",
Armv7s => "cortex-a9",
Arm64 => "apple-a7",
Arm64_32 => "apple-s4",
I386 | I686 => "yonah",
X86_64 | X86_64_sim => "core2",
X86_64_macabi => "core2",
Arm64_macabi => "apple-a12",
Arm64_sim => "apple-a12",
}
}
fn link_env_remove(self) -> StaticCow<[StaticCow<str>]> {
match self {
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim
| Arm64_sim => {
cvs!["MACOSX_DEPLOYMENT_TARGET"]
}
X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
}
}
}
fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
let platform_name: StaticCow<str> = match abi {
"sim" => format!("{}-simulator", os).into(),
"macabi" => "mac-catalyst".into(),
@ -19,6 +100,8 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin
}
.into();
let arch = arch.target_name();
let mut args = TargetOptions::link_args(
LinkerFlavor::Darwin(Cc::No, Lld::No),
&["-arch", arch, "-platform_version"],
@ -35,24 +118,29 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin
args
}
pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOptions {
// ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
// Static TLS is only available in macOS 10.7+. If you try to compile for 10.6
// either the linker will complain if it is used or the binary will end up
// segfaulting at runtime when run on 10.6. Rust by default supports macOS
// 10.7+, but there is a standard environment variable,
// MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older
// versions of macOS. For example compiling on 10.10 with
// MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate
// warnings about the usage of ELF TLS.
// warnings about the usage of static TLS.
//
// Here we detect what version is being requested, defaulting to 10.7. ELF
// Here we detect what version is being requested, defaulting to 10.7. Static
// TLS is flagged as enabled if it looks to be supported. The architecture
// only matters for default deployment target which is 11.0 for ARM64 and
// 10.7 for everything else.
let has_thread_local = macos_deployment_target("x86_64") >= (10, 7);
let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7);
let abi = arch.target_abi();
TargetOptions {
abi: abi.into(),
os: os.into(),
cpu: arch.target_cpu().into(),
link_env_remove: arch.link_env_remove(),
vendor: "apple".into(),
linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No),
// macOS has -dead_strip, which doesn't rely on function_sections
@ -103,23 +191,24 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> {
.and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok())
}
fn macos_default_deployment_target(arch: &str) -> (u32, u32) {
if arch == "arm64" { (11, 0) } else { (10, 7) }
fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
// Note: Arm64_sim is not included since macOS has no simulator.
if matches!(arch, Arm64 | Arm64_macabi) { (11, 0) } else { (10, 7) }
}
fn macos_deployment_target(arch: &str) -> (u32, u32) {
fn macos_deployment_target(arch: Arch) -> (u32, u32) {
deployment_target("MACOSX_DEPLOYMENT_TARGET")
.unwrap_or_else(|| macos_default_deployment_target(arch))
}
fn macos_lld_platform_version(arch: &str) -> String {
fn macos_lld_platform_version(arch: Arch) -> String {
let (major, minor) = macos_deployment_target(arch);
format!("{}.{}", major, minor)
}
pub fn macos_llvm_target(arch: &str) -> String {
pub fn macos_llvm_target(arch: Arch) -> String {
let (major, minor) = macos_deployment_target(arch);
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor)
}
pub fn macos_link_env_remove() -> Vec<StaticCow<str>> {
@ -142,7 +231,7 @@ fn ios_deployment_target() -> (u32, u32) {
deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
}
pub fn ios_llvm_target(arch: &str) -> String {
pub fn ios_llvm_target(arch: Arch) -> String {
// Modern iOS tooling extracts information about deployment target
// from LC_BUILD_VERSION. This load command will only be emitted when
// we build with a version specific `llvm_target`, with the version
@ -150,7 +239,7 @@ pub fn ios_llvm_target(arch: &str) -> String {
// to pick it up (since std and core are still built with the fallback
// of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION).
let (major, minor) = ios_deployment_target();
format!("{}-apple-ios{}.{}.0", arch, major, minor)
format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor)
}
fn ios_lld_platform_version() -> String {
@ -158,9 +247,9 @@ fn ios_lld_platform_version() -> String {
format!("{}.{}", major, minor)
}
pub fn ios_sim_llvm_target(arch: &str) -> String {
pub fn ios_sim_llvm_target(arch: Arch) -> String {
let (major, minor) = ios_deployment_target();
format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor)
}
fn tvos_deployment_target() -> (u32, u32) {
@ -181,7 +270,7 @@ fn watchos_lld_platform_version() -> String {
format!("{}.{}", major, minor)
}
pub fn watchos_sim_llvm_target(arch: &str) -> String {
pub fn watchos_sim_llvm_target(arch: Arch) -> String {
let (major, minor) = watchos_deployment_target();
format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor)
format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor)
}

View File

@ -1,81 +0,0 @@
use crate::spec::{cvs, TargetOptions};
use std::borrow::Cow;
#[cfg(test)]
#[path = "apple/tests.rs"]
mod tests;
use Arch::*;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
Armv7,
Armv7k,
Armv7s,
Arm64,
Arm64_32,
I386,
#[allow(dead_code)] // Some targets don't use this enum...
X86_64,
X86_64_sim,
X86_64_macabi,
Arm64_macabi,
Arm64_sim,
}
fn target_arch_name(arch: Arch) -> &'static str {
match arch {
Armv7 => "armv7",
Armv7k => "armv7k",
Armv7s => "armv7s",
Arm64 | Arm64_macabi | Arm64_sim => "arm64",
Arm64_32 => "arm64_32",
I386 => "i386",
X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
}
}
fn target_abi(arch: Arch) -> &'static str {
match arch {
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "",
X86_64_macabi | Arm64_macabi => "macabi",
// x86_64-apple-ios is a simulator target, even though it isn't
// declared that way in the target like the other ones...
Arm64_sim | X86_64_sim => "sim",
}
}
fn target_cpu(arch: Arch) -> &'static str {
match arch {
Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
Armv7k => "cortex-a8",
Armv7s => "cortex-a9",
Arm64 => "apple-a7",
Arm64_32 => "apple-s4",
I386 => "yonah",
X86_64 | X86_64_sim => "core2",
X86_64_macabi => "core2",
Arm64_macabi => "apple-a12",
Arm64_sim => "apple-a12",
}
}
fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> {
match arch {
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | X86_64_sim | Arm64_sim => {
cvs!["MACOSX_DEPLOYMENT_TARGET"]
}
X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
}
}
pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
let abi = target_abi(arch);
TargetOptions {
abi: abi.into(),
cpu: target_cpu(arch).into(),
link_env_remove: link_env_remove(arch),
has_thread_local: false,
..super::apple_base::opts(os, target_arch_name(arch), abi)
}
}

View File

@ -1,4 +1,4 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, Arch};
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {

View File

@ -1,18 +1,21 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{ios_llvm_target, opts, Arch};
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
let llvm_target = super::apple_base::ios_llvm_target("armv7");
let arch = Arch::Armv7;
Target {
llvm_target: llvm_target.into(),
// Clang automatically chooses a more specific target based on
// IPHONEOS_DEPLOYMENT_TARGET.
// This is required for the target to pick the right
// MACH-O commands, so we do too.
llvm_target: ios_llvm_target(arch).into(),
pointer_width: 32,
data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
arch: "arm".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+v7,+vfp3,+neon".into(),
max_atomic_width: Some(64),
..opts("ios", Arch::Armv7)
..opts("ios", arch)
},
}
}

View File

@ -1,13 +1,13 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, Arch};
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
let base = opts("watchos", Arch::Armv7k);
let arch = Arch::Armv7k;
Target {
llvm_target: "armv7k-apple-watchos".into(),
pointer_width: 32,
data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
arch: "arm".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+v7,+vfp4,+neon".into(),
max_atomic_width: Some(64),
@ -22,7 +22,7 @@ pub fn target() -> Target {
darwinpcs\0\
-Os\0"
.into(),
..base
..opts("watchos", arch)
},
}
}

View File

@ -1,16 +1,17 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, Arch};
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::Armv7s;
Target {
llvm_target: "armv7s-apple-ios".into(),
pointer_width: 32,
data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
arch: "arm".into(),
arch: arch.target_arch(),
options: TargetOptions {
features: "+v7,+vfp4,+neon".into(),
max_atomic_width: Some(64),
..opts("ios", Arch::Armv7s)
..opts("ios", arch)
},
}
}

View File

@ -1,21 +1,23 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let base = opts("ios", Arch::I386);
let llvm_target = super::apple_base::ios_sim_llvm_target("i386");
let arch = Arch::I386;
Target {
llvm_target: llvm_target.into(),
// Clang automatically chooses a more specific target based on
// IPHONEOS_DEPLOYMENT_TARGET.
// This is required for the target to pick the right
// MACH-O commands, so we do too.
llvm_target: ios_sim_llvm_target(arch).into(),
pointer_width: 32,
data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
f64:32:64-f80:128-n8:16:32-S128"
.into(),
arch: "x86".into(),
arch: arch.target_arch(),
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: StackProbeType::X86,
..base
..opts("ios", arch)
},
}
}

View File

@ -1,28 +1,28 @@
use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
// ld64 only understand i386 and not i686
let mut base = super::apple_base::opts("macos", "i386", "");
base.cpu = "yonah".into();
// ld64 only understands i386 and not i686
let arch = Arch::I386;
let mut base = opts("macos", arch);
base.max_atomic_width = Some(64);
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
base.link_env_remove.to_mut().extend(macos_link_env_remove());
base.stack_probes = StackProbeType::X86;
base.frame_pointer = FramePointer::Always;
Target {
// Clang automatically chooses a more specific target based on
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
// correctly, we do too.
let arch = "i686";
let llvm_target = super::apple_base::macos_llvm_target(&arch);
Target {
llvm_target: llvm_target.into(),
//
// While ld64 doesn't understand i686, LLVM does.
llvm_target: macos_llvm_target(Arch::I686).into(),
pointer_width: 32,
data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
f64:32:64-f80:128-n8:16:32-S128"
.into(),
arch: "x86".into(),
arch: arch.target_arch(),
options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
}
}

View File

@ -1,18 +0,0 @@
use crate::spec::TargetOptions;
use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType};
pub fn opts() -> TargetOptions {
TargetOptions {
env: "gnu".into(),
disable_redzone: true,
panic_strategy: PanicStrategy::Abort,
stack_probes: StackProbeType::X86,
frame_pointer: FramePointer::Always,
position_independent_executables: true,
needs_plt: true,
relro_level: RelroLevel::Full,
relocation_model: RelocModel::Static,
..Default::default()
}
}

View File

@ -59,7 +59,6 @@ pub mod crt_objects;
mod android_base;
mod apple_base;
mod apple_sdk_base;
mod avr_gnu_base;
mod bpf_base;
mod dragonfly_base;
@ -71,7 +70,6 @@ mod illumos_base;
mod l4re_base;
mod linux_base;
mod linux_gnu_base;
mod linux_kernel_base;
mod linux_musl_base;
mod linux_uclibc_base;
mod msvc_base;
@ -1003,7 +1001,7 @@ macro_rules! supported_targets {
$(
#[test] // `#[test]`
fn $module() {
tests_impl::test_target(super::$module::target(), $triple);
tests_impl::test_target(super::$module::target());
}
)+
}
@ -1071,8 +1069,6 @@ supported_targets! {
("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
("aarch64-linux-android", aarch64_linux_android),
("x86_64-unknown-none-linuxkernel", x86_64_unknown_none_linuxkernel),
("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
("armv6-unknown-freebsd", armv6_unknown_freebsd),
("armv7-unknown-freebsd", armv7_unknown_freebsd),
@ -1941,8 +1937,10 @@ impl Target {
| PlatformIntrinsic
| Unadjusted
| Cdecl { .. }
| EfiApi
| RustCold => true,
EfiApi => {
["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
}
X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
Aapcs { .. } => "arm" == self.arch,
CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),

View File

@ -2,15 +2,15 @@ use super::super::*;
use std::assert_matches::assert_matches;
// Test target self-consistency and JSON encoding/decoding roundtrip.
pub(super) fn test_target(mut target: Target, triple: &str) {
pub(super) fn test_target(mut target: Target) {
let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j);
target.update_to_cli();
target.check_consistency(triple);
target.check_consistency();
assert_eq!(recycled_target, Ok(target));
}
impl Target {
fn check_consistency(&self, triple: &str) {
fn check_consistency(&self) {
assert_eq!(self.is_like_osx, self.vendor == "apple");
assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos");
assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi");
@ -129,8 +129,7 @@ impl Target {
if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") {
assert_eq!(self.relocation_model, RelocModel::Pic);
}
// PIEs are supported but not enabled by default with linuxkernel target.
if self.position_independent_executables && !triple.ends_with("-linuxkernel") {
if self.position_independent_executables {
assert_eq!(self.relocation_model, RelocModel::Pic);
}
// The UEFI targets do not support dynamic linking but still require PIC (#101377).

View File

@ -1,29 +1,27 @@
use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let arch = "x86_64";
let mut base = super::apple_base::opts("macos", arch, "");
base.cpu = "core2".into();
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
let arch = Arch::X86_64;
let mut base = opts("macos", arch);
base.max_atomic_width = Some(128); // core2 supports cmpxchg16b
base.frame_pointer = FramePointer::Always;
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
base.link_env_remove.to_mut().extend(macos_link_env_remove());
base.stack_probes = StackProbeType::X86;
base.supported_sanitizers =
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
Target {
// Clang automatically chooses a more specific target based on
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
// correctly, we do too.
let llvm_target = super::apple_base::macos_llvm_target(&arch);
Target {
llvm_target: llvm_target.into(),
llvm_target: macos_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
arch: arch.into(),
arch: arch.target_arch(),
options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
}
}

View File

@ -1,20 +1,18 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let base = opts("ios", Arch::X86_64_sim);
let llvm_target = super::apple_base::ios_sim_llvm_target("x86_64");
let arch = Arch::X86_64_sim;
Target {
llvm_target: llvm_target.into(),
llvm_target: ios_sim_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
arch: "x86_64".into(),
arch: arch.target_arch(),
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: StackProbeType::X86,
..base
..opts("ios", arch)
},
}
}

View File

@ -1,10 +1,11 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, Arch};
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let llvm_target = "x86_64-apple-ios13.0-macabi";
let mut base = opts("ios", Arch::X86_64_macabi);
let arch = Arch::X86_64_macabi;
let mut base = opts("ios", arch);
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
Target {
@ -12,7 +13,7 @@ pub fn target() -> Target {
pointer_width: 64,
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
arch: "x86_64".into(),
arch: arch.target_arch(),
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: StackProbeType::X86,

View File

@ -1,17 +1,17 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, Arch};
use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let base = opts("tvos", Arch::X86_64_sim);
let arch = Arch::X86_64_sim;
Target {
llvm_target: "x86_64-apple-tvos".into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(),
arch: "x86_64".into(),
arch: arch.target_arch(),
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: StackProbeType::X86,
..base
..opts("tvos", arch)
},
}
}

View File

@ -1,18 +1,14 @@
use super::apple_sdk_base::{opts, Arch};
use super::apple_base::{opts, watchos_sim_llvm_target, Arch};
use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let base = opts("watchos", Arch::X86_64_sim);
let arch = "x86_64";
let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
let arch = Arch::X86_64_sim;
Target {
llvm_target: llvm_target.into(),
llvm_target: watchos_sim_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
arch: "x86_64".into(),
arch: arch.target_arch(),
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: StackProbeType::X86,
@ -28,7 +24,7 @@ pub fn target() -> Target {
darwinpcs\0\
-Os\0"
.into(),
..base
..opts("watchos", arch)
},
}
}

View File

@ -1,28 +0,0 @@
// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
// generic Linux kernel options.
use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::linux_kernel_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
base.features =
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into();
base.code_model = Some(CodeModel::Kernel);
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
Target {
// FIXME: Some dispute, the linux-on-clang folks think this should use
// "Linux". We disagree because running *on* Linux is nothing like
// running *as" linux, and historically the "os" component as has always
// been used to mean the "on" part.
llvm_target: "x86_64-unknown-none-elf".into(),
pointer_width: 64,
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
arch: "x86_64".into(),
options: base,
}
}

View File

@ -27,7 +27,6 @@ pub struct Autoderef<'a, 'tcx> {
// Meta infos:
infcx: &'a InferCtxt<'tcx>,
span: Span,
overloaded_span: Span,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
@ -99,12 +98,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
body_id: hir::HirId,
span: Span,
base_ty: Ty<'tcx>,
overloaded_span: Span,
) -> Autoderef<'a, 'tcx> {
Autoderef {
infcx,
span,
overloaded_span,
body_id,
param_env,
state: AutoderefSnapshot {
@ -193,10 +190,6 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
self.span
}
pub fn overloaded_span(&self) -> Span {
self.overloaded_span
}
pub fn reached_recursion_limit(&self) -> bool {
self.state.reached_recursion_limit
}

View File

@ -714,7 +714,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligation.cause.body_id,
span,
base_ty,
span,
);
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
// Re-add the `&`

View File

@ -59,6 +59,9 @@ use crate::marker::DiscriminantKind;
use crate::marker::Tuple;
use crate::mem;
#[cfg(not(bootstrap))]
pub mod mir;
// These imports are used for simplifying intra-doc links
#[allow(unused_imports)]
#[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]

View File

@ -0,0 +1,123 @@
//! Rustc internal tooling for hand-writing MIR.
//!
//! If for some reasons you are not writing rustc tests and have found yourself considering using
//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make
//! anything work besides those things which the rustc test suite happened to need. If you make a
//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead
//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir).
//!
//! The documentation for this module describes how to use this feature. If you are interested in
//! hacking on the implementation, most of that documentation lives at
//! `rustc_mir_building/src/build/custom/mod.rs`.
//!
//! Typical usage will look like this:
//!
//! ```rust
//! #![feature(core_intrinsics, custom_mir)]
//!
//! extern crate core;
//! use core::intrinsics::mir::*;
//!
//! #[custom_mir(dialect = "built")]
//! pub fn simple(x: i32) -> i32 {
//! mir!(
//! let temp1: i32;
//! let temp2: _;
//!
//! {
//! temp1 = x;
//! Goto(exit)
//! }
//!
//! exit = {
//! temp2 = Move(temp1);
//! RET = temp2;
//! Return()
//! }
//! )
//! }
//! ```
//!
//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details:
//!
//! - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
//! attribute only works on functions - there is no way to insert custom MIR into the middle of
//! another function.
//! - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here.
//! This will normally be the phase that corresponds to the thing you are trying to test. The
//! phase can be omitted for dialects that have just one.
//! - You should define your function signature like you normally would. Externally, this function
//! can be called like any other function.
//! - Type inference works - you don't have to spell out the type of all of your locals.
//!
//! For now, all statements and terminators are parsed from nested invocations of the special
//! functions provided in this module. We additionally want to (but do not yet) support more
//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not
//! supported yet.
//!
#![unstable(
feature = "custom_mir",
reason = "MIR is an implementation detail and extremely unstable",
issue = "none"
)]
#![allow(unused_variables, non_snake_case, missing_debug_implementations)]
/// Type representing basic blocks.
///
/// All terminators will have this type as a return type. It helps achieve some type safety.
pub struct BasicBlock;
macro_rules! define {
($name:literal, $($sig:tt)*) => {
#[rustc_diagnostic_item = $name]
pub $($sig)* { panic!() }
}
}
define!("mir_return", fn Return() -> BasicBlock);
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
define!("mir_retag", fn Retag<T>(place: T));
define!("mir_retag_raw", fn RetagRaw<T>(place: T));
define!("mir_move", fn Move<T>(place: T) -> T);
/// Convenience macro for generating custom MIR.
///
/// See the module documentation for syntax details. This macro is not magic - it only transforms
/// your MIR into something that is easier to parse in the compiler.
#[rustc_macro_transparency = "transparent"]
pub macro mir {
(
$(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
$entry_block:block
$(
$block_name:ident = $block:block
)*
) => {{
// First, we declare all basic blocks.
$(
let $block_name: ::core::intrinsics::mir::BasicBlock;
)*
{
// Now all locals
#[allow(non_snake_case)]
let RET;
$(
let $local_decl $(: $local_decl_ty)? ;
)*
{
// Finally, the contents of the basic blocks
$entry_block;
$(
$block;
)*
RET
}
}
}}
}

View File

@ -1059,7 +1059,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// 8 | let x: Pin<&mut Foo> = {
/// | - borrow later stored here
/// 9 | let x: Pin<&mut Foo> = pin!(Foo { /* … */ });
/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
/// 10 | x
/// 11 | }; // <- Foo is dropped
/// | - temporary value is freed at the end of this statement

View File

@ -15,7 +15,6 @@ cfg_if::cfg_if! {
target_os = "espidf",
))] {
// These "unix" family members do not have unwinder.
// Note this also matches x86_64-unknown-none-linuxkernel.
} else if #[cfg(any(
unix,
windows,

@ -1 +1 @@
Subproject commit aa5ee485bd6bd80d205da7c82fcdd776f92fdd51
Subproject commit 3f64052c048c6def93b94a2b514ee88bba918744

@ -1 +1 @@
Subproject commit 9c73283775466d22208a0b28afcab44db4c0cc10
Subproject commit 05532356e7a4dbea2330aabb77611f5179493bb8

@ -1 +1 @@
Subproject commit 4ea7c5def38ac81df33a9e48e5637a82a5ac404d
Subproject commit 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d19

@ -1 +1 @@
Subproject commit 03491f33375c5a2a1661c7fa4be671fe95ce1249
Subproject commit 2b15c0abf2bada6e00553814336bc3e2d8399097

@ -1 +1 @@
Subproject commit 51a37ad19a15709d0601afbac6581f5aea6a45da
Subproject commit d0dc6c97a6486f68bac782fff135086eae6d77ec

View File

@ -310,7 +310,6 @@ target | std | host | notes
`x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
`x86_64-unknown-hermit` | ✓ | | HermitCore
`x86_64-unknown-l4re-uclibc` | ? | |
`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules
[`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
`x86_64-uwp-windows-gnu` | ✓ | |
`x86_64-uwp-windows-msvc` | ✓ | |

View File

@ -326,7 +326,7 @@ impl Options {
crate::usage("rustdoc");
return Err(0);
} else if matches.opt_present("version") {
rustc_driver::version("rustdoc", matches);
rustc_driver::version!("rustdoc", matches);
return Err(0);
}

View File

@ -71,7 +71,7 @@ pub(crate) fn render<T: Print, S: Print>(
let mut themes: Vec<String> = style_files.iter().map(|s| s.basename().unwrap()).collect();
themes.sort();
let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
let rustdoc_version = rustc_interface::util::version_str!().unwrap_or("unknown version");
let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
let sidebar = Buffer::html().to_display(sidebar);
PageLayout {

View File

@ -0,0 +1,14 @@
// MIR for `immut_ref` after built
fn immut_ref(_1: &i32) -> &i32 {
let mut _0: &i32; // return place in scope 0 at $DIR/references.rs:+0:30: +0:34
let mut _2: *const i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
bb0: {
_2 = &raw const (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:34
Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:34
_0 = &(*_2); // scope 0 at $DIR/references.rs:+0:1: +0:34
Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:34
return; // scope 0 at $DIR/references.rs:+0:1: +0:34
}
}

View File

@ -0,0 +1,14 @@
// MIR for `mut_ref` after built
fn mut_ref(_1: &mut i32) -> &mut i32 {
let mut _0: &mut i32; // return place in scope 0 at $DIR/references.rs:+0:32: +0:40
let mut _2: *mut i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
bb0: {
_2 = &raw mut (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:40
Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:40
_0 = &mut (*_2); // scope 0 at $DIR/references.rs:+0:1: +0:40
Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:40
return; // scope 0 at $DIR/references.rs:+0:1: +0:40
}
}

View File

@ -0,0 +1,43 @@
#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;
use core::ptr::{addr_of, addr_of_mut};
// EMIT_MIR references.mut_ref.built.after.mir
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub fn mut_ref(x: &mut i32) -> &mut i32 {
mir!(
let t: *mut i32;
{
t = addr_of_mut!(*x);
RetagRaw(t);
RET = &mut *t;
Retag(RET);
Return()
}
)
}
// EMIT_MIR references.immut_ref.built.after.mir
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub fn immut_ref(x: &i32) -> &i32 {
mir!(
let t: *const i32;
{
t = addr_of!(*x);
RetagRaw(t);
RET = & *t;
Retag(RET);
Return()
}
)
}
fn main() {
let mut x = 5;
assert_eq!(*mut_ref(&mut x), 5);
assert_eq!(*immut_ref(&x), 5);
}

View File

@ -0,0 +1,37 @@
#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;
// EMIT_MIR simple_assign.simple.built.after.mir
#[custom_mir(dialect = "built")]
pub fn simple(x: i32) -> i32 {
mir!(
let temp1: i32;
let temp2: _;
{
temp1 = x;
Goto(exit)
}
exit = {
temp2 = Move(temp1);
RET = temp2;
Return()
}
)
}
// EMIT_MIR simple_assign.simple_ref.built.after.mir
#[custom_mir(dialect = "built")]
pub fn simple_ref(x: &mut i32) -> &mut i32 {
mir!({
RET = Move(x);
Return()
})
}
fn main() {
assert_eq!(5, simple(5));
}

View File

@ -0,0 +1,18 @@
// MIR for `simple` after built
fn simple(_1: i32) -> i32 {
let mut _0: i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:26: +0:29
let mut _2: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
let mut _3: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
bb0: {
_2 = _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
goto -> bb1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
}
bb1: {
_3 = move _2; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
_0 = _3; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
}
}

View File

@ -0,0 +1,10 @@
// MIR for `simple_ref` after built
fn simple_ref(_1: &mut i32) -> &mut i32 {
let mut _0: &mut i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:35: +0:43
bb0: {
_0 = move _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43
return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43
}
}

View File

@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let x = defer(&vec!["Goodbye", "world!"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
LL | x.x[0];
| ------ borrow later used here
|

View File

@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
LL | buggy_map.insert(42, &*Box::new(1));
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | buggy_map.insert(43, &*tmp);
| --------------------------- borrow later used here

View File

@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let y = x.as_ref().unwrap_or(&id(5));
| ^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
LL | let _ = &y;
| -- borrow later used here
|

View File

@ -5,7 +5,7 @@ LL | pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
| -- lifetime `'a` defined here
LL | / bar.call((
LL | | &id(()),
| | ^^^^^^ creates a temporary which is freed while still in use
| | ^^^^^^ creates a temporary value which is freed while still in use
LL | | ));
| | -- temporary value is freed at the end of this statement
| |______|

View File

@ -10,7 +10,7 @@ fn main() {
let val: &_ = binding.0;
//~^ ERROR temporary value dropped while borrowed [E0716]
//~| NOTE temporary value is freed at the end of this statement
//~| NOTE creates a temporary which is freed while still in use
//~| NOTE creates a temporary value which is freed while still in use
//~| HELP consider using a `let` binding to create a longer lived value
println!("{}", val);
//~^ borrow later used here

View File

@ -9,7 +9,7 @@ fn main() {
let val: &_ = x.borrow().0;
//~^ ERROR temporary value dropped while borrowed [E0716]
//~| NOTE temporary value is freed at the end of this statement
//~| NOTE creates a temporary which is freed while still in use
//~| NOTE creates a temporary value which is freed while still in use
//~| HELP consider using a `let` binding to create a longer lived value
println!("{}", val);
//~^ borrow later used here

View File

@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let val: &_ = x.borrow().0;
| ^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | println!("{}", val);
| --- borrow later used here

View File

@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let x1 = arg(&AddFlags(1));
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
@ -21,7 +21,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let x2 = AddFlags(1).get();
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
@ -38,7 +38,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let x3 = &*arg(&AddFlags(1));
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
@ -55,7 +55,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let ref x4 = *arg(&AddFlags(1));
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
@ -72,7 +72,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let &ref x5 = arg(&AddFlags(1));
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
@ -89,7 +89,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let x6 = AddFlags(1).get();
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
...
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let StackBox { f: x7 } = StackBox { f: AddFlags(1).get() };
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
| creates a temporary value which is freed while still in use
LL |
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here

View File

@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
LL | let x: &'static usize =
| -------------- type annotation requires that borrow lasts for `'static`
LL | &std::intrinsics::size_of::<i32>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
LL | }
| - temporary value is freed at the end of this statement

View File

@ -10,7 +10,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/dont_promote_unstable_const_fn.rs:17:28
|
LL | let _: &'static u32 = &foo();
| ------------ ^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL | }
@ -20,7 +20,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/dont_promote_unstable_const_fn.rs:21:28
|
LL | let _: &'static u32 = &meh();
| ------------ ^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -31,7 +31,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/dont_promote_unstable_const_fn.rs:22:26
|
LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL |

View File

@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28
|
LL | let _: &'static u32 = &foo();
| ------------ ^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL | let _x: &'static u32 = &foo();
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29
|
LL | let _x: &'static u32 = &foo();
| ------------ ^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL | }

View File

@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/promoted_const_fn_fail.rs:17:27
|
LL | let x: &'static u8 = &(bar() + 1);
| ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use
| ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...

View File

@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/promoted_const_fn_fail_deny_const_err.rs:18:27
|
LL | let x: &'static u8 = &(bar() + 1);
| ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use
| ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...

View File

@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/promoted_raw_ptr_ops.rs:2:29
|
LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/promoted_raw_ptr_ops.rs:4:30
|
LL | let y: &'static usize = &(&1 as *const i32 as usize + 1);
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/promoted_raw_ptr_ops.rs:6:28
|
LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) });
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/promoted_raw_ptr_ops.rs:8:29
|
LL | let a: &'static bool = &(main as fn() == main as fn());
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL |

View File

@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/transmute-const-promotion.rs:4:37
|
LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL |

View File

@ -7,7 +7,7 @@ LL | let x: &'static bool = &unsafe {
| | type annotation requires that borrow lasts for `'static`
LL | | Foo { a: &1 }.b == Foo { a: &2 }.b
LL | | };
| |_____^ creates a temporary which is freed while still in use
| |_____^ creates a temporary value which is freed while still in use
LL | }
| - temporary value is freed at the end of this statement

View File

@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-conversion.rs:2:28
|
LL | let x: &'static i32 = &(5_i32.reverse_bits());
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-conversion.rs:4:28
|
LL | let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-conversion.rs:6:28
|
LL | let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-conversion.rs:8:28
|
LL | let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-conversion.rs:10:29
|
LL | let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-conversion.rs:12:29
|
LL | let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -68,7 +68,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-conversion.rs:14:29
|
LL | let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes());
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL |

View File

@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-overflowing.rs:2:36
|
LL | let x: &'static (i32, bool) = &(5_i32.overflowing_add(3));
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-overflowing.rs:4:36
|
LL | let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3));
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
--> $DIR/const-int-overflowing.rs:6:36
|
LL | let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3));
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL |

Some files were not shown because too many files have changed in this diff Show More