mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #144876 - Zalathar:rollup-jhv9rir, r=Zalathar
Rollup of 12 pull requests Successful merges: - rust-lang/rust#142205 (Mark `slice::swap_with_slice` unstably const) - rust-lang/rust#144188 (`available_parallelism`: Add documentation for why we don't look at `ulimit`) - rust-lang/rust#144322 (Add lint against dangling pointers from local variables) - rust-lang/rust#144497 (tests: Add test for basic line-by-line stepping in a debugger) - rust-lang/rust#144559 (Enable extract-insert-dyn.rs test on RISC-V (riscv64)) - rust-lang/rust#144667 (`AlignmentEnum` should just be `repr(usize)` now) - rust-lang/rust#144706 (Do not give function allocations alignment in consteval and Miri.) - rust-lang/rust#144746 (resolve: Cleanups and micro-optimizations to extern prelude) - rust-lang/rust#144785 (Regression test for LLVM error with unsupported expression in static initializer for const pointer in array on macOS.) - rust-lang/rust#144811 (Stylize `*-lynxos178-*` target maintainer handle to make it easier to copy/paste) - rust-lang/rust#144848 (For "stage 1" ui-fulldeps, use the stage 1 compiler to query target info) - rust-lang/rust#144853 (Remove unnecessary `rust_` prefixes) Failed merges: - rust-lang/rust#144794 (Port `#[coroutine]` to the new attribute system) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -4519,6 +4519,7 @@ name = "rustc_resolve"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"indexmap",
|
||||
"itertools",
|
||||
"pulldown-cmark",
|
||||
"rustc_arena",
|
||||
|
||||
@@ -937,8 +937,12 @@ pub fn get_alloc_info(&self, id: AllocId) -> AllocInfo {
|
||||
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
|
||||
if let Some(fn_val) = self.get_fn_alloc(id) {
|
||||
let align = match fn_val {
|
||||
FnVal::Instance(instance) => {
|
||||
self.tcx.codegen_instance_attrs(instance.def).alignment.unwrap_or(Align::ONE)
|
||||
FnVal::Instance(_instance) => {
|
||||
// FIXME: Until we have a clear design for the effects of align(N) functions
|
||||
// on the address of function pointers, we don't consider the align(N)
|
||||
// attribute on functions in the interpreter.
|
||||
// See <https://github.com/rust-lang/rust/issues/144661> for more context.
|
||||
Align::ONE
|
||||
}
|
||||
// Machine-specific extra functions currently do not support alignment restrictions.
|
||||
FnVal::Other(_) => Align::ONE,
|
||||
|
||||
@@ -207,6 +207,12 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i
|
||||
|
||||
lint_custom_inner_attribute_unstable = custom inner attributes are unstable
|
||||
|
||||
lint_dangling_pointers_from_locals = a dangling pointer will be produced because the local variable `{$local_var_name}` will be dropped
|
||||
.ret_ty = return type of the {$fn_kind} is `{$ret_ty}`
|
||||
.local_var = `{$local_var_name}` is part the {$fn_kind} and will be dropped at the end of the {$fn_kind}
|
||||
.created_at = dangling pointer created here
|
||||
.note = pointers do not have a lifetime; after returning, the `{$local_var_ty}` will be deallocated at the end of the {$fn_kind} because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
lint_dangling_pointers_from_temporaries = a dangling pointer will be produced because the temporary `{$ty}` will be dropped
|
||||
.label_ptr = this pointer will immediately be invalid
|
||||
.label_temporary = this `{$ty}` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use rustc_ast::visit::{visit_opt, walk_list};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
|
||||
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, find_attr};
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, LangItem, TyKind, find_attr};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::{declare_lint, impl_lint_pass};
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
use crate::lints::DanglingPointersFromTemporaries;
|
||||
use crate::lints::{DanglingPointersFromLocals, DanglingPointersFromTemporaries};
|
||||
use crate::{LateContext, LateLintPass};
|
||||
|
||||
declare_lint! {
|
||||
@@ -42,6 +43,36 @@
|
||||
"detects getting a pointer from a temporary"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `dangling_pointers_from_locals` lint detects getting a pointer to data
|
||||
/// of a local that will be dropped at the end of the function.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// fn f() -> *const u8 {
|
||||
/// let x = 0;
|
||||
/// &x // returns a dangling ptr to `x`
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Returning a pointer from a local value will not prolong its lifetime,
|
||||
/// which means that the value can be dropped and the allocation freed
|
||||
/// while the pointer still exists, making the pointer dangling.
|
||||
/// This is not an error (as far as the type system is concerned)
|
||||
/// but probably is not what the user intended either.
|
||||
///
|
||||
/// If you need stronger guarantees, consider using references instead,
|
||||
/// as they are statically verified by the borrow-checker to never dangle.
|
||||
pub DANGLING_POINTERS_FROM_LOCALS,
|
||||
Warn,
|
||||
"detects returning a pointer from a local variable"
|
||||
}
|
||||
|
||||
/// FIXME: false negatives (i.e. the lint is not emitted when it should be)
|
||||
/// 1. Ways to get a temporary that are not recognized:
|
||||
/// - `owning_temporary.field`
|
||||
@@ -53,20 +84,123 @@
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub(crate) struct DanglingPointers;
|
||||
|
||||
impl_lint_pass!(DanglingPointers => [DANGLING_POINTERS_FROM_TEMPORARIES]);
|
||||
impl_lint_pass!(DanglingPointers => [DANGLING_POINTERS_FROM_TEMPORARIES, DANGLING_POINTERS_FROM_LOCALS]);
|
||||
|
||||
// This skips over const blocks, but they cannot use or return a dangling pointer anyways.
|
||||
impl<'tcx> LateLintPass<'tcx> for DanglingPointers {
|
||||
fn check_fn(
|
||||
&mut self,
|
||||
cx: &LateContext<'tcx>,
|
||||
_: FnKind<'tcx>,
|
||||
_: &'tcx FnDecl<'tcx>,
|
||||
fn_kind: FnKind<'tcx>,
|
||||
fn_decl: &'tcx FnDecl<'tcx>,
|
||||
body: &'tcx Body<'tcx>,
|
||||
_: Span,
|
||||
_: LocalDefId,
|
||||
def_id: LocalDefId,
|
||||
) {
|
||||
DanglingPointerSearcher { cx, inside_call_args: false }.visit_body(body)
|
||||
DanglingPointerSearcher { cx, inside_call_args: false }.visit_body(body);
|
||||
|
||||
if let FnRetTy::Return(ret_ty) = &fn_decl.output
|
||||
&& let TyKind::Ptr(_) = ret_ty.kind
|
||||
{
|
||||
// get the return type of the function or closure
|
||||
let ty = match cx.tcx.type_of(def_id).instantiate_identity().kind() {
|
||||
ty::FnDef(..) => cx.tcx.fn_sig(def_id).instantiate_identity(),
|
||||
ty::Closure(_, args) => args.as_closure().sig(),
|
||||
_ => return,
|
||||
};
|
||||
let ty = ty.output();
|
||||
|
||||
// this type is only used for layout computation and pretty-printing, neither of them rely on regions
|
||||
let ty = cx.tcx.instantiate_bound_regions_with_erased(ty);
|
||||
|
||||
// verify that we have a pointer type
|
||||
let inner_ty = match ty.kind() {
|
||||
ty::RawPtr(inner_ty, _) => *inner_ty,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if cx
|
||||
.tcx
|
||||
.layout_of(cx.typing_env().as_query_input(inner_ty))
|
||||
.is_ok_and(|layout| !layout.is_1zst())
|
||||
{
|
||||
let dcx = &DanglingPointerLocalContext {
|
||||
body: def_id,
|
||||
fn_ret: ty,
|
||||
fn_ret_span: ret_ty.span,
|
||||
fn_ret_inner: inner_ty,
|
||||
fn_kind: match fn_kind {
|
||||
FnKind::ItemFn(..) => "function",
|
||||
FnKind::Method(..) => "method",
|
||||
FnKind::Closure => "closure",
|
||||
},
|
||||
};
|
||||
|
||||
// look for `return`s
|
||||
DanglingPointerReturnSearcher { cx, dcx }.visit_body(body);
|
||||
|
||||
// analyze implicit return expression
|
||||
if let ExprKind::Block(block, None) = &body.value.kind
|
||||
&& let innermost_block = block.innermost_block()
|
||||
&& let Some(expr) = innermost_block.expr
|
||||
{
|
||||
lint_addr_of_local(cx, dcx, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DanglingPointerLocalContext<'tcx> {
|
||||
body: LocalDefId,
|
||||
fn_ret: Ty<'tcx>,
|
||||
fn_ret_span: Span,
|
||||
fn_ret_inner: Ty<'tcx>,
|
||||
fn_kind: &'static str,
|
||||
}
|
||||
|
||||
struct DanglingPointerReturnSearcher<'lcx, 'tcx> {
|
||||
cx: &'lcx LateContext<'tcx>,
|
||||
dcx: &'lcx DanglingPointerLocalContext<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for DanglingPointerReturnSearcher<'_, 'tcx> {
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result {
|
||||
if let ExprKind::Ret(Some(expr)) = expr.kind {
|
||||
lint_addr_of_local(self.cx, self.dcx, expr);
|
||||
}
|
||||
walk_expr(self, expr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Look for `&<path_to_local_in_same_body>` pattern and emit lint for it
|
||||
fn lint_addr_of_local<'a>(
|
||||
cx: &LateContext<'a>,
|
||||
dcx: &DanglingPointerLocalContext<'a>,
|
||||
expr: &'a Expr<'a>,
|
||||
) {
|
||||
// peel casts as they do not interest us here, we want the inner expression.
|
||||
let (inner, _) = super::utils::peel_casts(cx, expr);
|
||||
|
||||
if let ExprKind::AddrOf(_, _, inner_of) = inner.kind
|
||||
&& let ExprKind::Path(ref qpath) = inner_of.peel_blocks().kind
|
||||
&& let Res::Local(from) = cx.qpath_res(qpath, inner_of.hir_id)
|
||||
&& cx.tcx.hir_enclosing_body_owner(from) == dcx.body
|
||||
{
|
||||
cx.tcx.emit_node_span_lint(
|
||||
DANGLING_POINTERS_FROM_LOCALS,
|
||||
expr.hir_id,
|
||||
expr.span,
|
||||
DanglingPointersFromLocals {
|
||||
ret_ty: dcx.fn_ret,
|
||||
ret_ty_span: dcx.fn_ret_span,
|
||||
fn_kind: dcx.fn_kind,
|
||||
local_var: cx.tcx.hir_span(from),
|
||||
local_var_name: cx.tcx.hir_ident(from),
|
||||
local_var_ty: dcx.fn_ret_inner,
|
||||
created_at: (expr.hir_id != inner.hir_id).then_some(inner.span),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1188,6 +1188,22 @@ pub(crate) struct DanglingPointersFromTemporaries<'tcx> {
|
||||
pub temporary_span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_dangling_pointers_from_locals)]
|
||||
#[note]
|
||||
pub(crate) struct DanglingPointersFromLocals<'tcx> {
|
||||
pub ret_ty: Ty<'tcx>,
|
||||
#[label(lint_ret_ty)]
|
||||
pub ret_ty_span: Span,
|
||||
pub fn_kind: &'static str,
|
||||
#[label(lint_local_var)]
|
||||
pub local_var: Span,
|
||||
pub local_var_name: Ident,
|
||||
pub local_var_ty: Ty<'tcx>,
|
||||
#[label(lint_created_at)]
|
||||
pub created_at: Option<Span>,
|
||||
}
|
||||
|
||||
// multiple_supertrait_upcastable.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_multiple_supertrait_upcastable)]
|
||||
|
||||
@@ -6,6 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
indexmap = "2.4.0"
|
||||
itertools = "0.12"
|
||||
pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
|
||||
@@ -968,7 +968,7 @@ fn build_reduced_graph_for_extern_crate(
|
||||
}
|
||||
self.r.potentially_unused_imports.push(import);
|
||||
let imported_binding = self.r.import(binding, import);
|
||||
if parent == self.r.graph_root {
|
||||
if ident.name != kw::Underscore && parent == self.r.graph_root {
|
||||
let ident = ident.normalize_to_macros_2_0();
|
||||
if let Some(entry) = self.r.extern_prelude.get(&ident)
|
||||
&& expansion != LocalExpnId::ROOT
|
||||
@@ -984,23 +984,29 @@ fn build_reduced_graph_for_extern_crate(
|
||||
// more details: https://github.com/rust-lang/rust/pull/111761
|
||||
return;
|
||||
}
|
||||
let entry = self.r.extern_prelude.entry(ident).or_insert(ExternPreludeEntry {
|
||||
binding: Cell::new(None),
|
||||
introduced_by_item: true,
|
||||
});
|
||||
if orig_name.is_some() {
|
||||
entry.introduced_by_item = true;
|
||||
}
|
||||
// Binding from `extern crate` item in source code can replace
|
||||
// a binding from `--extern` on command line here.
|
||||
if !entry.is_import() {
|
||||
entry.binding.set(Some(imported_binding));
|
||||
} else if ident.name != kw::Underscore {
|
||||
self.r.dcx().span_delayed_bug(
|
||||
item.span,
|
||||
format!("it had been define the external module '{ident}' multiple times"),
|
||||
);
|
||||
}
|
||||
|
||||
use indexmap::map::Entry;
|
||||
match self.r.extern_prelude.entry(ident) {
|
||||
Entry::Occupied(mut occupied) => {
|
||||
let entry = occupied.get_mut();
|
||||
if let Some(old_binding) = entry.binding.get()
|
||||
&& old_binding.is_import()
|
||||
{
|
||||
let msg = format!("extern crate `{ident}` already in extern prelude");
|
||||
self.r.tcx.dcx().span_delayed_bug(item.span, msg);
|
||||
} else {
|
||||
// Binding from `extern crate` item in source code can replace
|
||||
// a binding from `--extern` on command line here.
|
||||
entry.binding.set(Some(imported_binding));
|
||||
entry.introduced_by_item = orig_name.is_some();
|
||||
}
|
||||
entry
|
||||
}
|
||||
Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry {
|
||||
binding: Cell::new(Some(imported_binding)),
|
||||
introduced_by_item: true,
|
||||
}),
|
||||
};
|
||||
}
|
||||
self.r.define_binding_local(parent, ident, TypeNS, imported_binding);
|
||||
}
|
||||
|
||||
@@ -1098,7 +1098,7 @@ fn early_lookup_typo_candidate(
|
||||
}
|
||||
}
|
||||
Scope::ExternPrelude => {
|
||||
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
|
||||
suggestions.extend(this.extern_prelude.keys().filter_map(|ident| {
|
||||
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
|
||||
filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res))
|
||||
}));
|
||||
@@ -1409,7 +1409,7 @@ pub(crate) fn lookup_import_candidates<FilterFn>(
|
||||
);
|
||||
|
||||
if lookup_ident.span.at_least_rust_2018() {
|
||||
for ident in self.extern_prelude.clone().into_keys() {
|
||||
for &ident in self.extern_prelude.keys() {
|
||||
if ident.span.from_expansion() {
|
||||
// Idents are adjusted to the root context before being
|
||||
// resolved in the extern prelude, so reporting this to the
|
||||
|
||||
@@ -2476,19 +2476,10 @@ fn lookup_typo_candidate(
|
||||
} else {
|
||||
// Items from the prelude
|
||||
if !module.no_implicit_prelude {
|
||||
let extern_prelude = self.r.extern_prelude.clone();
|
||||
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
|
||||
self.r
|
||||
.cstore_mut()
|
||||
.maybe_process_path_extern(self.r.tcx, ident.name)
|
||||
.and_then(|crate_id| {
|
||||
let crate_mod =
|
||||
Res::Def(DefKind::Mod, crate_id.as_def_id());
|
||||
|
||||
filter_fn(crate_mod).then(|| {
|
||||
TypoSuggestion::typo_from_ident(*ident, crate_mod)
|
||||
})
|
||||
})
|
||||
names.extend(self.r.extern_prelude.keys().flat_map(|ident| {
|
||||
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
|
||||
filter_fn(res)
|
||||
.then_some(TypoSuggestion::typo_from_ident(*ident, res))
|
||||
}));
|
||||
|
||||
if let Some(prelude) = self.r.prelude {
|
||||
|
||||
@@ -1487,13 +1487,23 @@ pub fn new(
|
||||
let mut invocation_parents = FxHashMap::default();
|
||||
invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT);
|
||||
|
||||
let mut extern_prelude: FxIndexMap<Ident, ExternPreludeEntry<'_>> = tcx
|
||||
let mut extern_prelude: FxIndexMap<_, _> = tcx
|
||||
.sess
|
||||
.opts
|
||||
.externs
|
||||
.iter()
|
||||
.filter(|(_, entry)| entry.add_prelude)
|
||||
.map(|(name, _)| (Ident::from_str(name), Default::default()))
|
||||
.filter_map(|(name, entry)| {
|
||||
// Make sure `self`, `super`, `_` etc do not get into extern prelude.
|
||||
// FIXME: reject `--extern self` and similar in option parsing instead.
|
||||
if entry.add_prelude
|
||||
&& let name = Symbol::intern(name)
|
||||
&& name.can_be_raw()
|
||||
{
|
||||
Some((Ident::with_dummy_span(name), Default::default()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !attr::contains_name(attrs, sym::no_core) {
|
||||
@@ -2168,40 +2178,42 @@ fn disambiguate_macro_rules_vs_modularized(
|
||||
}
|
||||
|
||||
fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBinding<'ra>> {
|
||||
if ident.is_path_segment_keyword() {
|
||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
return None;
|
||||
}
|
||||
|
||||
let norm_ident = ident.normalize_to_macros_2_0();
|
||||
let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| {
|
||||
Some(if let Some(binding) = entry.binding.get() {
|
||||
let mut record_use = None;
|
||||
let entry = self.extern_prelude.get(&ident.normalize_to_macros_2_0());
|
||||
let binding = entry.and_then(|entry| match entry.binding.get() {
|
||||
Some(binding) if binding.is_import() => {
|
||||
if finalize {
|
||||
if !entry.is_import() {
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
|
||||
} else if entry.introduced_by_item {
|
||||
self.record_use(ident, binding, Used::Other);
|
||||
}
|
||||
record_use = Some(binding);
|
||||
}
|
||||
binding
|
||||
} else {
|
||||
Some(binding)
|
||||
}
|
||||
Some(binding) => {
|
||||
if finalize {
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
|
||||
}
|
||||
Some(binding)
|
||||
}
|
||||
None => {
|
||||
let crate_id = if finalize {
|
||||
let Some(crate_id) =
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
|
||||
else {
|
||||
return Some(self.dummy_binding);
|
||||
};
|
||||
crate_id
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
|
||||
} else {
|
||||
self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)?
|
||||
self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
|
||||
};
|
||||
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
|
||||
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT)
|
||||
})
|
||||
match crate_id {
|
||||
Some(crate_id) => {
|
||||
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
|
||||
let binding =
|
||||
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
|
||||
entry.binding.set(Some(binding));
|
||||
Some(binding)
|
||||
}
|
||||
None => finalize.then_some(self.dummy_binding),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(entry) = self.extern_prelude.get(&norm_ident) {
|
||||
entry.binding.set(binding);
|
||||
if let Some(binding) = record_use {
|
||||
self.record_use(ident, binding, Used::Scope);
|
||||
}
|
||||
|
||||
binding
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(clippy::enum_clike_unportable_variant)]
|
||||
|
||||
use crate::num::NonZero;
|
||||
use crate::ub_checks::assert_unsafe_precondition;
|
||||
use crate::{cmp, fmt, hash, mem, num};
|
||||
@@ -241,7 +243,7 @@ fn default() -> Alignment {
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(u16)]
|
||||
#[repr(usize)]
|
||||
enum AlignmentEnum {
|
||||
_Align1Shl0 = 1 << 0,
|
||||
_Align1Shl1 = 1 << 1,
|
||||
@@ -263,7 +265,7 @@ enum AlignmentEnum {
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(u32)]
|
||||
#[repr(usize)]
|
||||
enum AlignmentEnum {
|
||||
_Align1Shl0 = 1 << 0,
|
||||
_Align1Shl1 = 1 << 1,
|
||||
@@ -301,7 +303,7 @@ enum AlignmentEnum {
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(u64)]
|
||||
#[repr(usize)]
|
||||
enum AlignmentEnum {
|
||||
_Align1Shl0 = 1 << 0,
|
||||
_Align1Shl1 = 1 << 1,
|
||||
|
||||
@@ -3974,8 +3974,9 @@ pub fn copy_within<R: RangeBounds<usize>>(&mut self, src: R, dest: usize)
|
||||
///
|
||||
/// [`split_at_mut`]: slice::split_at_mut
|
||||
#[stable(feature = "swap_with_slice", since = "1.27.0")]
|
||||
#[rustc_const_unstable(feature = "const_swap_with_slice", issue = "142204")]
|
||||
#[track_caller]
|
||||
pub fn swap_with_slice(&mut self, other: &mut [T]) {
|
||||
pub const fn swap_with_slice(&mut self, other: &mut [T]) {
|
||||
assert!(self.len() == other.len(), "destination and source slices have different lengths");
|
||||
// SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was
|
||||
// checked to have the same length. The slices cannot overlap because
|
||||
|
||||
@@ -696,14 +696,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let msg = info.message();
|
||||
crate::sys::backtrace::__rust_end_short_backtrace(move || {
|
||||
if let Some(s) = msg.as_str() {
|
||||
rust_panic_with_hook(
|
||||
panic_with_hook(
|
||||
&mut StaticStrPayload(s),
|
||||
loc,
|
||||
info.can_unwind(),
|
||||
info.force_no_backtrace(),
|
||||
);
|
||||
} else {
|
||||
rust_panic_with_hook(
|
||||
panic_with_hook(
|
||||
&mut FormatStringPayload { inner: &msg, string: None },
|
||||
loc,
|
||||
info.can_unwind(),
|
||||
@@ -767,7 +767,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
let loc = Location::caller();
|
||||
crate::sys::backtrace::__rust_end_short_backtrace(move || {
|
||||
rust_panic_with_hook(
|
||||
panic_with_hook(
|
||||
&mut Payload { inner: Some(msg) },
|
||||
loc,
|
||||
/* can_unwind */ true,
|
||||
@@ -792,7 +792,7 @@ fn payload_as_str(payload: &dyn Any) -> &str {
|
||||
/// panics, panic hooks, and finally dispatching to the panic runtime to either
|
||||
/// abort or unwind.
|
||||
#[optimize(size)]
|
||||
fn rust_panic_with_hook(
|
||||
fn panic_with_hook(
|
||||
payload: &mut dyn PanicPayload,
|
||||
location: &Location<'_>,
|
||||
can_unwind: bool,
|
||||
@@ -885,8 +885,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
rust_panic(&mut RewrapBox(payload))
|
||||
}
|
||||
|
||||
/// An unmangled function (through `rustc_std_internal_symbol`) on which to slap
|
||||
/// yer breakpoints.
|
||||
/// A function with a fixed suffix (through `rustc_std_internal_symbol`)
|
||||
/// on which to slap yer breakpoints.
|
||||
#[inline(never)]
|
||||
#[cfg_attr(not(test), rustc_std_internal_symbol)]
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
|
||||
@@ -2018,6 +2018,9 @@ fn _assert_both<T: Send + Sync>() {}
|
||||
/// which may take time on systems with large numbers of mountpoints.
|
||||
/// (This does not apply to cgroup v2, or to processes not in a
|
||||
/// cgroup.)
|
||||
/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of
|
||||
/// threads, `available_parallelism` cannot know how much of that limit a Rust program should
|
||||
/// take, or know in a reliable and race-free way how much of that limit is already taken.
|
||||
///
|
||||
/// On all targets:
|
||||
/// - It may overcount the amount of parallelism available when running in a VM
|
||||
|
||||
@@ -1663,7 +1663,11 @@ fn run(self, builder: &Builder<'_>) {
|
||||
// bootstrap compiler.
|
||||
// NOTE: Only stage 1 is special cased because we need the rustc_private artifacts to match the
|
||||
// running compiler in stage 2 when plugins run.
|
||||
let query_compiler;
|
||||
let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 {
|
||||
// Even when using the stage 0 compiler, we also need to provide the stage 1 compiler
|
||||
// so that compiletest can query it for target information.
|
||||
query_compiler = Some(compiler);
|
||||
// At stage 0 (stage - 1) we are using the stage0 compiler. Using `self.target` can lead
|
||||
// finding an incorrect compiler path on cross-targets, as the stage 0 is always equal to
|
||||
// `build.build` in the configuration.
|
||||
@@ -1672,6 +1676,7 @@ fn run(self, builder: &Builder<'_>) {
|
||||
let test_stage = compiler.stage + 1;
|
||||
(test_stage, format!("stage{test_stage}-{build}"))
|
||||
} else {
|
||||
query_compiler = None;
|
||||
let stage = compiler.stage;
|
||||
(stage, format!("stage{stage}-{target}"))
|
||||
};
|
||||
@@ -1716,6 +1721,9 @@ fn run(self, builder: &Builder<'_>) {
|
||||
cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
|
||||
cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target));
|
||||
cmd.arg("--rustc-path").arg(builder.rustc(compiler));
|
||||
if let Some(query_compiler) = query_compiler {
|
||||
cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
|
||||
}
|
||||
|
||||
// Minicore auxiliary lib for `no_core` tests that need `core` stubs in cross-compilation
|
||||
// scenarios.
|
||||
|
||||
@@ -15,7 +15,7 @@ Target triples available:
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- Renat Fatykhov, https://github.com/rfatykhov-lynx
|
||||
[@rfatykhov-lynx](https://github.com/rfatykhov-lynx)
|
||||
|
||||
## Requirements
|
||||
|
||||
|
||||
@@ -279,6 +279,15 @@ pub struct Config {
|
||||
/// [`Self::rustc_path`].
|
||||
pub stage0_rustc_path: Option<Utf8PathBuf>,
|
||||
|
||||
/// Path to the stage 1 or higher `rustc` used to obtain target information via
|
||||
/// `--print=all-target-specs-json` and similar queries.
|
||||
///
|
||||
/// Normally this is unset, because [`Self::rustc_path`] can be used instead.
|
||||
/// But when running "stage 1" ui-fulldeps tests, `rustc_path` is a stage 0
|
||||
/// compiler, whereas target specs must be obtained from a stage 1+ compiler
|
||||
/// (in case the JSON format has changed since the last bootstrap bump).
|
||||
pub query_rustc_path: Option<Utf8PathBuf>,
|
||||
|
||||
/// Path to the `rustdoc`-under-test. Like [`Self::rustc_path`], this `rustdoc` is *staged*.
|
||||
pub rustdoc_path: Option<Utf8PathBuf>,
|
||||
|
||||
@@ -712,6 +721,7 @@ pub fn incomplete_for_rustdoc_gui_test() -> Config {
|
||||
rustc_path: Utf8PathBuf::default(),
|
||||
cargo_path: Default::default(),
|
||||
stage0_rustc_path: Default::default(),
|
||||
query_rustc_path: Default::default(),
|
||||
rustdoc_path: Default::default(),
|
||||
coverage_dump_path: Default::default(),
|
||||
python: Default::default(),
|
||||
@@ -917,7 +927,7 @@ pub struct TargetCfgs {
|
||||
|
||||
impl TargetCfgs {
|
||||
fn new(config: &Config) -> TargetCfgs {
|
||||
let mut targets: HashMap<String, TargetCfg> = serde_json::from_str(&rustc_output(
|
||||
let mut targets: HashMap<String, TargetCfg> = serde_json::from_str(&query_rustc_output(
|
||||
config,
|
||||
&["--print=all-target-specs-json", "-Zunstable-options"],
|
||||
Default::default(),
|
||||
@@ -950,7 +960,7 @@ fn new(config: &Config) -> TargetCfgs {
|
||||
if config.target.ends_with(".json") || !envs.is_empty() {
|
||||
targets.insert(
|
||||
config.target.clone(),
|
||||
serde_json::from_str(&rustc_output(
|
||||
serde_json::from_str(&query_rustc_output(
|
||||
config,
|
||||
&[
|
||||
"--print=target-spec-json",
|
||||
@@ -1009,10 +1019,13 @@ fn get_current_target_config(
|
||||
// which are respected for `--print=cfg` but not for `--print=all-target-specs-json`. The
|
||||
// code below extracts them from `--print=cfg`: make sure to only override fields that can
|
||||
// actually be changed with `-C` flags.
|
||||
for config in
|
||||
rustc_output(config, &["--print=cfg", "--target", &config.target], Default::default())
|
||||
.trim()
|
||||
.lines()
|
||||
for config in query_rustc_output(
|
||||
config,
|
||||
&["--print=cfg", "--target", &config.target],
|
||||
Default::default(),
|
||||
)
|
||||
.trim()
|
||||
.lines()
|
||||
{
|
||||
let (name, value) = config
|
||||
.split_once("=\"")
|
||||
@@ -1113,7 +1126,7 @@ pub enum Endian {
|
||||
}
|
||||
|
||||
fn builtin_cfg_names(config: &Config) -> HashSet<String> {
|
||||
rustc_output(
|
||||
query_rustc_output(
|
||||
config,
|
||||
&["--print=check-cfg", "-Zunstable-options", "--check-cfg=cfg()"],
|
||||
Default::default(),
|
||||
@@ -1128,7 +1141,7 @@ fn builtin_cfg_names(config: &Config) -> HashSet<String> {
|
||||
&["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"];
|
||||
|
||||
fn supported_crate_types(config: &Config) -> HashSet<String> {
|
||||
let crate_types: HashSet<_> = rustc_output(
|
||||
let crate_types: HashSet<_> = query_rustc_output(
|
||||
config,
|
||||
&["--target", &config.target, "--print=supported-crate-types", "-Zunstable-options"],
|
||||
Default::default(),
|
||||
@@ -1149,8 +1162,10 @@ fn supported_crate_types(config: &Config) -> HashSet<String> {
|
||||
crate_types
|
||||
}
|
||||
|
||||
fn rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
|
||||
let mut command = Command::new(&config.rustc_path);
|
||||
fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
|
||||
let query_rustc_path = config.query_rustc_path.as_deref().unwrap_or(&config.rustc_path);
|
||||
|
||||
let mut command = Command::new(query_rustc_path);
|
||||
add_dylib_path(&mut command, iter::once(&config.compile_lib_path));
|
||||
command.args(&config.target_rustcflags).args(args);
|
||||
command.env("RUSTC_BOOTSTRAP", "1");
|
||||
|
||||
@@ -63,6 +63,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
"path to rustc to use for compiling run-make recipes",
|
||||
"PATH",
|
||||
)
|
||||
.optopt(
|
||||
"",
|
||||
"query-rustc-path",
|
||||
"path to rustc to use for querying target information (defaults to `--rustc-path`)",
|
||||
"PATH",
|
||||
)
|
||||
.optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
|
||||
.optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH")
|
||||
.reqopt("", "python", "path to python to use for doc tests", "PATH")
|
||||
@@ -354,6 +360,7 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
|
||||
rustc_path: opt_path(matches, "rustc-path"),
|
||||
cargo_path: matches.opt_str("cargo-path").map(Utf8PathBuf::from),
|
||||
stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(Utf8PathBuf::from),
|
||||
query_rustc_path: matches.opt_str("query-rustc-path").map(Utf8PathBuf::from),
|
||||
rustdoc_path: matches.opt_str("rustdoc-path").map(Utf8PathBuf::from),
|
||||
coverage_dump_path: matches.opt_str("coverage-dump-path").map(Utf8PathBuf::from),
|
||||
python: matches.opt_str("python").unwrap(),
|
||||
|
||||
@@ -16,7 +16,7 @@ LL | ABORT()
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ LL | ABORT()
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -16,7 +16,7 @@ LL | ABORT()
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -19,7 +19,7 @@ LL | ABORT()
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -15,7 +15,7 @@ LL | ABORT()
|
||||
= note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
|
||||
= note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -15,7 +15,7 @@ LL | ABORT()
|
||||
= note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
|
||||
= note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -15,7 +15,7 @@ LL | ABORT()
|
||||
= note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
|
||||
= note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -15,7 +15,7 @@ LL | ABORT()
|
||||
= note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
|
||||
= note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -14,7 +14,7 @@ LL | ABORT()
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -18,7 +18,7 @@ LL | ABORT()
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -16,7 +16,7 @@ LL | ABORT()
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
|
||||
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
= note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
|
||||
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
// Make sure we catch this even without Stacked Borrows
|
||||
//@compile-flags: -Zmiri-disable-stacked-borrows
|
||||
|
||||
#![allow(dangling_pointers_from_locals)]
|
||||
|
||||
use std::mem;
|
||||
|
||||
fn dangling() -> *const u8 {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
//@compile-flags: -Zmin-function-alignment=8
|
||||
|
||||
// FIXME(rust-lang/rust#82232, rust-lang/rust#143834): temporarily renamed to mitigate `#[align]`
|
||||
// nameres ambiguity
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(fn_align)]
|
||||
|
||||
// When a function uses `align(N)`, the function address should be a multiple of `N`.
|
||||
|
||||
#[rustc_align(256)]
|
||||
fn foo() {}
|
||||
|
||||
#[rustc_align(16)]
|
||||
fn bar() {}
|
||||
|
||||
#[rustc_align(4)]
|
||||
fn baz() {}
|
||||
|
||||
fn main() {
|
||||
assert!((foo as usize).is_multiple_of(256));
|
||||
assert!((bar as usize).is_multiple_of(16));
|
||||
|
||||
// The maximum of `align(N)` and `-Zmin-function-alignment=N` is used.
|
||||
assert!((baz as usize).is_multiple_of(8));
|
||||
}
|
||||
@@ -5,7 +5,8 @@
|
||||
repr_simd,
|
||||
arm_target_feature,
|
||||
mips_target_feature,
|
||||
s390x_target_feature
|
||||
s390x_target_feature,
|
||||
riscv_target_feature
|
||||
)]
|
||||
#![no_std]
|
||||
#![crate_type = "lib"]
|
||||
@@ -25,97 +26,105 @@
|
||||
pub struct i8x16([i8; 16]);
|
||||
|
||||
// CHECK-LABEL: dyn_simd_extract
|
||||
// CHECK: extractelement <16 x i8> %x, i32 %idx
|
||||
// CHECK: extractelement <16 x i8> %[[TEMP:.+]], i32 %idx
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 {
|
||||
simd_extract_dyn(x, idx)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: literal_dyn_simd_extract
|
||||
// CHECK: extractelement <16 x i8> %x, i32 7
|
||||
// CHECK: extractelement <16 x i8> %[[TEMP:.+]], i32 7
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 {
|
||||
simd_extract_dyn(x, 7)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: const_dyn_simd_extract
|
||||
// CHECK: extractelement <16 x i8> %x, i32 7
|
||||
// CHECK: extractelement <16 x i8> %[[TEMP:.+]], i32 7
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 {
|
||||
simd_extract_dyn(x, const { 3 + 4 })
|
||||
}
|
||||
|
||||
// CHECK-LABEL: const_simd_extract
|
||||
// CHECK: extractelement <16 x i8> %x, i32 7
|
||||
// CHECK: extractelement <16 x i8> %[[TEMP:.+]], i32 7
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 {
|
||||
simd_extract(x, const { 3 + 4 })
|
||||
}
|
||||
|
||||
// CHECK-LABEL: dyn_simd_insert
|
||||
// CHECK: insertelement <16 x i8> %x, i8 %e, i32 %idx
|
||||
// CHECK: insertelement <16 x i8> %[[TEMP:.+]], i8 %e, i32 %idx
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 {
|
||||
simd_insert_dyn(x, idx, e)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: literal_dyn_simd_insert
|
||||
// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
|
||||
// CHECK: insertelement <16 x i8> %[[TEMP:.+]], i8 %e, i32 7
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
|
||||
simd_insert_dyn(x, 7, e)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: const_dyn_simd_insert
|
||||
// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
|
||||
// CHECK: insertelement <16 x i8> %[[TEMP:.+]], i8 %e, i32 7
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
|
||||
simd_insert_dyn(x, const { 3 + 4 }, e)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: const_simd_insert
|
||||
// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
|
||||
// CHECK: insertelement <16 x i8> %[[TEMP:.+]], i8 %e, i32 7
|
||||
#[no_mangle]
|
||||
#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
|
||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
|
||||
#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
|
||||
#[cfg_attr(target_arch = "mips", target_feature(enable = "msa"))]
|
||||
#[cfg_attr(target_arch = "s390x", target_feature(enable = "vector"))]
|
||||
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
|
||||
unsafe extern "C" fn const_simd_insert(x: i8x16, e: i8) -> i8x16 {
|
||||
simd_insert(x, const { 3 + 4 }, e)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//! Test that stepping through a simple program with a debugger one line at a
|
||||
//! time works intuitively, e.g. that `next` takes you to the next source line.
|
||||
//! Regression test for <https://github.com/rust-lang/rust/issues/33013>.
|
||||
|
||||
//@ ignore-aarch64: Doesn't work yet.
|
||||
//@ compile-flags: -g
|
||||
|
||||
// gdb-command: run
|
||||
// FIXME(#97083): Should we be able to break on initialization of zero-sized types?
|
||||
// FIXME(#97083): Right now the first breakable line is:
|
||||
// gdb-check: let mut c = 27;
|
||||
// gdb-command: next
|
||||
// gdb-check: let d = c = 99;
|
||||
// gdb-command: next
|
||||
// FIXME(#33013): gdb-check: let e = "hi bob";
|
||||
// FIXME(#33013): gdb-command: next
|
||||
// FIXME(#33013): gdb-check: let f = b"hi bob";
|
||||
// FIXME(#33013): gdb-command: next
|
||||
// FIXME(#33013): gdb-check: let g = b'9';
|
||||
// FIXME(#33013): gdb-command: next
|
||||
// FIXME(#33013): gdb-check: let h = ["whatever"; 8];
|
||||
// FIXME(#33013): gdb-command: next
|
||||
// gdb-check: let i = [1,2,3,4];
|
||||
// gdb-command: next
|
||||
// gdb-check: let j = (23, "hi");
|
||||
// gdb-command: next
|
||||
// gdb-check: let k = 2..3;
|
||||
// gdb-command: next
|
||||
// gdb-check: let l = &i[k];
|
||||
// gdb-command: next
|
||||
// gdb-check: let m: *const() = &a;
|
||||
|
||||
fn main () {
|
||||
let a = (); // #break
|
||||
let b : [i32; 0] = [];
|
||||
let mut c = 27;
|
||||
let d = c = 99;
|
||||
let e = "hi bob";
|
||||
let f = b"hi bob";
|
||||
let g = b'9';
|
||||
let h = ["whatever"; 8];
|
||||
let i = [1,2,3,4];
|
||||
let j = (23, "hi");
|
||||
let k = 2..3;
|
||||
let l = &i[k];
|
||||
let m: *const() = &a;
|
||||
}
|
||||
+4
-8
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
let _2: std::ptr::NonNull<[T]>;
|
||||
let mut _3: *mut [T];
|
||||
let mut _4: *const [T];
|
||||
let _12: ();
|
||||
let _11: ();
|
||||
scope 3 {
|
||||
let _8: std::ptr::alignment::AlignmentEnum;
|
||||
scope 4 {
|
||||
@@ -31,12 +31,11 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
scope 20 (inlined NonNull::<u8>::as_ptr) {
|
||||
}
|
||||
scope 21 (inlined std::alloc::dealloc) {
|
||||
let mut _11: usize;
|
||||
let mut _10: usize;
|
||||
scope 22 (inlined Layout::size) {
|
||||
}
|
||||
scope 23 (inlined Layout::align) {
|
||||
scope 24 (inlined std::ptr::Alignment::as_usize) {
|
||||
let mut _10: u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,16 +86,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
bb2: {
|
||||
StorageLive(_9);
|
||||
_9 = copy _3 as *mut u8 (PtrToPtr);
|
||||
StorageLive(_11);
|
||||
StorageLive(_10);
|
||||
_10 = discriminant(_8);
|
||||
_11 = move _10 as usize (IntToInt);
|
||||
StorageDead(_10);
|
||||
_12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable];
|
||||
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_11);
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
+4
-8
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
let _2: std::ptr::NonNull<[T]>;
|
||||
let mut _3: *mut [T];
|
||||
let mut _4: *const [T];
|
||||
let _12: ();
|
||||
let _11: ();
|
||||
scope 3 {
|
||||
let _8: std::ptr::alignment::AlignmentEnum;
|
||||
scope 4 {
|
||||
@@ -31,12 +31,11 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
scope 20 (inlined NonNull::<u8>::as_ptr) {
|
||||
}
|
||||
scope 21 (inlined std::alloc::dealloc) {
|
||||
let mut _11: usize;
|
||||
let mut _10: usize;
|
||||
scope 22 (inlined Layout::size) {
|
||||
}
|
||||
scope 23 (inlined Layout::align) {
|
||||
scope 24 (inlined std::ptr::Alignment::as_usize) {
|
||||
let mut _10: u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,16 +86,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
bb2: {
|
||||
StorageLive(_9);
|
||||
_9 = copy _3 as *mut u8 (PtrToPtr);
|
||||
StorageLive(_11);
|
||||
StorageLive(_10);
|
||||
_10 = discriminant(_8);
|
||||
_11 = move _10 as usize (IntToInt);
|
||||
StorageDead(_10);
|
||||
_12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable];
|
||||
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_11);
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
+4
-8
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
let _2: std::ptr::NonNull<[T]>;
|
||||
let mut _3: *mut [T];
|
||||
let mut _4: *const [T];
|
||||
let _12: ();
|
||||
let _11: ();
|
||||
scope 3 {
|
||||
let _8: std::ptr::alignment::AlignmentEnum;
|
||||
scope 4 {
|
||||
@@ -31,12 +31,11 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
scope 20 (inlined NonNull::<u8>::as_ptr) {
|
||||
}
|
||||
scope 21 (inlined std::alloc::dealloc) {
|
||||
let mut _11: usize;
|
||||
let mut _10: usize;
|
||||
scope 22 (inlined Layout::size) {
|
||||
}
|
||||
scope 23 (inlined Layout::align) {
|
||||
scope 24 (inlined std::ptr::Alignment::as_usize) {
|
||||
let mut _10: u64;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,16 +86,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
bb2: {
|
||||
StorageLive(_9);
|
||||
_9 = copy _3 as *mut u8 (PtrToPtr);
|
||||
StorageLive(_11);
|
||||
StorageLive(_10);
|
||||
_10 = discriminant(_8);
|
||||
_11 = move _10 as usize (IntToInt);
|
||||
StorageDead(_10);
|
||||
_12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable];
|
||||
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_11);
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
+4
-8
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
let _2: std::ptr::NonNull<[T]>;
|
||||
let mut _3: *mut [T];
|
||||
let mut _4: *const [T];
|
||||
let _12: ();
|
||||
let _11: ();
|
||||
scope 3 {
|
||||
let _8: std::ptr::alignment::AlignmentEnum;
|
||||
scope 4 {
|
||||
@@ -31,12 +31,11 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
scope 20 (inlined NonNull::<u8>::as_ptr) {
|
||||
}
|
||||
scope 21 (inlined std::alloc::dealloc) {
|
||||
let mut _11: usize;
|
||||
let mut _10: usize;
|
||||
scope 22 (inlined Layout::size) {
|
||||
}
|
||||
scope 23 (inlined Layout::align) {
|
||||
scope 24 (inlined std::ptr::Alignment::as_usize) {
|
||||
let mut _10: u64;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,16 +86,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
|
||||
bb2: {
|
||||
StorageLive(_9);
|
||||
_9 = copy _3 as *mut u8 (PtrToPtr);
|
||||
StorageLive(_11);
|
||||
StorageLive(_10);
|
||||
_10 = discriminant(_8);
|
||||
_11 = move _10 as usize (IntToInt);
|
||||
StorageDead(_10);
|
||||
_12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable];
|
||||
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_11);
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ pub unsafe fn generic_in_place<T: Copy>(ptr: *mut Box<[T]>) {
|
||||
// CHECK: [[B:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute);
|
||||
// CHECK: [[C:_.+]] = move ([[B]].0: std::ptr::alignment::AlignmentEnum);
|
||||
// CHECK: [[D:_.+]] = discriminant([[C]]);
|
||||
// CHECK: [[E:_.+]] = move [[D]] as usize (IntToInt);
|
||||
// CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[E]]) ->
|
||||
// CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[D]]) ->
|
||||
std::ptr::drop_in_place(ptr)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//! LLVM error with unsupported expression in static
|
||||
//! initializer for const pointer in array on macOS.
|
||||
//!
|
||||
//! Regression test for <https://github.com/rust-lang/rust/issues/89225>.
|
||||
|
||||
//@ build-pass
|
||||
//@ compile-flags: -C opt-level=3
|
||||
|
||||
const fn make() -> (i32, i32, *const i32) {
|
||||
const V: i32 = 123;
|
||||
&V as *const i32;
|
||||
(0, 0, &V)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let arr = [make(); 32];
|
||||
println!("{}", arr[0].0);
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
//@ check-pass
|
||||
|
||||
struct Zst((), ());
|
||||
struct Adt(u8);
|
||||
|
||||
const X: u8 = 5;
|
||||
|
||||
fn simple() -> *const u8 {
|
||||
let x = 0;
|
||||
&x
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn bindings() -> *const u8 {
|
||||
let x = 0;
|
||||
let x = &x;
|
||||
x
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn bindings_with_return() -> *const u8 {
|
||||
let x = 42;
|
||||
let y = &x;
|
||||
return y;
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn with_simple_cast() -> *const u8 {
|
||||
let x = 0u8;
|
||||
&x as *const u8
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn bindings_and_casts() -> *const u8 {
|
||||
let x = 0u8;
|
||||
let x = &x as *const u8;
|
||||
x as *const u8
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn return_with_complex_cast() -> *mut u8 {
|
||||
let mut x = 0u8;
|
||||
return &mut x as *mut u8 as *const u8 as *mut u8;
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn with_block() -> *const u8 {
|
||||
let x = 0;
|
||||
&{ x }
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn with_many_blocks() -> *const u8 {
|
||||
let x = 0;
|
||||
{
|
||||
{
|
||||
&{
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
{ x }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn simple_return() -> *const u8 {
|
||||
let x = 0;
|
||||
return &x;
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn return_mut() -> *mut u8 {
|
||||
let mut x = 0;
|
||||
return &mut x;
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn const_and_flow() -> *const u8 {
|
||||
if false {
|
||||
let x = 8;
|
||||
return &x;
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
&X // not dangling
|
||||
}
|
||||
|
||||
fn vector<T: Default>() -> *const Vec<T> {
|
||||
let x = vec![T::default()];
|
||||
&x
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn local_adt() -> *const Adt {
|
||||
let x = Adt(5);
|
||||
return &x;
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn closure() -> *const u8 {
|
||||
let _x = || -> *const u8 {
|
||||
let x = 8;
|
||||
return &x;
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
};
|
||||
&X // not dangling
|
||||
}
|
||||
|
||||
fn fn_ptr() -> *const fn() -> u8 {
|
||||
fn ret_u8() -> u8 {
|
||||
0
|
||||
}
|
||||
|
||||
let x = ret_u8 as fn() -> u8;
|
||||
&x
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn as_arg(a: Adt) -> *const Adt {
|
||||
&a
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 {
|
||||
&a
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn ptr_as_arg(a: *const Adt) -> *const *const Adt {
|
||||
&a
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn adt_as_arg(a: &Adt) -> *const &Adt {
|
||||
&a
|
||||
//~^ WARN a dangling pointer will be produced
|
||||
}
|
||||
|
||||
fn unit() -> *const () {
|
||||
let x = ();
|
||||
&x // not dangling
|
||||
}
|
||||
|
||||
fn zst() -> *const Zst {
|
||||
let x = Zst((), ());
|
||||
&x // not dangling
|
||||
}
|
||||
|
||||
fn ref_implicit(a: &Adt) -> *const Adt {
|
||||
a // not dangling
|
||||
}
|
||||
|
||||
fn ref_explicit(a: &Adt) -> *const Adt {
|
||||
&*a // not dangling
|
||||
}
|
||||
|
||||
fn identity(a: *const Adt) -> *const Adt {
|
||||
a // not dangling
|
||||
}
|
||||
|
||||
fn from_ref(a: &Adt) -> *const Adt {
|
||||
std::ptr::from_ref(a) // not dangling
|
||||
}
|
||||
|
||||
fn inner_static() -> *const u8 {
|
||||
static U: u8 = 5;
|
||||
if false {
|
||||
return &U as *const u8; // not dangling
|
||||
}
|
||||
&U // not dangling
|
||||
}
|
||||
|
||||
fn return_in_closure() {
|
||||
let x = 0;
|
||||
let c = || -> *const u8 {
|
||||
&x // not dangling by it-self
|
||||
};
|
||||
}
|
||||
|
||||
fn option<T: Default>() -> *const Option<T> {
|
||||
let x = Some(T::default());
|
||||
&x // can't compute layout of `Option<T>`, so cnat' be sure it won't be a ZST
|
||||
}
|
||||
|
||||
fn generic<T: Default>() -> *const T {
|
||||
let x = T::default();
|
||||
&x // can't compute layout of `T`, so can't be sure it won't be a ZST
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,247 @@
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:10:5
|
||||
|
|
||||
LL | fn simple() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 0;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | &x
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
= note: `#[warn(dangling_pointers_from_locals)]` on by default
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:17:5
|
||||
|
|
||||
LL | fn bindings() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 0;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | let x = &x;
|
||||
| -- dangling pointer created here
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:24:12
|
||||
|
|
||||
LL | fn bindings_with_return() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 42;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | let y = &x;
|
||||
| -- dangling pointer created here
|
||||
LL | return y;
|
||||
| ^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:30:5
|
||||
|
|
||||
LL | fn with_simple_cast() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 0u8;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | &x as *const u8
|
||||
| --^^^^^^^^^^^^^
|
||||
| |
|
||||
| dangling pointer created here
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:37:5
|
||||
|
|
||||
LL | fn bindings_and_casts() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 0u8;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | let x = &x as *const u8;
|
||||
| -- dangling pointer created here
|
||||
LL | x as *const u8
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:43:12
|
||||
|
|
||||
LL | fn return_with_complex_cast() -> *mut u8 {
|
||||
| ------- return type of the function is `*mut u8`
|
||||
LL | let mut x = 0u8;
|
||||
| ----- `x` is part the function and will be dropped at the end of the function
|
||||
LL | return &mut x as *mut u8 as *const u8 as *mut u8;
|
||||
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| dangling pointer created here
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:49:5
|
||||
|
|
||||
LL | fn with_block() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 0;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | &{ x }
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:57:13
|
||||
|
|
||||
LL | fn with_many_blocks() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 0;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
...
|
||||
LL | / &{
|
||||
LL | |
|
||||
LL | | { x }
|
||||
LL | | }
|
||||
| |_____________^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:67:12
|
||||
|
|
||||
LL | fn simple_return() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | let x = 0;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | return &x;
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:73:12
|
||||
|
|
||||
LL | fn return_mut() -> *mut u8 {
|
||||
| ------- return type of the function is `*mut u8`
|
||||
LL | let mut x = 0;
|
||||
| ----- `x` is part the function and will be dropped at the end of the function
|
||||
LL | return &mut x;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:80:16
|
||||
|
|
||||
LL | fn const_and_flow() -> *const u8 {
|
||||
| --------- return type of the function is `*const u8`
|
||||
LL | if false {
|
||||
LL | let x = 8;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | return &x;
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:88:5
|
||||
|
|
||||
LL | fn vector<T: Default>() -> *const Vec<T> {
|
||||
| ------------- return type of the function is `*const Vec<T>`
|
||||
LL | let x = vec![T::default()];
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | &x
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `Vec<T>` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:94:12
|
||||
|
|
||||
LL | fn local_adt() -> *const Adt {
|
||||
| ---------- return type of the function is `*const Adt`
|
||||
LL | let x = Adt(5);
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | return &x;
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:101:16
|
||||
|
|
||||
LL | let _x = || -> *const u8 {
|
||||
| --------- return type of the closure is `*const u8`
|
||||
LL | let x = 8;
|
||||
| - `x` is part the closure and will be dropped at the end of the closure
|
||||
LL | return &x;
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the closure because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `x` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:113:5
|
||||
|
|
||||
LL | fn fn_ptr() -> *const fn() -> u8 {
|
||||
| ----------------- return type of the function is `*const fn() -> u8`
|
||||
...
|
||||
LL | let x = ret_u8 as fn() -> u8;
|
||||
| - `x` is part the function and will be dropped at the end of the function
|
||||
LL | &x
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `a` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:118:5
|
||||
|
|
||||
LL | fn as_arg(a: Adt) -> *const Adt {
|
||||
| - ---------- return type of the function is `*const Adt`
|
||||
| |
|
||||
| `a` is part the function and will be dropped at the end of the function
|
||||
LL | &a
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `a` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:123:5
|
||||
|
|
||||
LL | fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 {
|
||||
| - ----------------- return type of the function is `*const fn() -> u8`
|
||||
| |
|
||||
| `a` is part the function and will be dropped at the end of the function
|
||||
LL | &a
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `a` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:128:5
|
||||
|
|
||||
LL | fn ptr_as_arg(a: *const Adt) -> *const *const Adt {
|
||||
| - ----------------- return type of the function is `*const *const Adt`
|
||||
| |
|
||||
| `a` is part the function and will be dropped at the end of the function
|
||||
LL | &a
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `*const Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: a dangling pointer will be produced because the local variable `a` will be dropped
|
||||
--> $DIR/dangling-pointers-from-locals.rs:133:5
|
||||
|
|
||||
LL | fn adt_as_arg(a: &Adt) -> *const &Adt {
|
||||
| - ----------- return type of the function is `*const &Adt`
|
||||
| |
|
||||
| `a` is part the function and will be dropped at the end of the function
|
||||
LL | &a
|
||||
| ^^
|
||||
|
|
||||
= note: pointers do not have a lifetime; after returning, the `&Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
|
||||
|
||||
warning: 19 warnings emitted
|
||||
|
||||
Reference in New Issue
Block a user