Auto merge of #137371 - matthiaskrgr:rollup-3qkdqar, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #128080 (Specify scope in `out_of_scope_macro_calls` lint) - #135630 (add more `s390x` target features) - #136089 (Reduce `Box::default` stack copies in debug mode) - #137204 (Clarify MIR dialects and phases) - #137299 (Simplify `Postorder` customization.) - #137302 (Use a probe to avoid registering stray region obligations when re-checking drops in MIR typeck) - #137305 (Tweaks in and around `rustc_middle`) - #137313 (Some codegen_llvm cleanups) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
71e06b9c59
44 changed files with 379 additions and 308 deletions
|
@ -226,7 +226,7 @@ fn emit_polonius_mir<'tcx>(
|
||||||
regioncx,
|
regioncx,
|
||||||
closure_region_requirements,
|
closure_region_requirements,
|
||||||
borrow_set,
|
borrow_set,
|
||||||
pass_where.clone(),
|
pass_where,
|
||||||
out,
|
out,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -613,9 +613,14 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||||
// types, so there's no guarantee that it succeeds. We also
|
// types, so there's no guarantee that it succeeds. We also
|
||||||
// can't rely on the the `ErrorGuaranteed` from `fully_perform` here
|
// can't rely on the the `ErrorGuaranteed` from `fully_perform` here
|
||||||
// because it comes from delay_span_bug.
|
// because it comes from delay_span_bug.
|
||||||
let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
|
//
|
||||||
let errors =
|
// Do this inside of a probe because we don't particularly care (or want)
|
||||||
match dropck_outlives::compute_dropck_outlives_with_errors(&ocx, op, span) {
|
// any region side-effects of this operation in our infcx.
|
||||||
|
typeck.infcx.probe(|_| {
|
||||||
|
let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
|
||||||
|
let errors = match dropck_outlives::compute_dropck_outlives_with_errors(
|
||||||
|
&ocx, op, span,
|
||||||
|
) {
|
||||||
Ok(_) => ocx.select_all_or_error(),
|
Ok(_) => ocx.select_all_or_error(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.is_empty() {
|
if e.is_empty() {
|
||||||
|
@ -626,11 +631,12 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
|
typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||||
} else {
|
} else {
|
||||||
span_bug!(span, "Rerunning drop data query produced no error.");
|
span_bug!(span, "Rerunning drop data query produced no error.");
|
||||||
}
|
}
|
||||||
|
});
|
||||||
DropData { dropck_result: Default::default(), region_constraint_data: None }
|
DropData { dropck_result: Default::default(), region_constraint_data: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,8 +362,8 @@ fn fat_lto(
|
||||||
ptr as *const *const libc::c_char,
|
ptr as *const *const libc::c_char,
|
||||||
symbols_below_threshold.len() as libc::size_t,
|
symbols_below_threshold.len() as libc::size_t,
|
||||||
);
|
);
|
||||||
save_temp_bitcode(cgcx, &module, "lto.after-restriction");
|
|
||||||
}
|
}
|
||||||
|
save_temp_bitcode(cgcx, &module, "lto.after-restriction");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(LtoModuleCodegen::Fat(module))
|
Ok(LtoModuleCodegen::Fat(module))
|
||||||
|
|
|
@ -66,9 +66,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
||||||
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
|
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
|
||||||
// existing logic below to set the Storage Class, but it has an
|
// existing logic below to set the Storage Class, but it has an
|
||||||
// exemption for MinGW for backwards compatibility.
|
// exemption for MinGW for backwards compatibility.
|
||||||
unsafe {
|
llvm::set_dllimport_storage_class(llfn);
|
||||||
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
|
||||||
}
|
|
||||||
llfn
|
llfn
|
||||||
} else {
|
} else {
|
||||||
cx.declare_fn(sym, fn_abi, Some(instance))
|
cx.declare_fn(sym, fn_abi, Some(instance))
|
||||||
|
@ -99,65 +97,61 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
||||||
// has been applied to the definition (wherever that definition may be).
|
// has been applied to the definition (wherever that definition may be).
|
||||||
|
|
||||||
llvm::set_linkage(llfn, llvm::Linkage::ExternalLinkage);
|
llvm::set_linkage(llfn, llvm::Linkage::ExternalLinkage);
|
||||||
unsafe {
|
let is_generic = instance.args.non_erasable_generics().next().is_some();
|
||||||
let is_generic = instance.args.non_erasable_generics().next().is_some();
|
|
||||||
|
|
||||||
let is_hidden = if is_generic {
|
let is_hidden = if is_generic {
|
||||||
// This is a monomorphization of a generic function.
|
// This is a monomorphization of a generic function.
|
||||||
if !(cx.tcx.sess.opts.share_generics()
|
if !(cx.tcx.sess.opts.share_generics()
|
||||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||||
== rustc_attr_parsing::InlineAttr::Never)
|
== rustc_attr_parsing::InlineAttr::Never)
|
||||||
{
|
|
||||||
// When not sharing generics, all instances are in the same
|
|
||||||
// crate and have hidden visibility.
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
if let Some(instance_def_id) = instance_def_id.as_local() {
|
|
||||||
// This is a monomorphization of a generic function
|
|
||||||
// defined in the current crate. It is hidden if:
|
|
||||||
// - the definition is unreachable for downstream
|
|
||||||
// crates, or
|
|
||||||
// - the current crate does not re-export generics
|
|
||||||
// (because the crate is a C library or executable)
|
|
||||||
cx.tcx.is_unreachable_local_definition(instance_def_id)
|
|
||||||
|| !cx.tcx.local_crate_exports_generics()
|
|
||||||
} else {
|
|
||||||
// This is a monomorphization of a generic function
|
|
||||||
// defined in an upstream crate. It is hidden if:
|
|
||||||
// - it is instantiated in this crate, and
|
|
||||||
// - the current crate does not re-export generics
|
|
||||||
instance.upstream_monomorphization(tcx).is_none()
|
|
||||||
&& !cx.tcx.local_crate_exports_generics()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This is a non-generic function. It is hidden if:
|
|
||||||
// - it is instantiated in the local crate, and
|
|
||||||
// - it is defined an upstream crate (non-local), or
|
|
||||||
// - it is not reachable
|
|
||||||
cx.tcx.is_codegened_item(instance_def_id)
|
|
||||||
&& (!instance_def_id.is_local()
|
|
||||||
|| !cx.tcx.is_reachable_non_generic(instance_def_id))
|
|
||||||
};
|
|
||||||
if is_hidden {
|
|
||||||
llvm::set_visibility(llfn, llvm::Visibility::Hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
|
||||||
// should use dllimport for functions.
|
|
||||||
if cx.use_dll_storage_attrs
|
|
||||||
&& let Some(library) = tcx.native_library(instance_def_id)
|
|
||||||
&& library.kind.is_dllimport()
|
|
||||||
&& !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
|
|
||||||
{
|
{
|
||||||
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
// When not sharing generics, all instances are in the same
|
||||||
}
|
// crate and have hidden visibility.
|
||||||
|
true
|
||||||
if cx.should_assume_dso_local(llfn, true) {
|
} else {
|
||||||
llvm::LLVMRustSetDSOLocal(llfn, true);
|
if let Some(instance_def_id) = instance_def_id.as_local() {
|
||||||
|
// This is a monomorphization of a generic function
|
||||||
|
// defined in the current crate. It is hidden if:
|
||||||
|
// - the definition is unreachable for downstream
|
||||||
|
// crates, or
|
||||||
|
// - the current crate does not re-export generics
|
||||||
|
// (because the crate is a C library or executable)
|
||||||
|
cx.tcx.is_unreachable_local_definition(instance_def_id)
|
||||||
|
|| !cx.tcx.local_crate_exports_generics()
|
||||||
|
} else {
|
||||||
|
// This is a monomorphization of a generic function
|
||||||
|
// defined in an upstream crate. It is hidden if:
|
||||||
|
// - it is instantiated in this crate, and
|
||||||
|
// - the current crate does not re-export generics
|
||||||
|
instance.upstream_monomorphization(tcx).is_none()
|
||||||
|
&& !cx.tcx.local_crate_exports_generics()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// This is a non-generic function. It is hidden if:
|
||||||
|
// - it is instantiated in the local crate, and
|
||||||
|
// - it is defined an upstream crate (non-local), or
|
||||||
|
// - it is not reachable
|
||||||
|
cx.tcx.is_codegened_item(instance_def_id)
|
||||||
|
&& (!instance_def_id.is_local()
|
||||||
|
|| !cx.tcx.is_reachable_non_generic(instance_def_id))
|
||||||
|
};
|
||||||
|
if is_hidden {
|
||||||
|
llvm::set_visibility(llfn, llvm::Visibility::Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
||||||
|
// should use dllimport for functions.
|
||||||
|
if cx.use_dll_storage_attrs
|
||||||
|
&& let Some(library) = tcx.native_library(instance_def_id)
|
||||||
|
&& library.kind.is_dllimport()
|
||||||
|
&& !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
|
||||||
|
{
|
||||||
|
llvm::set_dllimport_storage_class(llfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.assume_dso_local(llfn, true);
|
||||||
|
|
||||||
llfn
|
llfn
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -336,12 +336,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
llvm::set_thread_local_mode(g, self.tls_model);
|
llvm::set_thread_local_mode(g, self.tls_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dso_local = self.should_assume_dso_local(g, true);
|
let dso_local = self.assume_dso_local(g, true);
|
||||||
if dso_local {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustSetDSOLocal(g, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !def_id.is_local() {
|
if !def_id.is_local() {
|
||||||
let needs_dll_storage_attr = self.use_dll_storage_attrs
|
let needs_dll_storage_attr = self.use_dll_storage_attrs
|
||||||
|
@ -375,9 +370,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
// is actually present in the current crate. We can find out via the
|
// is actually present in the current crate. We can find out via the
|
||||||
// is_codegened_item query.
|
// is_codegened_item query.
|
||||||
if !self.tcx.is_codegened_item(def_id) {
|
if !self.tcx.is_codegened_item(def_id) {
|
||||||
unsafe {
|
llvm::set_dllimport_storage_class(g);
|
||||||
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,9 +380,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
&& library.kind.is_dllimport()
|
&& library.kind.is_dllimport()
|
||||||
{
|
{
|
||||||
// For foreign (native) libs we know the exact storage type to use.
|
// For foreign (native) libs we know the exact storage type to use.
|
||||||
unsafe {
|
llvm::set_dllimport_storage_class(g);
|
||||||
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.instances.borrow_mut().insert(instance, g);
|
self.instances.borrow_mut().insert(instance, g);
|
||||||
|
@ -460,9 +451,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
set_global_alignment(self, g, alloc.align);
|
set_global_alignment(self, g, alloc.align);
|
||||||
llvm::set_initializer(g, v);
|
llvm::set_initializer(g, v);
|
||||||
|
|
||||||
if self.should_assume_dso_local(g, true) {
|
self.assume_dso_local(g, true);
|
||||||
llvm::LLVMRustSetDSOLocal(g, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward the allocation's mutability (picked by the const interner) to LLVM.
|
// Forward the allocation's mutability (picked by the const interner) to LLVM.
|
||||||
if alloc.mutability.is_not() {
|
if alloc.mutability.is_not() {
|
||||||
|
|
|
@ -403,3 +403,15 @@ pub(crate) fn add_module_flag_str(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_dllimport_storage_class<'ll>(v: &'ll Value) {
|
||||||
|
unsafe {
|
||||||
|
LLVMSetDLLStorageClass(v, DLLStorageClass::DllImport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_dso_local<'ll>(v: &'ll Value) {
|
||||||
|
unsafe {
|
||||||
|
LLVMRustSetDSOLocal(v, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,11 +38,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
||||||
|
|
||||||
llvm::set_linkage(g, base::linkage_to_llvm(linkage));
|
llvm::set_linkage(g, base::linkage_to_llvm(linkage));
|
||||||
llvm::set_visibility(g, base::visibility_to_llvm(visibility));
|
llvm::set_visibility(g, base::visibility_to_llvm(visibility));
|
||||||
unsafe {
|
self.assume_dso_local(g, false);
|
||||||
if self.should_assume_dso_local(g, false) {
|
|
||||||
llvm::LLVMRustSetDSOLocal(g, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.instances.borrow_mut().insert(instance, g);
|
self.instances.borrow_mut().insert(instance, g);
|
||||||
}
|
}
|
||||||
|
@ -79,9 +75,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
||||||
|
|
||||||
debug!("predefine_fn: instance = {:?}", instance);
|
debug!("predefine_fn: instance = {:?}", instance);
|
||||||
|
|
||||||
if self.should_assume_dso_local(lldecl, false) {
|
self.assume_dso_local(lldecl, false);
|
||||||
unsafe { llvm::LLVMRustSetDSOLocal(lldecl, true) };
|
|
||||||
}
|
|
||||||
|
|
||||||
self.instances.borrow_mut().insert(instance, lldecl);
|
self.instances.borrow_mut().insert(instance, lldecl);
|
||||||
}
|
}
|
||||||
|
@ -90,11 +84,16 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
||||||
impl CodegenCx<'_, '_> {
|
impl CodegenCx<'_, '_> {
|
||||||
/// Whether a definition or declaration can be assumed to be local to a group of
|
/// Whether a definition or declaration can be assumed to be local to a group of
|
||||||
/// libraries that form a single DSO or executable.
|
/// libraries that form a single DSO or executable.
|
||||||
pub(crate) fn should_assume_dso_local(
|
/// Marks the local as DSO if so.
|
||||||
&self,
|
pub(crate) fn assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool {
|
||||||
llval: &llvm::Value,
|
let assume = self.should_assume_dso_local(llval, is_declaration);
|
||||||
is_declaration: bool,
|
if assume {
|
||||||
) -> bool {
|
llvm::set_dso_local(llval);
|
||||||
|
}
|
||||||
|
assume
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool {
|
||||||
let linkage = llvm::get_linkage(llval);
|
let linkage = llvm::get_linkage(llval);
|
||||||
let visibility = llvm::get_visibility(llval);
|
let visibility = llvm::get_visibility(llval);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ use rustc_middle::bug;
|
||||||
use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
|
use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
|
||||||
use rustc_middle::mir::ConstraintCategory;
|
use rustc_middle::mir::ConstraintCategory;
|
||||||
use rustc_middle::traits::select;
|
use rustc_middle::traits::select;
|
||||||
pub use rustc_middle::ty::IntVarValue;
|
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{
|
use rustc_middle::ty::fold::{
|
||||||
BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions,
|
BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions,
|
||||||
|
@ -950,7 +949,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.borrow();
|
||||||
assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
|
assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
|
||||||
let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved");
|
let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved");
|
||||||
assert!(storage.data.is_empty());
|
assert!(storage.data.is_empty(), "{:#?}", storage.data);
|
||||||
// We clone instead of taking because borrowck still wants to use the
|
// We clone instead of taking because borrowck still wants to use the
|
||||||
// inference context after calling this for diagnostics and the new
|
// inference context after calling this for diagnostics and the new
|
||||||
// trait solver.
|
// trait solver.
|
||||||
|
|
|
@ -630,7 +630,8 @@ lint_opaque_hidden_inferred_bound_sugg = add this bound
|
||||||
lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
|
lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
|
||||||
.suggestion = use pat_param to preserve semantics
|
.suggestion = use pat_param to preserve semantics
|
||||||
|
|
||||||
lint_out_of_scope_macro_calls = cannot find macro `{$path}` in this scope
|
lint_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location}
|
||||||
|
.label = not found from {$location}
|
||||||
.help = import `macro_rules` with `use` to make it callable above its definition
|
.help = import `macro_rules` with `use` to make it callable above its definition
|
||||||
|
|
||||||
lint_overflowing_bin_hex = literal out of range for `{$ty}`
|
lint_overflowing_bin_hex = literal out of range for `{$ty}`
|
||||||
|
|
|
@ -444,8 +444,8 @@ pub(super) fn decorate_lint(
|
||||||
lints::InnerAttributeUnstable::CustomInnerAttribute
|
lints::InnerAttributeUnstable::CustomInnerAttribute
|
||||||
}
|
}
|
||||||
.decorate_lint(diag),
|
.decorate_lint(diag),
|
||||||
BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
|
BuiltinLintDiag::OutOfScopeMacroCalls { span, path, location } => {
|
||||||
lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
|
lints::OutOfScopeMacroCalls { span, path, location }.decorate_lint(diag)
|
||||||
}
|
}
|
||||||
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
|
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
|
||||||
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
|
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
|
||||||
|
|
|
@ -3108,7 +3108,10 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
|
||||||
#[diag(lint_out_of_scope_macro_calls)]
|
#[diag(lint_out_of_scope_macro_calls)]
|
||||||
#[help]
|
#[help]
|
||||||
pub(crate) struct OutOfScopeMacroCalls {
|
pub(crate) struct OutOfScopeMacroCalls {
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
pub location: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
|
|
|
@ -819,7 +819,9 @@ pub enum BuiltinLintDiag {
|
||||||
is_macro: bool,
|
is_macro: bool,
|
||||||
},
|
},
|
||||||
OutOfScopeMacroCalls {
|
OutOfScopeMacroCalls {
|
||||||
|
span: Span,
|
||||||
path: String,
|
path: String,
|
||||||
|
location: String,
|
||||||
},
|
},
|
||||||
UnexpectedBuiltinCfg {
|
UnexpectedBuiltinCfg {
|
||||||
cfg: String,
|
cfg: String,
|
||||||
|
|
|
@ -79,7 +79,7 @@ impl<'tcx> BasicBlocks<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reverse_postorder(&self) -> &[BasicBlock] {
|
pub fn reverse_postorder(&self) -> &[BasicBlock] {
|
||||||
self.cache.reverse_postorder.get_or_init(|| {
|
self.cache.reverse_postorder.get_or_init(|| {
|
||||||
let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, ()).collect();
|
let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, None).collect();
|
||||||
rpo.reverse();
|
rpo.reverse();
|
||||||
rpo
|
rpo
|
||||||
})
|
})
|
||||||
|
|
|
@ -30,7 +30,6 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
pub use self::query::*;
|
pub use self::query::*;
|
||||||
use self::visit::TyContext;
|
|
||||||
use crate::mir::interpret::{AllocRange, Scalar};
|
use crate::mir::interpret::{AllocRange, Scalar};
|
||||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||||
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
|
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
|
||||||
|
@ -98,24 +97,17 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MirPhase {
|
impl MirPhase {
|
||||||
/// Gets the index of the current MirPhase within the set of all `MirPhase`s.
|
/// Gets the (dialect, phase) index of the current `MirPhase`. Both numbers
|
||||||
///
|
/// are 1-indexed.
|
||||||
/// FIXME(JakobDegen): Return a `(usize, usize)` instead.
|
pub fn index(&self) -> (usize, usize) {
|
||||||
pub fn phase_index(&self) -> usize {
|
match *self {
|
||||||
const BUILT_PHASE_COUNT: usize = 1;
|
MirPhase::Built => (1, 1),
|
||||||
const ANALYSIS_PHASE_COUNT: usize = 2;
|
MirPhase::Analysis(analysis_phase) => (2, 1 + analysis_phase as usize),
|
||||||
match self {
|
MirPhase::Runtime(runtime_phase) => (3, 1 + runtime_phase as usize),
|
||||||
MirPhase::Built => 1,
|
|
||||||
MirPhase::Analysis(analysis_phase) => {
|
|
||||||
1 + BUILT_PHASE_COUNT + (*analysis_phase as usize)
|
|
||||||
}
|
|
||||||
MirPhase::Runtime(runtime_phase) => {
|
|
||||||
1 + BUILT_PHASE_COUNT + ANALYSIS_PHASE_COUNT + (*runtime_phase as usize)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
|
/// Parses a `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
|
||||||
pub fn parse(dialect: String, phase: Option<String>) -> Self {
|
pub fn parse(dialect: String, phase: Option<String>) -> Self {
|
||||||
match &*dialect.to_ascii_lowercase() {
|
match &*dialect.to_ascii_lowercase() {
|
||||||
"built" => {
|
"built" => {
|
||||||
|
@ -539,17 +531,6 @@ impl<'tcx> Body<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_for_ty_context(&self, ty_context: TyContext) -> Span {
|
|
||||||
match ty_context {
|
|
||||||
TyContext::UserTy(span) => span,
|
|
||||||
TyContext::ReturnTy(source_info)
|
|
||||||
| TyContext::LocalDecl { source_info, .. }
|
|
||||||
| TyContext::YieldTy(source_info)
|
|
||||||
| TyContext::ResumeTy(source_info) => source_info.span,
|
|
||||||
TyContext::Location(loc) => self.source_info(loc).span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the return type; it always return first element from `local_decls` array.
|
/// Returns the return type; it always return first element from `local_decls` array.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn return_ty(&self) -> Ty<'tcx> {
|
pub fn return_ty(&self) -> Ty<'tcx> {
|
||||||
|
@ -791,7 +772,7 @@ impl<T> ClearCrossCrate<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_crate_local(self) -> T {
|
pub fn unwrap_crate_local(self) -> T {
|
||||||
match self {
|
match self {
|
||||||
ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
|
ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
|
||||||
ClearCrossCrate::Set(v) => v,
|
ClearCrossCrate::Set(v) => v,
|
||||||
|
@ -948,7 +929,7 @@ mod binding_form_impl {
|
||||||
/// involved in borrow_check errors, e.g., explanations of where the
|
/// involved in borrow_check errors, e.g., explanations of where the
|
||||||
/// temporaries come from, when their destructors are run, and/or how
|
/// temporaries come from, when their destructors are run, and/or how
|
||||||
/// one might revise the code to satisfy the borrow checker's rules.
|
/// one might revise the code to satisfy the borrow checker's rules.
|
||||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
|
||||||
pub struct BlockTailInfo {
|
pub struct BlockTailInfo {
|
||||||
/// If `true`, then the value resulting from evaluating this tail
|
/// If `true`, then the value resulting from evaluating this tail
|
||||||
/// expression is ignored by the block's expression context.
|
/// expression is ignored by the block's expression context.
|
||||||
|
@ -972,7 +953,6 @@ pub struct LocalDecl<'tcx> {
|
||||||
/// Temporaries and the return place are always mutable.
|
/// Temporaries and the return place are always mutable.
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
|
|
||||||
// FIXME(matthewjasper) Don't store in this in `Body`
|
|
||||||
pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
|
pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
|
||||||
|
|
||||||
/// The type of this local.
|
/// The type of this local.
|
||||||
|
@ -982,7 +962,6 @@ pub struct LocalDecl<'tcx> {
|
||||||
/// e.g., via `let x: T`, then we carry that type here. The MIR
|
/// e.g., via `let x: T`, then we carry that type here. The MIR
|
||||||
/// borrow checker needs this information since it can affect
|
/// borrow checker needs this information since it can affect
|
||||||
/// region inference.
|
/// region inference.
|
||||||
// FIXME(matthewjasper) Don't store in this in `Body`
|
|
||||||
pub user_ty: Option<Box<UserTypeProjections>>,
|
pub user_ty: Option<Box<UserTypeProjections>>,
|
||||||
|
|
||||||
/// The *syntactic* (i.e., not visibility) source scope the local is defined
|
/// The *syntactic* (i.e., not visibility) source scope the local is defined
|
||||||
|
@ -1090,7 +1069,6 @@ pub enum LocalInfo<'tcx> {
|
||||||
AggregateTemp,
|
AggregateTemp,
|
||||||
/// A temporary created for evaluation of some subexpression of some block's tail expression
|
/// A temporary created for evaluation of some subexpression of some block's tail expression
|
||||||
/// (with no intervening statement context).
|
/// (with no intervening statement context).
|
||||||
// FIXME(matthewjasper) Don't store in this in `Body`
|
|
||||||
BlockTailTemp(BlockTailInfo),
|
BlockTailTemp(BlockTailInfo),
|
||||||
/// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s,
|
/// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s,
|
||||||
/// and subject to Edition 2024 temporary lifetime rules
|
/// and subject to Edition 2024 temporary lifetime rules
|
||||||
|
@ -1105,7 +1083,7 @@ pub enum LocalInfo<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> LocalDecl<'tcx> {
|
impl<'tcx> LocalDecl<'tcx> {
|
||||||
pub fn local_info(&self) -> &LocalInfo<'tcx> {
|
pub fn local_info(&self) -> &LocalInfo<'tcx> {
|
||||||
self.local_info.as_ref().assert_crate_local()
|
self.local_info.as_ref().unwrap_crate_local()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` only if local is a binding that can itself be
|
/// Returns `true` only if local is a binding that can itself be
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) const ALIGN: usize = 40;
|
||||||
|
|
||||||
/// An indication of where we are in the control flow graph. Used for printing
|
/// An indication of where we are in the control flow graph. Used for printing
|
||||||
/// extra information in `dump_mir`
|
/// extra information in `dump_mir`
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum PassWhere {
|
pub enum PassWhere {
|
||||||
/// We have not started dumping the control flow graph, but we are about to.
|
/// We have not started dumping the control flow graph, but we are about to.
|
||||||
BeforeCFG,
|
BeforeCFG,
|
||||||
|
@ -231,7 +231,8 @@ fn dump_path<'tcx>(
|
||||||
let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number {
|
let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number {
|
||||||
String::new()
|
String::new()
|
||||||
} else if pass_num {
|
} else if pass_num {
|
||||||
format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count)
|
let (dialect_index, phase_index) = body.phase.index();
|
||||||
|
format!(".{}-{}-{:03}", dialect_index, phase_index, body.pass_count)
|
||||||
} else {
|
} else {
|
||||||
".-------".to_string()
|
".-------".to_string()
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,68 +23,77 @@ use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex}
|
||||||
|
|
||||||
/// Represents the "flavors" of MIR.
|
/// Represents the "flavors" of MIR.
|
||||||
///
|
///
|
||||||
/// All flavors of MIR use the same data structure, but there are some important differences. These
|
/// The MIR pipeline is structured into a few major dialects, with one or more phases within each
|
||||||
/// differences come in two forms: Dialects and phases.
|
/// dialect. A MIR flavor is identified by a dialect-phase pair. A single `MirPhase` value
|
||||||
|
/// specifies such a pair. All flavors of MIR use the same data structure to represent the program.
|
||||||
///
|
///
|
||||||
/// Dialects represent a stronger distinction than phases. This is because the transitions between
|
/// Different MIR dialects have different semantics. (The differences between dialects are small,
|
||||||
/// dialects are semantic changes, and therefore technically *lowerings* between distinct IRs. In
|
/// but they do exist.) The progression from one MIR dialect to the next is technically a lowering
|
||||||
/// other words, the same [`Body`](crate::mir::Body) might be well-formed for multiple dialects, but
|
/// from one IR to another. In other words, a single well-formed [`Body`](crate::mir::Body) might
|
||||||
/// have different semantic meaning and different behavior at runtime.
|
/// have different semantic meaning and different behavior at runtime in the different dialects.
|
||||||
|
/// The specific differences between dialects are described on the variants below.
|
||||||
///
|
///
|
||||||
/// Each dialect additionally has a number of phases. However, phase changes never involve semantic
|
/// Phases exist only to place restrictions on what language constructs are permitted in
|
||||||
/// changes. If some MIR is well-formed both before and after a phase change, it is also guaranteed
|
/// well-formed MIR, and subsequent phases mostly increase those restrictions. I.e. to convert MIR
|
||||||
/// that it has the same semantic meaning. In this sense, phase changes can only add additional
|
/// from one phase to the next might require removing/replacing certain MIR constructs.
|
||||||
/// restrictions on what MIR is well-formed.
|
|
||||||
///
|
///
|
||||||
/// When adding phases, remember to update [`MirPhase::phase_index`].
|
/// When adding dialects or phases, remember to update [`MirPhase::index`].
|
||||||
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
#[derive(HashStable)]
|
#[derive(HashStable)]
|
||||||
pub enum MirPhase {
|
pub enum MirPhase {
|
||||||
/// The MIR that is generated by MIR building.
|
/// The "built MIR" dialect, as generated by MIR building.
|
||||||
///
|
///
|
||||||
/// The only things that operate on this dialect are unsafeck, the various MIR lints, and const
|
/// The only things that operate on this dialect are unsafeck, the various MIR lints, and const
|
||||||
/// qualifs.
|
/// qualifs.
|
||||||
///
|
///
|
||||||
/// This has no distinct phases.
|
/// This dialect has just the one (implicit) phase, which places few restrictions on what MIR
|
||||||
|
/// constructs are allowed.
|
||||||
Built,
|
Built,
|
||||||
/// The MIR used for most analysis.
|
|
||||||
|
/// The "analysis MIR" dialect, used for borrowck and friends.
|
||||||
///
|
///
|
||||||
/// The only semantic change between analysis and built MIR is constant promotion. In built MIR,
|
/// The only semantic difference between built MIR and analysis MIR relates to constant
|
||||||
/// sequences of statements that would generally be subject to constant promotion are
|
/// promotion. In built MIR, sequences of statements that would generally be subject to
|
||||||
/// semantically constants, while in analysis MIR all constants are explicit.
|
/// constant promotion are semantically constants, while in analysis MIR all constants are
|
||||||
|
/// explicit.
|
||||||
///
|
///
|
||||||
/// The result of const promotion is available from the `mir_promoted` and `promoted_mir` queries.
|
/// The result of const promotion is available from the `mir_promoted` and `promoted_mir`
|
||||||
|
/// queries.
|
||||||
///
|
///
|
||||||
/// This is the version of MIR used by borrowck and friends.
|
/// The phases of this dialect are described in `AnalysisPhase`.
|
||||||
Analysis(AnalysisPhase),
|
Analysis(AnalysisPhase),
|
||||||
/// The MIR used for CTFE, optimizations, and codegen.
|
|
||||||
|
/// The "runtime MIR" dialect, used for CTFE, optimizations, and codegen.
|
||||||
///
|
///
|
||||||
/// The semantic changes that occur in the lowering from analysis to runtime MIR are as follows:
|
/// The semantic differences between analysis MIR and runtime MIR are as follows.
|
||||||
///
|
///
|
||||||
/// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly speaking,
|
/// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly
|
||||||
/// if dataflow analysis determines that the place being dropped is uninitialized, the drop will
|
/// speaking, if dataflow analysis determines that the place being dropped is uninitialized,
|
||||||
/// not be executed. The exact semantics of this aren't written down anywhere, which means they
|
/// the drop will not be executed. The exact semantics of this aren't written down anywhere,
|
||||||
/// are essentially "what drop elaboration does." In runtime MIR, the drops are unconditional;
|
/// which means they are essentially "what drop elaboration does." In runtime MIR, the drops
|
||||||
/// when a `Drop` terminator is reached, if the type has drop glue that drop glue is always
|
/// are unconditional; when a `Drop` terminator is reached, if the type has drop glue that
|
||||||
/// executed. This may be UB if the underlying place is not initialized.
|
/// drop glue is always executed. This may be UB if the underlying place is not initialized.
|
||||||
/// - Packed drops: Places might in general be misaligned - in most cases this is UB, the exception
|
/// - Packed drops: Places might in general be misaligned - in most cases this is UB, the
|
||||||
/// is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be misaligned
|
/// exception is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be
|
||||||
/// for this reason implicitly moves `P` to a temporary before dropping. Runtime MIR has no such
|
/// misaligned for this reason implicitly moves `P` to a temporary before dropping. Runtime
|
||||||
/// rules, and dropping a misaligned place is simply UB.
|
/// MIR has no such rules, and dropping a misaligned place is simply UB.
|
||||||
/// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In runtime
|
/// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In
|
||||||
/// MIR, this is UB.
|
/// runtime MIR, this is UB.
|
||||||
/// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same way
|
/// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same
|
||||||
/// that Rust itself has them. Where exactly these are is generally subject to change, and so we
|
/// way that Rust itself has them. Where exactly these are is generally subject to change,
|
||||||
/// don't document this here. Runtime MIR has most retags explicit (though implicit retags
|
/// and so we don't document this here. Runtime MIR has most retags explicit (though implicit
|
||||||
/// can still occur at `Rvalue::{Ref,AddrOf}`).
|
/// retags can still occur at `Rvalue::{Ref,AddrOf}`).
|
||||||
/// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code has
|
/// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code
|
||||||
/// access to. This occurs in coroutine bodies. Such locals do not behave like other locals,
|
/// has access to. This occurs in coroutine bodies. Such locals do not behave like other
|
||||||
/// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals -
|
/// locals, because they e.g. may be aliased in surprising ways. Runtime MIR has no such
|
||||||
/// all coroutine bodies are lowered and so all places that look like locals really are locals.
|
/// special locals. All coroutine bodies are lowered and so all places that look like locals
|
||||||
|
/// really are locals.
|
||||||
///
|
///
|
||||||
/// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part
|
/// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part
|
||||||
/// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that
|
/// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that
|
||||||
/// transformations which may suppress such errors should not run on analysis MIR.
|
/// transformations that can suppress such errors should not run on analysis MIR.
|
||||||
|
///
|
||||||
|
/// The phases of this dialect are described in `RuntimePhase`.
|
||||||
Runtime(RuntimePhase),
|
Runtime(RuntimePhase),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +120,8 @@ pub enum AnalysisPhase {
|
||||||
/// * [`TerminatorKind::FalseEdge`]
|
/// * [`TerminatorKind::FalseEdge`]
|
||||||
/// * [`StatementKind::FakeRead`]
|
/// * [`StatementKind::FakeRead`]
|
||||||
/// * [`StatementKind::AscribeUserType`]
|
/// * [`StatementKind::AscribeUserType`]
|
||||||
/// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or [`CoverageKind::SpanMarker`]
|
/// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or
|
||||||
|
/// [`CoverageKind::SpanMarker`]
|
||||||
/// * [`Rvalue::Ref`] with `BorrowKind::Fake`
|
/// * [`Rvalue::Ref`] with `BorrowKind::Fake`
|
||||||
/// * [`CastKind::PointerCoercion`] with any of the following:
|
/// * [`CastKind::PointerCoercion`] with any of the following:
|
||||||
/// * [`PointerCoercion::ArrayToPointer`]
|
/// * [`PointerCoercion::ArrayToPointer`]
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl SwitchTargets {
|
||||||
self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
|
self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a new target to the switch. But You cannot add an already present value.
|
/// Adds a new target to the switch. Panics if you add an already present value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add_target(&mut self, value: u128, bb: BasicBlock) {
|
pub fn add_target(&mut self, value: u128, bb: BasicBlock) {
|
||||||
let value = Pu128(value);
|
let value = Pu128(value);
|
||||||
|
|
|
@ -104,23 +104,21 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
|
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
|
||||||
pub struct Postorder<'a, 'tcx, C> {
|
pub struct Postorder<'a, 'tcx> {
|
||||||
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
|
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
|
||||||
visited: DenseBitSet<BasicBlock>,
|
visited: DenseBitSet<BasicBlock>,
|
||||||
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
|
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
|
||||||
root_is_start_block: bool,
|
root_is_start_block: bool,
|
||||||
extra: C,
|
/// A non-empty `extra` allows for a precise calculation of the successors.
|
||||||
|
extra: Option<(TyCtxt<'tcx>, Instance<'tcx>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, C> Postorder<'a, 'tcx, C>
|
impl<'a, 'tcx> Postorder<'a, 'tcx> {
|
||||||
where
|
|
||||||
C: Customization<'tcx>,
|
|
||||||
{
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
|
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
|
||||||
root: BasicBlock,
|
root: BasicBlock,
|
||||||
extra: C,
|
extra: Option<(TyCtxt<'tcx>, Instance<'tcx>)>,
|
||||||
) -> Postorder<'a, 'tcx, C> {
|
) -> Postorder<'a, 'tcx> {
|
||||||
let mut po = Postorder {
|
let mut po = Postorder {
|
||||||
basic_blocks,
|
basic_blocks,
|
||||||
visited: DenseBitSet::new_empty(basic_blocks.len()),
|
visited: DenseBitSet::new_empty(basic_blocks.len()),
|
||||||
|
@ -140,7 +138,11 @@ where
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let data = &self.basic_blocks[bb];
|
let data = &self.basic_blocks[bb];
|
||||||
let successors = C::successors(data, self.extra);
|
let successors = if let Some(extra) = self.extra {
|
||||||
|
data.mono_successors(extra.0, extra.1)
|
||||||
|
} else {
|
||||||
|
data.terminator().successors()
|
||||||
|
};
|
||||||
self.visit_stack.push((bb, successors));
|
self.visit_stack.push((bb, successors));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,10 +200,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, C> Iterator for Postorder<'_, 'tcx, C>
|
impl<'tcx> Iterator for Postorder<'_, 'tcx> {
|
||||||
where
|
|
||||||
C: Customization<'tcx>,
|
|
||||||
{
|
|
||||||
type Item = BasicBlock;
|
type Item = BasicBlock;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<BasicBlock> {
|
fn next(&mut self) -> Option<BasicBlock> {
|
||||||
|
@ -241,32 +240,12 @@ pub fn postorder<'a, 'tcx>(
|
||||||
reverse_postorder(body).rev()
|
reverse_postorder(body).rev()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lets us plug in some additional logic and data into a Postorder traversal. Or not.
|
|
||||||
pub trait Customization<'tcx>: Copy {
|
|
||||||
fn successors<'a>(_: &'a BasicBlockData<'tcx>, _: Self) -> Successors<'a>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Customization<'tcx> for () {
|
|
||||||
fn successors<'a>(data: &'a BasicBlockData<'tcx>, _: ()) -> Successors<'a> {
|
|
||||||
data.terminator().successors()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Customization<'tcx> for (TyCtxt<'tcx>, Instance<'tcx>) {
|
|
||||||
fn successors<'a>(
|
|
||||||
data: &'a BasicBlockData<'tcx>,
|
|
||||||
(tcx, instance): (TyCtxt<'tcx>, Instance<'tcx>),
|
|
||||||
) -> Successors<'a> {
|
|
||||||
data.mono_successors(tcx, instance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mono_reachable_reverse_postorder<'a, 'tcx>(
|
pub fn mono_reachable_reverse_postorder<'a, 'tcx>(
|
||||||
body: &'a Body<'tcx>,
|
body: &'a Body<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
) -> Vec<BasicBlock> {
|
) -> Vec<BasicBlock> {
|
||||||
let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, (tcx, instance));
|
let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, Some((tcx, instance)));
|
||||||
let mut items = Vec::with_capacity(body.basic_blocks.len());
|
let mut items = Vec::with_capacity(body.basic_blocks.len());
|
||||||
while let Some(block) = iter.next() {
|
while let Some(block) = iter.next() {
|
||||||
items.push(block);
|
items.push(block);
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub struct ObligationCause<'tcx> {
|
||||||
/// information.
|
/// information.
|
||||||
pub body_id: LocalDefId,
|
pub body_id: LocalDefId,
|
||||||
|
|
||||||
code: InternedObligationCauseCode<'tcx>,
|
code: ObligationCauseCodeHandle<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This custom hash function speeds up hashing for `Obligation` deduplication
|
// This custom hash function speeds up hashing for `Obligation` deduplication
|
||||||
|
@ -97,7 +97,7 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||||
|
|
||||||
pub fn map_code(
|
pub fn map_code(
|
||||||
&mut self,
|
&mut self,
|
||||||
f: impl FnOnce(InternedObligationCauseCode<'tcx>) -> ObligationCauseCode<'tcx>,
|
f: impl FnOnce(ObligationCauseCodeHandle<'tcx>) -> ObligationCauseCode<'tcx>,
|
||||||
) {
|
) {
|
||||||
self.code = f(std::mem::take(&mut self.code)).into();
|
self.code = f(std::mem::take(&mut self.code)).into();
|
||||||
}
|
}
|
||||||
|
@ -152,15 +152,16 @@ pub struct UnifyReceiverContext<'tcx> {
|
||||||
pub args: GenericArgsRef<'tcx>,
|
pub args: GenericArgsRef<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A compact form of `ObligationCauseCode`.
|
||||||
#[derive(Clone, PartialEq, Eq, Default, HashStable)]
|
#[derive(Clone, PartialEq, Eq, Default, HashStable)]
|
||||||
#[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)]
|
#[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)]
|
||||||
pub struct InternedObligationCauseCode<'tcx> {
|
pub struct ObligationCauseCodeHandle<'tcx> {
|
||||||
/// `None` for `ObligationCauseCode::Misc` (a common case, occurs ~60% of
|
/// `None` for `ObligationCauseCode::Misc` (a common case, occurs ~60% of
|
||||||
/// the time). `Some` otherwise.
|
/// the time). `Some` otherwise.
|
||||||
code: Option<Arc<ObligationCauseCode<'tcx>>>,
|
code: Option<Arc<ObligationCauseCode<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> std::fmt::Debug for InternedObligationCauseCode<'tcx> {
|
impl<'tcx> std::fmt::Debug for ObligationCauseCodeHandle<'tcx> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let cause: &ObligationCauseCode<'_> = self;
|
let cause: &ObligationCauseCode<'_> = self;
|
||||||
cause.fmt(f)
|
cause.fmt(f)
|
||||||
|
@ -169,14 +170,14 @@ impl<'tcx> std::fmt::Debug for InternedObligationCauseCode<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> ObligationCauseCode<'tcx> {
|
impl<'tcx> ObligationCauseCode<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn into(self) -> InternedObligationCauseCode<'tcx> {
|
fn into(self) -> ObligationCauseCodeHandle<'tcx> {
|
||||||
InternedObligationCauseCode {
|
ObligationCauseCodeHandle {
|
||||||
code: if let ObligationCauseCode::Misc = self { None } else { Some(Arc::new(self)) },
|
code: if let ObligationCauseCode::Misc = self { None } else { Some(Arc::new(self)) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
|
impl<'tcx> std::ops::Deref for ObligationCauseCodeHandle<'tcx> {
|
||||||
type Target = ObligationCauseCode<'tcx>;
|
type Target = ObligationCauseCode<'tcx>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
@ -305,7 +306,7 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
/// The node of the function call.
|
/// The node of the function call.
|
||||||
call_hir_id: HirId,
|
call_hir_id: HirId,
|
||||||
/// The obligation introduced by this argument.
|
/// The obligation introduced by this argument.
|
||||||
parent_code: InternedObligationCauseCode<'tcx>,
|
parent_code: ObligationCauseCodeHandle<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Error derived when checking an impl item is compatible with
|
/// Error derived when checking an impl item is compatible with
|
||||||
|
@ -390,7 +391,8 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
/// `WellFormed(None)`.
|
/// `WellFormed(None)`.
|
||||||
WellFormed(Option<WellFormedLoc>),
|
WellFormed(Option<WellFormedLoc>),
|
||||||
|
|
||||||
/// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
|
/// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching
|
||||||
|
/// against.
|
||||||
MatchImpl(ObligationCause<'tcx>, DefId),
|
MatchImpl(ObligationCause<'tcx>, DefId),
|
||||||
|
|
||||||
BinOp {
|
BinOp {
|
||||||
|
@ -413,7 +415,7 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
ConstParam(Ty<'tcx>),
|
ConstParam(Ty<'tcx>),
|
||||||
|
|
||||||
/// Obligations emitted during the normalization of a weak type alias.
|
/// Obligations emitted during the normalization of a weak type alias.
|
||||||
TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId),
|
TypeAlias(ObligationCauseCodeHandle<'tcx>, Span, DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a value can be extracted into a const.
|
/// Whether a value can be extracted into a const.
|
||||||
|
@ -514,12 +516,6 @@ impl<'tcx> ObligationCauseCode<'tcx> {
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
rustc_data_structures::static_assert_size!(ObligationCauseCode<'_>, 48);
|
rustc_data_structures::static_assert_size!(ObligationCauseCode<'_>, 48);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
pub enum StatementAsExpression {
|
|
||||||
CorrectType,
|
|
||||||
NeedsBoxing,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||||
#[derive(TypeVisitable, TypeFoldable)]
|
#[derive(TypeVisitable, TypeFoldable)]
|
||||||
pub struct MatchExpressionArmCause<'tcx> {
|
pub struct MatchExpressionArmCause<'tcx> {
|
||||||
|
@ -584,7 +580,7 @@ pub struct DerivedCause<'tcx> {
|
||||||
pub parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
pub parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
|
|
||||||
/// The parent trait had this cause.
|
/// The parent trait had this cause.
|
||||||
pub parent_code: InternedObligationCauseCode<'tcx>,
|
pub parent_code: ObligationCauseCodeHandle<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||||
|
@ -592,9 +588,9 @@ pub struct DerivedCause<'tcx> {
|
||||||
pub struct ImplDerivedCause<'tcx> {
|
pub struct ImplDerivedCause<'tcx> {
|
||||||
pub derived: DerivedCause<'tcx>,
|
pub derived: DerivedCause<'tcx>,
|
||||||
/// The `DefId` of the `impl` that gave rise to the `derived` obligation.
|
/// The `DefId` of the `impl` that gave rise to the `derived` obligation.
|
||||||
/// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
|
/// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic
|
||||||
/// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
|
/// impl, then this will be the `DefId` of that trait alias. Care should therefore be taken to
|
||||||
/// that exceptional case where appropriate.
|
/// handle that exceptional case where appropriate.
|
||||||
pub impl_or_alias_def_id: DefId,
|
pub impl_or_alias_def_id: DefId,
|
||||||
/// The index of the derived predicate in the parent impl's predicates.
|
/// The index of the derived predicate in the parent impl's predicates.
|
||||||
pub impl_def_predicate_index: Option<usize>,
|
pub impl_def_predicate_index: Option<usize>,
|
||||||
|
@ -611,7 +607,7 @@ pub struct DerivedHostCause<'tcx> {
|
||||||
pub parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
pub parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||||
|
|
||||||
/// The parent trait had this cause.
|
/// The parent trait had this cause.
|
||||||
pub parent_code: InternedObligationCauseCode<'tcx>,
|
pub parent_code: ObligationCauseCodeHandle<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||||
|
|
|
@ -75,12 +75,6 @@ pub type CanonicalPredicateGoal<'tcx> =
|
||||||
pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
|
pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
|
||||||
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
|
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
|
||||||
|
|
||||||
pub type CanonicalTypeOpEqGoal<'tcx> =
|
|
||||||
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
|
|
||||||
|
|
||||||
pub type CanonicalTypeOpSubtypeGoal<'tcx> =
|
|
||||||
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
|
|
||||||
|
|
||||||
pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
|
pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
|
||||||
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
|
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
|
||||||
|
|
||||||
|
|
|
@ -331,8 +331,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let expr = &this.thir[expr_id];
|
let expr = &this.thir[expr_id];
|
||||||
let tail_result_is_ignored =
|
let tail_result_is_ignored =
|
||||||
destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
|
destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
|
||||||
this.block_context
|
this.block_context.push(BlockFrame::TailExpr {
|
||||||
.push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });
|
info: BlockTailInfo { tail_result_is_ignored, span: expr.span },
|
||||||
|
});
|
||||||
|
|
||||||
block = this.expr_into_dest(destination, block, expr_id).into_block();
|
block = this.expr_into_dest(destination, block, expr_id).into_block();
|
||||||
let popped = this.block_context.pop();
|
let popped = this.block_context.pop();
|
||||||
|
|
|
@ -142,7 +142,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// Overwrite temp local info if we have something more interesting to record.
|
// Overwrite temp local info if we have something more interesting to record.
|
||||||
if !matches!(local_info, LocalInfo::Boring) {
|
if !matches!(local_info, LocalInfo::Boring) {
|
||||||
let decl_info =
|
let decl_info =
|
||||||
this.local_decls[operand].local_info.as_mut().assert_crate_local();
|
this.local_decls[operand].local_info.as_mut().unwrap_crate_local();
|
||||||
if let LocalInfo::Boring | LocalInfo::BlockTailTemp(_) = **decl_info {
|
if let LocalInfo::Boring | LocalInfo::BlockTailTemp(_) = **decl_info {
|
||||||
**decl_info = local_info;
|
**decl_info = local_info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
_ => LocalInfo::Boring,
|
_ => LocalInfo::Boring,
|
||||||
};
|
};
|
||||||
**local_decl.local_info.as_mut().assert_crate_local() = local_info;
|
**local_decl.local_info.as_mut().unwrap_crate_local() = local_info;
|
||||||
this.local_decls.push(local_decl)
|
this.local_decls.push(local_decl)
|
||||||
};
|
};
|
||||||
debug!(?temp);
|
debug!(?temp);
|
||||||
|
|
|
@ -164,8 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.block_context.push(BlockFrame::TailExpr {
|
this.block_context.push(BlockFrame::TailExpr {
|
||||||
tail_result_is_ignored: true,
|
info: BlockTailInfo { tail_result_is_ignored: true, span: expr.span },
|
||||||
span: expr.span,
|
|
||||||
});
|
});
|
||||||
Some(expr.span)
|
Some(expr.span)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -722,7 +722,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
|
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||||
opt_match_place: Some((ref mut match_place, _)),
|
opt_match_place: Some((ref mut match_place, _)),
|
||||||
..
|
..
|
||||||
})) = **self.local_decls[local].local_info.as_mut().assert_crate_local()
|
})) = **self.local_decls[local].local_info.as_mut().unwrap_crate_local()
|
||||||
{
|
{
|
||||||
*match_place = Some(place);
|
*match_place = Some(place);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -112,16 +112,7 @@ enum BlockFrame {
|
||||||
/// Evaluation is currently within the tail expression of a block.
|
/// Evaluation is currently within the tail expression of a block.
|
||||||
///
|
///
|
||||||
/// Example: `{ STMT_1; STMT_2; EXPR }`
|
/// Example: `{ STMT_1; STMT_2; EXPR }`
|
||||||
TailExpr {
|
TailExpr { info: BlockTailInfo },
|
||||||
/// If true, then the surrounding context of the block ignores
|
|
||||||
/// the result of evaluating the block's tail expression.
|
|
||||||
///
|
|
||||||
/// Example: `let _ = { STMT_1; EXPR };`
|
|
||||||
tail_result_is_ignored: bool,
|
|
||||||
|
|
||||||
/// `Span` of the tail expression.
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Generic mark meaning that the block occurred as a subexpression
|
/// Generic mark meaning that the block occurred as a subexpression
|
||||||
/// where the result might be used.
|
/// where the result might be used.
|
||||||
|
@ -277,9 +268,7 @@ impl BlockContext {
|
||||||
match bf {
|
match bf {
|
||||||
BlockFrame::SubExpr => continue,
|
BlockFrame::SubExpr => continue,
|
||||||
BlockFrame::Statement { .. } => break,
|
BlockFrame::Statement { .. } => break,
|
||||||
&BlockFrame::TailExpr { tail_result_is_ignored, span } => {
|
&BlockFrame::TailExpr { info } => return Some(info),
|
||||||
return Some(BlockTailInfo { tail_result_is_ignored, span });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,9 +291,9 @@ impl BlockContext {
|
||||||
|
|
||||||
// otherwise: use accumulated is_ignored state.
|
// otherwise: use accumulated is_ignored state.
|
||||||
Some(
|
Some(
|
||||||
BlockFrame::TailExpr { tail_result_is_ignored: ignored, .. }
|
BlockFrame::TailExpr { info: BlockTailInfo { tail_result_is_ignored: ign, .. } }
|
||||||
| BlockFrame::Statement { ignores_expr_result: ignored },
|
| BlockFrame::Statement { ignores_expr_result: ign },
|
||||||
) => *ignored,
|
) => *ign,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -967,7 +956,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
} => {
|
} => {
|
||||||
self.local_decls[local].mutability = mutability;
|
self.local_decls[local].mutability = mutability;
|
||||||
self.local_decls[local].source_info.scope = self.source_scope;
|
self.local_decls[local].source_info.scope = self.source_scope;
|
||||||
**self.local_decls[local].local_info.as_mut().assert_crate_local() =
|
**self.local_decls[local].local_info.as_mut().unwrap_crate_local() =
|
||||||
if let Some(kind) = param.self_kind {
|
if let Some(kind) = param.self_kind {
|
||||||
LocalInfo::User(BindingForm::ImplicitSelf(kind))
|
LocalInfo::User(BindingForm::ImplicitSelf(kind))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1032,7 +1021,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let parent_id = self.source_scopes[original_source_scope]
|
let parent_id = self.source_scopes[original_source_scope]
|
||||||
.local_data
|
.local_data
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.assert_crate_local()
|
.unwrap_crate_local()
|
||||||
.lint_root;
|
.lint_root;
|
||||||
self.maybe_new_source_scope(pattern_span, arg_hir_id, parent_id);
|
self.maybe_new_source_scope(pattern_span, arg_hir_id, parent_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -604,7 +604,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let source_scope = self.source_scope;
|
let source_scope = self.source_scope;
|
||||||
if let LintLevel::Explicit(current_hir_id) = lint_level {
|
if let LintLevel::Explicit(current_hir_id) = lint_level {
|
||||||
let parent_id =
|
let parent_id =
|
||||||
self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root;
|
self.source_scopes[source_scope].local_data.as_ref().unwrap_crate_local().lint_root;
|
||||||
self.maybe_new_source_scope(region_scope.1.span, current_hir_id, parent_id);
|
self.maybe_new_source_scope(region_scope.1.span, current_hir_id, parent_id);
|
||||||
}
|
}
|
||||||
self.push_scope(region_scope);
|
self.push_scope(region_scope);
|
||||||
|
@ -992,7 +992,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
lint_root: if let LintLevel::Explicit(lint_root) = lint_level {
|
lint_root: if let LintLevel::Explicit(lint_root) = lint_level {
|
||||||
lint_root
|
lint_root
|
||||||
} else {
|
} else {
|
||||||
self.source_scopes[parent].local_data.as_ref().assert_crate_local().lint_root
|
self.source_scopes[parent].local_data.as_ref().unwrap_crate_local().lint_root
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
self.source_scopes.push(SourceScopeData {
|
self.source_scopes.push(SourceScopeData {
|
||||||
|
|
|
@ -79,7 +79,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
|
||||||
let lint_root = self.body.source_scopes[source_info.scope]
|
let lint_root = self.body.source_scopes[source_info.scope]
|
||||||
.local_data
|
.local_data
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.assert_crate_local()
|
.unwrap_crate_local()
|
||||||
.lint_root;
|
.lint_root;
|
||||||
|
|
||||||
Some((lint_root, source_info.span, self.tcx.def_span(const_item)))
|
Some((lint_root, source_info.span, self.tcx.def_span(const_item)))
|
||||||
|
|
|
@ -945,7 +945,7 @@ fn compute_layout<'tcx>(
|
||||||
let decl = &body.local_decls[local];
|
let decl = &body.local_decls[local];
|
||||||
debug!(?decl);
|
debug!(?decl);
|
||||||
|
|
||||||
// Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
|
// Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared
|
||||||
// the information. This is alright, since `ignore_for_traits` is only relevant when
|
// the information. This is alright, since `ignore_for_traits` is only relevant when
|
||||||
// this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
|
// this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
|
||||||
// default.
|
// default.
|
||||||
|
|
|
@ -85,7 +85,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
|
||||||
let lint_root = body.source_scopes[terminator.source_info.scope]
|
let lint_root = body.source_scopes[terminator.source_info.scope]
|
||||||
.local_data
|
.local_data
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.assert_crate_local()
|
.unwrap_crate_local()
|
||||||
.lint_root;
|
.lint_root;
|
||||||
let span = terminator.source_info.span;
|
let span = terminator.source_info.span;
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
||||||
let lint_root = self.body.source_scopes[source_info.scope]
|
let lint_root = self.body.source_scopes[source_info.scope]
|
||||||
.local_data
|
.local_data
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.assert_crate_local()
|
.unwrap_crate_local()
|
||||||
.lint_root;
|
.lint_root;
|
||||||
// FIXME: use existing printing routines to print the function signature
|
// FIXME: use existing printing routines to print the function signature
|
||||||
let fn_sig = self.tcx.fn_sig(fn_id).instantiate(self.tcx, fn_args);
|
let fn_sig = self.tcx.fn_sig(fn_id).instantiate(self.tcx, fn_args);
|
||||||
|
|
|
@ -158,7 +158,7 @@ impl<'tcx> MirPatch<'tcx> {
|
||||||
let index = self.next_local;
|
let index = self.next_local;
|
||||||
self.next_local += 1;
|
self.next_local += 1;
|
||||||
let mut new_decl = LocalDecl::new(ty, span);
|
let mut new_decl = LocalDecl::new(ty, span);
|
||||||
**new_decl.local_info.as_mut().assert_crate_local() = local_info;
|
**new_decl.local_info.as_mut().unwrap_crate_local() = local_info;
|
||||||
self.new_locals.push(new_decl);
|
self.new_locals.push(new_decl);
|
||||||
Local::new(index)
|
Local::new(index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -857,8 +857,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
),
|
),
|
||||||
path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
|
path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
|
||||||
let mut suggestion = None;
|
let mut suggestion = None;
|
||||||
let (span, label, module) =
|
let (span, label, module, segment) =
|
||||||
if let PathResult::Failed { span, label, module, .. } = path_res {
|
if let PathResult::Failed { span, label, module, segment_name, .. } =
|
||||||
|
path_res
|
||||||
|
{
|
||||||
// try to suggest if it's not a macro, maybe a function
|
// try to suggest if it's not a macro, maybe a function
|
||||||
if let PathResult::NonModule(partial_res) =
|
if let PathResult::NonModule(partial_res) =
|
||||||
self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
|
self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
|
||||||
|
@ -876,7 +878,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(span, label, module)
|
(span, label, module, segment_name)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
path_span,
|
path_span,
|
||||||
|
@ -886,12 +888,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
kind.descr()
|
kind.descr()
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
path.last().map(|segment| segment.ident.name).unwrap(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.report_error(
|
self.report_error(
|
||||||
span,
|
span,
|
||||||
ResolutionError::FailedToResolve {
|
ResolutionError::FailedToResolve {
|
||||||
segment: path.last().map(|segment| segment.ident.name),
|
segment: Some(segment),
|
||||||
label,
|
label,
|
||||||
suggestion,
|
suggestion,
|
||||||
module,
|
module,
|
||||||
|
@ -1067,11 +1070,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
|
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
|
||||||
|
let location = match parent_scope.module.kind {
|
||||||
|
ModuleKind::Def(_, _, name) if name == kw::Empty => {
|
||||||
|
"the crate root".to_string()
|
||||||
|
}
|
||||||
|
ModuleKind::Def(kind, def_id, name) => {
|
||||||
|
format!("{} `{name}`", kind.descr(def_id))
|
||||||
|
}
|
||||||
|
ModuleKind::Block => "this scope".to_string(),
|
||||||
|
};
|
||||||
self.tcx.sess.psess.buffer_lint(
|
self.tcx.sess.psess.buffer_lint(
|
||||||
OUT_OF_SCOPE_MACRO_CALLS,
|
OUT_OF_SCOPE_MACRO_CALLS,
|
||||||
path.span,
|
path.span,
|
||||||
node_id,
|
node_id,
|
||||||
BuiltinLintDiag::OutOfScopeMacroCalls { path: pprust::path_to_string(path) },
|
BuiltinLintDiag::OutOfScopeMacroCalls {
|
||||||
|
span: path.span,
|
||||||
|
path: pprust::path_to_string(path),
|
||||||
|
location,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -611,7 +611,26 @@ static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("backchain", Unstable(sym::s390x_target_feature), &[]),
|
("backchain", Unstable(sym::s390x_target_feature), &[]),
|
||||||
|
("deflate-conversion", Unstable(sym::s390x_target_feature), &[]),
|
||||||
|
("enhanced-sort", Unstable(sym::s390x_target_feature), &[]),
|
||||||
|
("guarded-storage", Unstable(sym::s390x_target_feature), &[]),
|
||||||
|
("high-word", Unstable(sym::s390x_target_feature), &[]),
|
||||||
|
("nnp-assist", Unstable(sym::s390x_target_feature), &["vector"]),
|
||||||
|
("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
|
||||||
("vector", Unstable(sym::s390x_target_feature), &[]),
|
("vector", Unstable(sym::s390x_target_feature), &[]),
|
||||||
|
("vector-enhancements-1", Unstable(sym::s390x_target_feature), &["vector"]),
|
||||||
|
("vector-enhancements-2", Unstable(sym::s390x_target_feature), &["vector-enhancements-1"]),
|
||||||
|
("vector-packed-decimal", Unstable(sym::s390x_target_feature), &["vector"]),
|
||||||
|
(
|
||||||
|
"vector-packed-decimal-enhancement",
|
||||||
|
Unstable(sym::s390x_target_feature),
|
||||||
|
&["vector-packed-decimal"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"vector-packed-decimal-enhancement-2",
|
||||||
|
Unstable(sym::s390x_target_feature),
|
||||||
|
&["vector-packed-decimal-enhancement"],
|
||||||
|
),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -768,7 +787,7 @@ impl Target {
|
||||||
/// the first list contains target features that must be enabled for ABI reasons,
|
/// the first list contains target features that must be enabled for ABI reasons,
|
||||||
/// and the second list contains target feature that must be disabled for ABI reasons.
|
/// and the second list contains target feature that must be disabled for ABI reasons.
|
||||||
///
|
///
|
||||||
/// These features are automatically appended to whatever the target spec sats as default
|
/// These features are automatically appended to whatever the target spec sets as default
|
||||||
/// features for the target.
|
/// features for the target.
|
||||||
///
|
///
|
||||||
/// All features enabled/disabled via `-Ctarget-features` and `#[target_features]` are checked
|
/// All features enabled/disabled via `-Ctarget-features` and `#[target_features]` are checked
|
||||||
|
|
|
@ -10,7 +10,6 @@ use rustc_hir::def::Res;
|
||||||
use rustc_hir::{MatchSource, Node};
|
use rustc_hir::{MatchSource, Node};
|
||||||
use rustc_middle::traits::{
|
use rustc_middle::traits::{
|
||||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||||
StatementAsExpression,
|
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::error::TypeError;
|
use rustc_middle::ty::error::TypeError;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
|
@ -26,8 +25,14 @@ use crate::errors::{
|
||||||
SuggestTuplePatternMany, SuggestTuplePatternOne, TypeErrorAdditionalDiags,
|
SuggestTuplePatternMany, SuggestTuplePatternOne, TypeErrorAdditionalDiags,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
enum StatementAsExpression {
|
||||||
|
CorrectType,
|
||||||
|
NeedsBoxing,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum SuggestAsRefKind {
|
enum SuggestAsRefKind {
|
||||||
Option,
|
Option,
|
||||||
Result,
|
Result,
|
||||||
}
|
}
|
||||||
|
@ -382,7 +387,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn suggest_function_pointers_impl(
|
pub(crate) fn suggest_function_pointers_impl(
|
||||||
&self,
|
&self,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
|
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
|
||||||
|
@ -518,7 +523,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn should_suggest_as_ref_kind(
|
fn should_suggest_as_ref_kind(
|
||||||
&self,
|
&self,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
found: Ty<'tcx>,
|
found: Ty<'tcx>,
|
||||||
|
@ -588,8 +593,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
) -> Option<TypeErrorAdditionalDiags> {
|
) -> Option<TypeErrorAdditionalDiags> {
|
||||||
/// Find the if expression with given span
|
/// Find the if expression with given span
|
||||||
struct IfVisitor {
|
struct IfVisitor {
|
||||||
pub found_if: bool,
|
found_if: bool,
|
||||||
pub err_span: Span,
|
err_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for IfVisitor {
|
impl<'v> Visitor<'v> for IfVisitor {
|
||||||
|
@ -736,7 +741,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
/// Be helpful when the user wrote `{... expr; }` and taking the `;` off
|
/// Be helpful when the user wrote `{... expr; }` and taking the `;` off
|
||||||
/// is enough to fix the error.
|
/// is enough to fix the error.
|
||||||
pub fn could_remove_semicolon(
|
fn could_remove_semicolon(
|
||||||
&self,
|
&self,
|
||||||
blk: &'tcx hir::Block<'tcx>,
|
blk: &'tcx hir::Block<'tcx>,
|
||||||
expected_ty: Ty<'tcx>,
|
expected_ty: Ty<'tcx>,
|
||||||
|
@ -816,7 +821,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
|
|
||||||
/// Suggest returning a local binding with a compatible type if the block
|
/// Suggest returning a local binding with a compatible type if the block
|
||||||
/// has no return expression.
|
/// has no return expression.
|
||||||
pub fn consider_returning_binding_diag(
|
fn consider_returning_binding_diag(
|
||||||
&self,
|
&self,
|
||||||
blk: &'tcx hir::Block<'tcx>,
|
blk: &'tcx hir::Block<'tcx>,
|
||||||
expected_ty: Ty<'tcx>,
|
expected_ty: Ty<'tcx>,
|
||||||
|
|
|
@ -1689,7 +1689,20 @@ impl<T: Default> Default for Box<T> {
|
||||||
/// Creates a `Box<T>`, with the `Default` value for T.
|
/// Creates a `Box<T>`, with the `Default` value for T.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Box::write(Box::new_uninit(), T::default())
|
let mut x: Box<mem::MaybeUninit<T>> = Box::new_uninit();
|
||||||
|
unsafe {
|
||||||
|
// SAFETY: `x` is valid for writing and has the same layout as `T`.
|
||||||
|
// If `T::default()` panics, dropping `x` will just deallocate the Box as `MaybeUninit<T>`
|
||||||
|
// does not have a destructor.
|
||||||
|
//
|
||||||
|
// We use `ptr::write` as `MaybeUninit::write` creates
|
||||||
|
// extra stack copies of `T` in debug mode.
|
||||||
|
//
|
||||||
|
// See https://github.com/rust-lang/rust/issues/136043 for more context.
|
||||||
|
ptr::write(&raw mut *x as *mut T, T::default());
|
||||||
|
// SAFETY: `x` was just initialized above.
|
||||||
|
x.assume_init()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
|
||||||
let node = mir.source_scopes[scope]
|
let node = mir.source_scopes[scope]
|
||||||
.local_data
|
.local_data
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.assert_crate_local()
|
.unwrap_crate_local()
|
||||||
.lint_root;
|
.lint_root;
|
||||||
|
|
||||||
if let Some(snip) = span.get_source_text(cx)
|
if let Some(snip) = span.get_source_text(cx)
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -
|
||||||
locals.len()
|
locals.len()
|
||||||
];
|
];
|
||||||
|
|
||||||
traversal::Postorder::new(&mir.basic_blocks, location.block, ())
|
traversal::Postorder::new(&mir.basic_blocks, location.block, None)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.rev()
|
.rev()
|
||||||
|
|
28
tests/codegen/box-default-debug-copies.rs
Normal file
28
tests/codegen/box-default-debug-copies.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
//@ compile-flags: -Copt-level=0
|
||||||
|
|
||||||
|
// Test to make sure that `<Box<T>>::default` does not create too many copies of `T` on the stack.
|
||||||
|
// in debug mode. This regressed in dd0620b86721ae8cae86736443acd3f72ba6fc32 to
|
||||||
|
// four `T` allocas.
|
||||||
|
//
|
||||||
|
// See https://github.com/rust-lang/rust/issues/136043 for more context.
|
||||||
|
//
|
||||||
|
// FIXME: This test only wants to ensure that there are at most two allocas of `T` created, instead
|
||||||
|
// of checking for exactly two.
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Thing([u8; 1000000]);
|
||||||
|
|
||||||
|
impl Default for Thing {
|
||||||
|
fn default() -> Self {
|
||||||
|
Thing([0; 1000000])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-COUNT-2: %{{.*}} = alloca {{.*}}1000000
|
||||||
|
// CHECK-NOT: %{{.*}} = alloca {{.*}}1000000
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn box_default_single_copy() -> Box<Thing> {
|
||||||
|
Box::default()
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
#![doc = in_root!()] //~ WARN cannot find macro `in_root` in this scope
|
#![doc = in_root!()] //~ WARN cannot find macro `in_root`
|
||||||
//~| WARN this was previously accepted by the compiler
|
//~| WARN this was previously accepted by the compiler
|
||||||
#![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope
|
#![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope
|
||||||
#![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope
|
#![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape`
|
||||||
//~| WARN this was previously accepted by the compiler
|
//~| WARN this was previously accepted by the compiler
|
||||||
#![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope
|
#![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@ fn before() {
|
||||||
|
|
||||||
macro_rules! in_root { () => { "" } }
|
macro_rules! in_root { () => { "" } }
|
||||||
|
|
||||||
#[doc = in_mod!()] //~ WARN cannot find macro `in_mod` in this scope
|
#[doc = in_mod!()] //~ WARN cannot find macro `in_mod`
|
||||||
//~| WARN this was previously accepted by the compiler
|
//~| WARN this was previously accepted by the compiler
|
||||||
mod macros_stay {
|
mod macros_stay {
|
||||||
#![doc = in_mod!()] //~ WARN cannot find macro `in_mod` in this scope
|
#![doc = in_mod!()] //~ WARN cannot find macro `in_mod`
|
||||||
//~| WARN this was previously accepted by the compiler
|
//~| WARN this was previously accepted by the compiler
|
||||||
|
|
||||||
macro_rules! in_mod { () => { "" } }
|
macro_rules! in_mod { () => { "" } }
|
||||||
|
@ -33,10 +33,10 @@ mod macros_stay {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
#[doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope
|
#[doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape`
|
||||||
//~| WARN this was previously accepted by the compiler
|
//~| WARN this was previously accepted by the compiler
|
||||||
mod macros_escape {
|
mod macros_escape {
|
||||||
#![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope
|
#![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape`
|
||||||
//~| WARN this was previously accepted by the compiler
|
//~| WARN this was previously accepted by the compiler
|
||||||
|
|
||||||
macro_rules! in_mod_escape { () => { "" } }
|
macro_rules! in_mod_escape { () => { "" } }
|
||||||
|
|
|
@ -126,62 +126,62 @@ LL | #![doc = in_block!()]
|
||||||
|
|
|
|
||||||
= help: have you added the `#[macro_use]` on the module/import?
|
= help: have you added the `#[macro_use]` on the module/import?
|
||||||
|
|
||||||
warning: cannot find macro `in_root` in this scope
|
warning: cannot find macro `in_root` in the current scope when looking from the crate root
|
||||||
--> $DIR/key-value-expansion-scope.rs:1:10
|
--> $DIR/key-value-expansion-scope.rs:1:10
|
||||||
|
|
|
|
||||||
LL | #![doc = in_root!()]
|
LL | #![doc = in_root!()]
|
||||||
| ^^^^^^^
|
| ^^^^^^^ not found from the crate root
|
||||||
|
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
||||||
= help: import `macro_rules` with `use` to make it callable above its definition
|
= help: import `macro_rules` with `use` to make it callable above its definition
|
||||||
= note: `#[warn(out_of_scope_macro_calls)]` on by default
|
= note: `#[warn(out_of_scope_macro_calls)]` on by default
|
||||||
|
|
||||||
warning: cannot find macro `in_mod_escape` in this scope
|
warning: cannot find macro `in_mod_escape` in the current scope when looking from the crate root
|
||||||
--> $DIR/key-value-expansion-scope.rs:4:10
|
--> $DIR/key-value-expansion-scope.rs:4:10
|
||||||
|
|
|
|
||||||
LL | #![doc = in_mod_escape!()]
|
LL | #![doc = in_mod_escape!()]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^ not found from the crate root
|
||||||
|
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
||||||
= help: import `macro_rules` with `use` to make it callable above its definition
|
= help: import `macro_rules` with `use` to make it callable above its definition
|
||||||
|
|
||||||
warning: cannot find macro `in_mod` in this scope
|
warning: cannot find macro `in_mod` in the current scope when looking from module `macros_stay`
|
||||||
--> $DIR/key-value-expansion-scope.rs:21:9
|
--> $DIR/key-value-expansion-scope.rs:21:9
|
||||||
|
|
|
|
||||||
LL | #[doc = in_mod!()]
|
LL | #[doc = in_mod!()]
|
||||||
| ^^^^^^
|
| ^^^^^^ not found from module `macros_stay`
|
||||||
|
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
||||||
= help: import `macro_rules` with `use` to make it callable above its definition
|
= help: import `macro_rules` with `use` to make it callable above its definition
|
||||||
|
|
||||||
warning: cannot find macro `in_mod` in this scope
|
warning: cannot find macro `in_mod` in the current scope when looking from module `macros_stay`
|
||||||
--> $DIR/key-value-expansion-scope.rs:24:14
|
--> $DIR/key-value-expansion-scope.rs:24:14
|
||||||
|
|
|
|
||||||
LL | #![doc = in_mod!()]
|
LL | #![doc = in_mod!()]
|
||||||
| ^^^^^^
|
| ^^^^^^ not found from module `macros_stay`
|
||||||
|
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
||||||
= help: import `macro_rules` with `use` to make it callable above its definition
|
= help: import `macro_rules` with `use` to make it callable above its definition
|
||||||
|
|
||||||
warning: cannot find macro `in_mod_escape` in this scope
|
warning: cannot find macro `in_mod_escape` in the current scope when looking from module `macros_escape`
|
||||||
--> $DIR/key-value-expansion-scope.rs:36:9
|
--> $DIR/key-value-expansion-scope.rs:36:9
|
||||||
|
|
|
|
||||||
LL | #[doc = in_mod_escape!()]
|
LL | #[doc = in_mod_escape!()]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^ not found from module `macros_escape`
|
||||||
|
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
||||||
= help: import `macro_rules` with `use` to make it callable above its definition
|
= help: import `macro_rules` with `use` to make it callable above its definition
|
||||||
|
|
||||||
warning: cannot find macro `in_mod_escape` in this scope
|
warning: cannot find macro `in_mod_escape` in the current scope when looking from module `macros_escape`
|
||||||
--> $DIR/key-value-expansion-scope.rs:39:14
|
--> $DIR/key-value-expansion-scope.rs:39:14
|
||||||
|
|
|
|
||||||
LL | #![doc = in_mod_escape!()]
|
LL | #![doc = in_mod_escape!()]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^ not found from module `macros_escape`
|
||||||
|
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
= note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
|
||||||
|
|
18
tests/ui/borrowck/bad-drop-side-effects.rs
Normal file
18
tests/ui/borrowck/bad-drop-side-effects.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/137288>.
|
||||||
|
|
||||||
|
trait B {
|
||||||
|
type C;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<U> B for &Missing {
|
||||||
|
//~^ ERROR cannot find type `Missing` in this scope
|
||||||
|
type C = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct E<T: B> {
|
||||||
|
g: <T as B>::C,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn h(i: Box<E<&()>>) {}
|
||||||
|
|
||||||
|
fn main() {}
|
9
tests/ui/borrowck/bad-drop-side-effects.stderr
Normal file
9
tests/ui/borrowck/bad-drop-side-effects.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0412]: cannot find type `Missing` in this scope
|
||||||
|
--> $DIR/bad-drop-side-effects.rs:7:16
|
||||||
|
|
|
||||||
|
LL | impl<U> B for &Missing {
|
||||||
|
| ^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0412`.
|
|
@ -58,6 +58,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
||||||
`cssc`
|
`cssc`
|
||||||
`d`
|
`d`
|
||||||
`d32`
|
`d32`
|
||||||
|
`deflate-conversion`
|
||||||
`dit`
|
`dit`
|
||||||
`doloop`
|
`doloop`
|
||||||
`dotprod`
|
`dotprod`
|
||||||
|
@ -72,6 +73,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
||||||
`ecv`
|
`ecv`
|
||||||
`edsp`
|
`edsp`
|
||||||
`elrw`
|
`elrw`
|
||||||
|
`enhanced-sort`
|
||||||
`ermsb`
|
`ermsb`
|
||||||
`exception-handling`
|
`exception-handling`
|
||||||
`extended-const`
|
`extended-const`
|
||||||
|
@ -109,11 +111,13 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
||||||
`frintts`
|
`frintts`
|
||||||
`fxsr`
|
`fxsr`
|
||||||
`gfni`
|
`gfni`
|
||||||
|
`guarded-storage`
|
||||||
`hard-float`
|
`hard-float`
|
||||||
`hard-float-abi`
|
`hard-float-abi`
|
||||||
`hard-tp`
|
`hard-tp`
|
||||||
`hbc`
|
`hbc`
|
||||||
`high-registers`
|
`high-registers`
|
||||||
|
`high-word`
|
||||||
`hvx`
|
`hvx`
|
||||||
`hvx-length128b`
|
`hvx-length128b`
|
||||||
`hwdiv`
|
`hwdiv`
|
||||||
|
@ -151,6 +155,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
||||||
`multivalue`
|
`multivalue`
|
||||||
`mutable-globals`
|
`mutable-globals`
|
||||||
`neon`
|
`neon`
|
||||||
|
`nnp-assist`
|
||||||
`nontrapping-fptoint`
|
`nontrapping-fptoint`
|
||||||
`nvic`
|
`nvic`
|
||||||
`paca`
|
`paca`
|
||||||
|
@ -229,6 +234,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
||||||
`thumb-mode`
|
`thumb-mode`
|
||||||
`thumb2`
|
`thumb2`
|
||||||
`tme`
|
`tme`
|
||||||
|
`transactional-execution`
|
||||||
`trust`
|
`trust`
|
||||||
`trustzone`
|
`trustzone`
|
||||||
`ual`
|
`ual`
|
||||||
|
@ -262,6 +268,11 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
||||||
`vdspv1`
|
`vdspv1`
|
||||||
`vdspv2`
|
`vdspv2`
|
||||||
`vector`
|
`vector`
|
||||||
|
`vector-enhancements-1`
|
||||||
|
`vector-enhancements-2`
|
||||||
|
`vector-packed-decimal`
|
||||||
|
`vector-packed-decimal-enhancement`
|
||||||
|
`vector-packed-decimal-enhancement-2`
|
||||||
`vfp2`
|
`vfp2`
|
||||||
`vfp3`
|
`vfp3`
|
||||||
`vfp4`
|
`vfp4`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue