diff --git a/Cargo.lock b/Cargo.lock index a966493f1397a..5a3906c470f77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4519,6 +4519,7 @@ name = "rustc_resolve" version = "0.0.0" dependencies = [ "bitflags", + "indexmap", "itertools", "pulldown-cmark", "rustc_arena", diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 47bebf5371a9a..23b40894f16d5 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -937,8 +937,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // (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 for more context. + Align::ONE } // Machine-specific extra functions currently do not support alignment restrictions. FnVal::Other(_) => Align::ONE, diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 69fe7fe83ffda..4d0c0c94a8138 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -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 diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 9e19949c3b6ee..af4457f4314b9 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -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 @@ declare_lint! { "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 @@ declare_lint! { #[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 `&` 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), + }, + ); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index fd8d0f832aa47..ef63c0dee8c2e 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -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, +} + // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] #[diag(lint_multiple_supertrait_upcastable)] diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 9ea9c58cfd17a..eb98a6e85c06b 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -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" } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 82eae08880382..d9671c43b3d8a 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -968,7 +968,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } 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 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // 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); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 3b57f6e883ae7..d18554bba1b17 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1098,7 +1098,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } 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 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); 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 diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 236b1404eebe3..c8ca57a380fef 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2476,19 +2476,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } 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 { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dbde6f7cfd7ed..6b034c5129f39 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1487,13 +1487,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut invocation_parents = FxHashMap::default(); invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT); - let mut extern_prelude: FxIndexMap> = 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 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option> { - 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 diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bd5b4e21baa0f..402634e49b37e 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -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 @@ impl const Default for 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, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 14042997bc2c3..1dddc48e68e97 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3974,8 +3974,9 @@ impl [T] { /// /// [`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 diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 7873049d20bfd..c2b0e43a3242f 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -696,14 +696,14 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { 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 @@ pub const fn begin_panic(msg: M) -> ! { 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 @@ pub fn rust_panic_without_hook(payload: Box) -> ! { 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"))] diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index dff981c900c08..8d3ab82ace120 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -2018,6 +2018,9 @@ fn _assert_sync_and_send() { /// 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 diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index ffc5dfad459db..8bee00a9c1376 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1663,7 +1663,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // 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 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the 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 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the 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. diff --git a/src/doc/rustc/src/platform-support/lynxos178.md b/src/doc/rustc/src/platform-support/lynxos178.md index 6463f95a0b8e0..121e11fb653c5 100644 --- a/src/doc/rustc/src/platform-support/lynxos178.md +++ b/src/doc/rustc/src/platform-support/lynxos178.md @@ -15,7 +15,7 @@ Target triples available: ## Target maintainers -- Renat Fatykhov, https://github.com/rfatykhov-lynx +[@rfatykhov-lynx](https://github.com/rfatykhov-lynx) ## Requirements diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index aceae3e3a3b9c..2d49b1a7097d0 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -279,6 +279,15 @@ pub struct Config { /// [`Self::rustc_path`]. pub stage0_rustc_path: Option, + /// 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, + /// Path to the `rustdoc`-under-test. Like [`Self::rustc_path`], this `rustdoc` is *staged*. pub rustdoc_path: Option, @@ -712,6 +721,7 @@ impl 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 = serde_json::from_str(&rustc_output( + let mut targets: HashMap = serde_json::from_str(&query_rustc_output( config, &["--print=all-target-specs-json", "-Zunstable-options"], Default::default(), @@ -950,7 +960,7 @@ impl 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 @@ impl TargetCfgs { // 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 { - rustc_output( + query_rustc_output( config, &["--print=check-cfg", "-Zunstable-options", "--check-cfg=cfg()"], Default::default(), @@ -1128,7 +1141,7 @@ pub const KNOWN_CRATE_TYPES: &[&str] = &["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]; fn supported_crate_types(config: &Config) -> HashSet { - 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 { crate_types } -fn rustc_output(config: &Config, args: &[&str], envs: HashMap) -> String { - let mut command = Command::new(&config.rustc_path); +fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap) -> 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"); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index c712185733c68..f5409e783418b 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -63,6 +63,12 @@ pub fn parse_config(args: Vec) -> 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 @@ pub fn parse_config(args: Vec) -> Config { 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(), diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr index deec81f7e51be..14b3be02a793c 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr index deec81f7e51be..14b3be02a793c 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/panic/abort_unwind.stderr b/src/tools/miri/tests/fail/panic/abort_unwind.stderr index 81d560c27ec71..35052f37dfcc7 100644 --- a/src/tools/miri/tests/fail/panic/abort_unwind.stderr +++ b/src/tools/miri/tests/fail/panic/abort_unwind.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index bc6cce93d41e4..3f1fbfef721c7 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr index 61bc9a7a49590..9aca2ed654f6d 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr index a7a42f8174e5e..425817d5f86c2 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr index ba1f11065ead1..a21e185219e6c 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr index 1464c1fcc7c96..a3cf5d72198b1 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr index b893220426c92..8295a581060d5 100644 --- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr +++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr index a0ee75e5dd27a..f0f305d76bc87 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.stderr +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr index 5fa485752a48f..216ae84512af0 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr +++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr @@ -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 diff --git a/src/tools/miri/tests/fail/validity/dangling_ref3.rs b/src/tools/miri/tests/fail/validity/dangling_ref3.rs index 8e8a75bd7ec04..0fecd8f1c285f 100644 --- a/src/tools/miri/tests/fail/validity/dangling_ref3.rs +++ b/src/tools/miri/tests/fail/validity/dangling_ref3.rs @@ -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 { diff --git a/src/tools/miri/tests/pass/fn_align.rs b/src/tools/miri/tests/pass/fn_align.rs deleted file mode 100644 index 9752d033458d3..0000000000000 --- a/src/tools/miri/tests/pass/fn_align.rs +++ /dev/null @@ -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)); -} diff --git a/tests/codegen-llvm/simd/extract-insert-dyn.rs b/tests/codegen-llvm/simd/extract-insert-dyn.rs index 729f0145314a3..9c17b82e55352 100644 --- a/tests/codegen-llvm/simd/extract-insert-dyn.rs +++ b/tests/codegen-llvm/simd/extract-insert-dyn.rs @@ -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 u32x16([u32; 16]); 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) } diff --git a/tests/debuginfo/basic-stepping.rs b/tests/debuginfo/basic-stepping.rs new file mode 100644 index 0000000000000..6e1344d22a50f --- /dev/null +++ b/tests/debuginfo/basic-stepping.rs @@ -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 . + +//@ 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; +} diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir index 2777bba893bbc..ba6ce0ee5286f 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir @@ -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::::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; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir index 2777bba893bbc..ba6ce0ee5286f 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir @@ -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::::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; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir index 2be0a478c852c..ba6ce0ee5286f 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir @@ -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::::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; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir index 2be0a478c852c..ba6ce0ee5286f 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir @@ -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::::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; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs index 11fb7afef0fb1..9ceba9444b8da 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs @@ -13,7 +13,6 @@ pub unsafe fn generic_in_place(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) } diff --git a/tests/ui/codegen/unsupported-static-initializer-in-const-array.rs b/tests/ui/codegen/unsupported-static-initializer-in-const-array.rs new file mode 100644 index 0000000000000..bc94130ee199a --- /dev/null +++ b/tests/ui/codegen/unsupported-static-initializer-in-const-array.rs @@ -0,0 +1,18 @@ +//! LLVM error with unsupported expression in static +//! initializer for const pointer in array on macOS. +//! +//! Regression test for . + +//@ 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); +} diff --git a/tests/ui/lint/dangling-pointers-from-locals.rs b/tests/ui/lint/dangling-pointers-from-locals.rs new file mode 100644 index 0000000000000..e321df2f42790 --- /dev/null +++ b/tests/ui/lint/dangling-pointers-from-locals.rs @@ -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() -> *const Vec { + 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() -> *const Option { + let x = Some(T::default()); + &x // can't compute layout of `Option`, so cnat' be sure it won't be a ZST +} + +fn generic() -> *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() {} diff --git a/tests/ui/lint/dangling-pointers-from-locals.stderr b/tests/ui/lint/dangling-pointers-from-locals.stderr new file mode 100644 index 0000000000000..e1d28bf22a0c1 --- /dev/null +++ b/tests/ui/lint/dangling-pointers-from-locals.stderr @@ -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() -> *const Vec { + | ------------- return type of the function is `*const Vec` +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` 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 +