diff options
30 files changed, 549 insertions, 133 deletions
diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 0e0bdf17389..6f75419c387 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -1,7 +1,7 @@ use super::ResolverAstLoweringExt; use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; use rustc_ast::{GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind}; -use rustc_hir::def::LifetimeRes; +use rustc_hir::def::{DefKind, LifetimeRes, Res}; use rustc_middle::span_bug; use rustc_middle::ty::ResolverAstLowering; use rustc_span::symbol::{kw, Ident}; @@ -77,7 +77,20 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { } fn visit_ty(&mut self, t: &'ast Ty) { - match t.kind { + match &t.kind { + TyKind::Path(None, _) => { + // We can sometimes encounter bare trait objects + // which are represented in AST as paths. + if let Some(partial_res) = self.resolver.get_partial_res(t.id) + && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res() + { + self.current_binders.push(t.id); + visit::walk_ty(self, t); + self.current_binders.pop(); + } else { + visit::walk_ty(self, t); + } + } TyKind::BareFn(_) => { self.current_binders.push(t.id); visit::walk_ty(self, t); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index f577f653ccd..7bed3fa6150 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,7 +2,6 @@ #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(if_let_guard)] -#![feature(int_roundings)] #![feature(let_chains)] #![feature(negative_impls)] #![feature(never_type)] diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2c9d212a6a6..5910dc2edef 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2215,7 +2215,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,compile_fail + /// ```rust /// #![feature(rustc_attrs)] /// ``` /// @@ -2226,7 +2226,7 @@ declare_lint! { /// These features are an implementation detail of the compiler and standard /// library and are not supposed to be used in user code. pub INTERNAL_FEATURES, - Deny, + Warn, "internal features are not supposed to be used" } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4e639a54cf7..6c8ef34063f 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1717,13 +1717,7 @@ impl<'a> Parser<'a> { self.recover_await_prefix(await_sp)? }; let sp = self.error_on_incorrect_await(lo, hi, &expr, is_question); - let kind = match expr.kind { - // Avoid knock-down errors as we don't know whether to interpret this as `foo().await?` - // or `foo()?.await` (the very reason we went with postfix syntax 😅). - ExprKind::Try(_) => ExprKind::Err, - _ => ExprKind::Await(expr, await_sp), - }; - let expr = self.mk_expr(lo.to(sp), kind); + let expr = self.mk_expr(lo.to(sp), ExprKind::Err); self.maybe_recover_from_bad_qpath(expr) } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 07b437f463f..2936c8fac7d 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -4,6 +4,7 @@ use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use itertools::Itertools; +use rustc_data_structures::unord::UnordSet; use rustc_errors::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; @@ -42,8 +43,16 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { ) } +/// Determine if a work from the worklist is coming from the a `#[allow]` +/// or a `#[expect]` of `dead_code` +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +enum ComesFromAllowExpect { + Yes, + No, +} + struct MarkSymbolVisitor<'tcx> { - worklist: Vec<LocalDefId>, + worklist: Vec<(LocalDefId, ComesFromAllowExpect)>, tcx: TyCtxt<'tcx>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, live_symbols: LocalDefIdSet, @@ -72,7 +81,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn check_def_id(&mut self, def_id: DefId) { if let Some(def_id) = def_id.as_local() { if should_explore(self.tcx, def_id) || self.struct_constructors.contains_key(&def_id) { - self.worklist.push(def_id); + self.worklist.push((def_id, ComesFromAllowExpect::No)); } self.live_symbols.insert(def_id); } @@ -269,12 +278,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } fn mark_live_symbols(&mut self) { - let mut scanned = LocalDefIdSet::default(); - while let Some(id) = self.worklist.pop() { - if !scanned.insert(id) { + let mut scanned = UnordSet::default(); + while let Some(work) = self.worklist.pop() { + if !scanned.insert(work) { continue; } + let (id, comes_from_allow_expect) = work; + // Avoid accessing the HIR for the synthesized associated type generated for RPITITs. if self.tcx.is_impl_trait_in_trait(id.to_def_id()) { self.live_symbols.insert(id); @@ -286,7 +297,30 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { let id = self.struct_constructors.get(&id).copied().unwrap_or(id); if let Some(node) = self.tcx.hir().find_by_def_id(id) { - self.live_symbols.insert(id); + // When using `#[allow]` or `#[expect]` of `dead_code`, we do a QOL improvement + // by declaring fn calls, statics, ... within said items as live, as well as + // the item itself, although technically this is not the case. + // + // This means that the lint for said items will never be fired. + // + // This doesn't make any difference for the item declared with `#[allow]`, as + // the lint firing will be a nop, as it will be silenced by the `#[allow]` of + // the item. + // + // However, for `#[expect]`, the presence or absence of the lint is relevant, + // so we don't add it to the list of live symbols when it comes from a + // `#[expect]`. This means that we will correctly report an item as live or not + // for the `#[expect]` case. + // + // Note that an item can and will be duplicated on the worklist with different + // `ComesFromAllowExpect`, particulary if it was added from the + // `effective_visibilities` query or from the `#[allow]`/`#[expect]` checks, + // this "duplication" is essential as otherwise a function with `#[expect]` + // called from a `pub fn` may be falsely reported as not live, falsely + // triggering the `unfulfilled_lint_expectations` lint. + if comes_from_allow_expect != ComesFromAllowExpect::Yes { + self.live_symbols.insert(id); + } self.visit_node(node); } } @@ -513,16 +547,20 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { } } -fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { +fn has_allow_dead_code_or_lang_attr( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> Option<ComesFromAllowExpect> { fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { tcx.has_attr(def_id, sym::lang) // Stable attribute for #[lang = "panic_impl"] || tcx.has_attr(def_id, sym::panic_handler) } - fn has_allow_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow + let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + matches!(lint_level, lint::Allow | lint::Expect(_)) } fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { @@ -537,9 +575,13 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool } } - has_allow_dead_code(tcx, def_id) - || has_used_like_attr(tcx, def_id) - || has_lang_attr(tcx, def_id) + if has_allow_expect_dead_code(tcx, def_id) { + Some(ComesFromAllowExpect::Yes) + } else if has_used_like_attr(tcx, def_id) || has_lang_attr(tcx, def_id) { + Some(ComesFromAllowExpect::No) + } else { + None + } } // These check_* functions seeds items that @@ -557,21 +599,23 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool // * Implementations of traits and trait methods fn check_item<'tcx>( tcx: TyCtxt<'tcx>, - worklist: &mut Vec<LocalDefId>, + worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, struct_constructors: &mut LocalDefIdMap<LocalDefId>, id: hir::ItemId, ) { let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id); - if allow_dead_code { - worklist.push(id.owner_id.def_id); + if let Some(comes_from_allow) = allow_dead_code { + worklist.push((id.owner_id.def_id, comes_from_allow)); } match tcx.def_kind(id.owner_id) { DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { - if allow_dead_code { - worklist.extend(enum_def.variants.iter().map(|variant| variant.def_id)); + if let Some(comes_from_allow) = allow_dead_code { + worklist.extend( + enum_def.variants.iter().map(|variant| (variant.def_id, comes_from_allow)), + ); } for variant in enum_def.variants { @@ -583,7 +627,7 @@ fn check_item<'tcx>( } DefKind::Impl { of_trait } => { if of_trait { - worklist.push(id.owner_id.def_id); + worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No)); } // get DefIds from another query @@ -594,8 +638,10 @@ fn check_item<'tcx>( // And we access the Map here to get HirId from LocalDefId for id in local_def_ids { - if of_trait || has_allow_dead_code_or_lang_attr(tcx, id) { - worklist.push(id); + if of_trait { + worklist.push((id, ComesFromAllowExpect::No)); + } else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) { + worklist.push((id, comes_from_allow)); } } } @@ -609,43 +655,59 @@ fn check_item<'tcx>( } DefKind::GlobalAsm => { // global_asm! is always live. - worklist.push(id.owner_id.def_id); + worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No)); } _ => {} } } -fn check_trait_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::TraitItemId) { +fn check_trait_item( + tcx: TyCtxt<'_>, + worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, + id: hir::TraitItemId, +) { use hir::TraitItemKind::{Const, Fn}; if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) - && has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) + && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) { - worklist.push(trait_item.owner_id.def_id); + worklist.push((trait_item.owner_id.def_id, comes_from_allow)); } } } -fn check_foreign_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::ForeignItemId) { +fn check_foreign_item( + tcx: TyCtxt<'_>, + worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, + id: hir::ForeignItemId, +) { if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn) - && has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id) + && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id) { - worklist.push(id.owner_id.def_id); + worklist.push((id.owner_id.def_id, comes_from_allow)); } } -fn create_and_seed_worklist(tcx: TyCtxt<'_>) -> (Vec<LocalDefId>, LocalDefIdMap<LocalDefId>) { +fn create_and_seed_worklist( + tcx: TyCtxt<'_>, +) -> (Vec<(LocalDefId, ComesFromAllowExpect)>, LocalDefIdMap<LocalDefId>) { let effective_visibilities = &tcx.effective_visibilities(()); // see `MarkSymbolVisitor::struct_constructors` let mut struct_constructors = Default::default(); let mut worklist = effective_visibilities .iter() .filter_map(|(&id, effective_vis)| { - effective_vis.is_public_at_level(Level::Reachable).then_some(id) + effective_vis + .is_public_at_level(Level::Reachable) + .then_some(id) + .map(|id| (id, ComesFromAllowExpect::No)) }) // Seed entry point - .chain(tcx.entry_fn(()).and_then(|(def_id, _)| def_id.as_local())) + .chain( + tcx.entry_fn(()) + .and_then(|(def_id, _)| def_id.as_local().map(|id| (id, ComesFromAllowExpect::No))), + ) .collect::<Vec<_>>(); let crate_items = tcx.hir_crate_items(()); @@ -878,9 +940,7 @@ impl<'tcx> DeadVisitor<'tcx> { return true; }; - self.live_symbols.contains(&def_id) - || has_allow_dead_code_or_lang_attr(self.tcx, def_id) - || name.as_str().starts_with('_') + self.live_symbols.contains(&def_id) || name.as_str().starts_with('_') } } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 6ab473c3b54..bc12422e7d7 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1165,7 +1165,9 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { let const_val = tables.tcx.valtree_to_const_val((c.ty(), val)); stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables)) } - _ => todo!(), + ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(¶m)), + ty::ErrorCt(_) => unreachable!(), + _ => unimplemented!(), }, ConstantKind::Unevaluated(unev_const, ty) => { stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 8a23af75749..875d5ae70da 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -417,6 +417,7 @@ pub fn allocation_filter<'tcx>( pub enum ConstantKind { Allocated(Allocation), Unevaluated(UnevaluatedConst), + ParamCt(Opaque), } #[derive(Clone, Debug)] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 6f6b6dbb80b..2136d29255f 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2074,10 +2074,10 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// #![feature(int_roundings)] #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")] /// ``` - #[unstable(feature = "int_roundings", issue = "88581")] + #[stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2109,11 +2109,11 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// #![feature(int_roundings)] #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")] #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")] /// ``` - #[unstable(feature = "int_roundings", issue = "88581")] + #[stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2134,13 +2134,13 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// #![feature(int_roundings)] #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")] #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")] #[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")] /// ``` - #[unstable(feature = "int_roundings", issue = "88581")] + #[stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_roundings1", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/std/src/env.rs b/library/std/src/env.rs index d372fa64065..f3122c2931d 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -178,7 +178,8 @@ impl Iterator for Vars { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Vars { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Vars").finish_non_exhaustive() + let Self { inner: VarsOs { inner } } = self; + f.debug_struct("Vars").field("inner", &inner.str_debug()).finish() } } @@ -196,7 +197,8 @@ impl Iterator for VarsOs { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for VarsOs { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("VarOs").finish_non_exhaustive() + let Self { inner } = self; + f.debug_struct("VarsOs").field("inner", inner).finish() } } @@ -829,7 +831,8 @@ impl DoubleEndedIterator for Args { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Args").field("inner", &self.inner.inner).finish() + let Self { inner: ArgsOs { inner } } = self; + f.debug_struct("Args").field("inner", inner).finish() } } @@ -870,7 +873,8 @@ impl DoubleEndedIterator for ArgsOs { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ArgsOs { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ArgsOs").field("inner", &self.inner).finish() + let Self { inner } = self; + f.debug_struct("ArgsOs").field("inner", inner).finish() } } diff --git a/library/std/src/env/tests.rs b/library/std/src/env/tests.rs index 94cace03af6..55869229581 100644 --- a/library/std/src/env/tests.rs +++ b/library/std/src/env/tests.rs @@ -95,8 +95,28 @@ fn args_debug() { format!("Args {{ inner: {:?} }}", args().collect::<Vec<_>>()), format!("{:?}", args()) ); +} + +#[test] +fn args_os_debug() { assert_eq!( format!("ArgsOs {{ inner: {:?} }}", args_os().collect::<Vec<_>>()), format!("{:?}", args_os()) ); } + +#[test] +fn vars_debug() { + assert_eq!( + format!("Vars {{ inner: {:?} }}", vars().collect::<Vec<_>>()), + format!("{:?}", vars()) + ); +} + +#[test] +fn vars_os_debug() { + assert_eq!( + format!("VarsOs {{ inner: {:?} }}", vars_os().collect::<Vec<_>>()), + format!("{:?}", vars_os()) + ); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 9038e8fa9d7..6f58e5a0f05 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -293,7 +293,6 @@ #![feature(float_next_up_down)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] -#![feature(int_roundings)] #![feature(ip)] #![feature(ip_in_core)] #![feature(maybe_uninit_slice)] diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index e53dbae6119..c79197a9ad1 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -112,6 +112,34 @@ pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. +pub struct EnvStrDebug<'a> { + slice: &'a [(OsString, OsString)], +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { slice } = self; + f.debug_list() + .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) + .finish() + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self { iter } = self; + EnvStrDebug { slice: iter.as_slice() } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + f.debug_list().entries(iter.as_slice()).finish() + } +} + impl !Send for Env {} impl !Sync for Env {} diff --git a/library/std/src/sys/sgx/os.rs b/library/std/src/sys/sgx/os.rs index 5da0257f35d..86f4c7d3d56 100644 --- a/library/std/src/sys/sgx/os.rs +++ b/library/std/src/sys/sgx/os.rs @@ -96,14 +96,61 @@ fn create_env_store() -> &'static EnvStore { unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) } } -pub type Env = vec::IntoIter<(OsString, OsString)>; +pub struct Env { + iter: vec::IntoIter<(OsString, OsString)>, +} + +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. +pub struct EnvStrDebug<'a> { + slice: &'a [(OsString, OsString)], +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { slice } = self; + f.debug_list() + .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) + .finish() + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self { iter } = self; + EnvStrDebug { slice: iter.as_slice() } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + f.debug_list().entries(iter.as_slice()).finish() + } +} + +impl !Send for Env {} +impl !Sync for Env {} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} pub fn env() -> Env { let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> { map.iter().map(|(k, v)| (k.clone(), v.clone())).collect() }; - get_env_store().map(|env| clone_to_vec(&env.lock().unwrap())).unwrap_or_default().into_iter() + let iter = get_env_store() + .map(|env| clone_to_vec(&env.lock().unwrap())) + .unwrap_or_default() + .into_iter(); + Env { iter } } pub fn getenv(k: &OsStr) -> Option<OsString> { diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs index 6135921f0b5..717c08434a8 100644 --- a/library/std/src/sys/solid/os.rs +++ b/library/std/src/sys/solid/os.rs @@ -85,6 +85,34 @@ pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. +pub struct EnvStrDebug<'a> { + slice: &'a [(OsString, OsString)], +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { slice } = self; + f.debug_list() + .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) + .finish() + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self { iter } = self; + EnvStrDebug { slice: iter.as_slice() } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + f.debug_list().entries(iter.as_slice()).finish() + } +} + impl !Send for Env {} impl !Sync for Env {} diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index a68c14758ff..215f63d04f7 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -495,6 +495,34 @@ pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. +pub struct EnvStrDebug<'a> { + slice: &'a [(OsString, OsString)], +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { slice } = self; + f.debug_list() + .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) + .finish() + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self { iter } = self; + EnvStrDebug { slice: iter.as_slice() } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + f.debug_list().entries(iter.as_slice()).finish() + } +} + impl !Send for Env {} impl !Sync for Env {} diff --git a/library/std/src/sys/unsupported/os.rs b/library/std/src/sys/unsupported/os.rs index e150ae143ad..248b34829f2 100644 --- a/library/std/src/sys/unsupported/os.rs +++ b/library/std/src/sys/unsupported/os.rs @@ -65,10 +65,26 @@ pub fn current_exe() -> io::Result<PathBuf> { pub struct Env(!); +impl Env { + // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self(inner) = self; + match *inner {} + } +} + +impl fmt::Debug for Env { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self(inner) = self; + match *inner {} + } +} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { - self.0 + let Self(inner) = self; + match *inner {} } } diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs index 197bdeda4fb..e0de284c5e2 100644 --- a/library/std/src/sys/wasi/os.rs +++ b/library/std/src/sys/wasi/os.rs @@ -142,10 +142,39 @@ impl StdError for JoinPathsError { pub fn current_exe() -> io::Result<PathBuf> { unsupported() } + pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. +pub struct EnvStrDebug<'a> { + slice: &'a [(OsString, OsString)], +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { slice } = self; + f.debug_list() + .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) + .finish() + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self { iter } = self; + EnvStrDebug { slice: iter.as_slice() } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + f.debug_list().entries(iter.as_slice()).finish() + } +} + impl !Send for Env {} impl !Sync for Env {} diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index d7adeb266ed..2329426ad1d 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -85,25 +85,69 @@ pub fn error_string(mut errnum: i32) -> String { pub struct Env { base: c::LPWCH, - cur: c::LPWCH, + iter: EnvIterator, +} + +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. +pub struct EnvStrDebug<'a> { + iter: &'a EnvIterator, +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + let iter: EnvIterator = (*iter).clone(); + let mut list = f.debug_list(); + for (a, b) in iter { + list.entry(&(a.to_str().unwrap(), b.to_str().unwrap())); + } + list.finish() + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self { base: _, iter } = self; + EnvStrDebug { iter } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { base: _, iter } = self; + f.debug_list().entries(iter.clone()).finish() + } } impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { + let Self { base: _, iter } = self; + iter.next() + } +} + +#[derive(Clone)] +struct EnvIterator(c::LPWCH); + +impl Iterator for EnvIterator { + type Item = (OsString, OsString); + + fn next(&mut self) -> Option<(OsString, OsString)> { + let Self(cur) = self; loop { unsafe { - if *self.cur == 0 { + if **cur == 0 { return None; } - let p = self.cur as *const u16; + let p = *cur as *const u16; let mut len = 0; while *p.add(len) != 0 { len += 1; } let s = slice::from_raw_parts(p, len); - self.cur = self.cur.add(len + 1); + *cur = cur.add(len + 1); // Windows allows environment variables to start with an equals // symbol (in any other position, this is the separator between @@ -137,7 +181,7 @@ pub fn env() -> Env { if ch.is_null() { panic!("failure getting env string from OS: {}", io::Error::last_os_error()); } - Env { base: ch, cur: ch } + Env { base: ch, iter: EnvIterator(ch) } } } diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs index 554ac673d51..ab675d0a1a6 100644 --- a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs @@ -49,13 +49,11 @@ async fn foo8() -> Result<(), ()> { Ok(()) } fn foo9() -> Result<(), ()> { - let _ = await bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks - //~^ ERROR incorrect use of `await` + let _ = await bar(); //~ ERROR incorrect use of `await` Ok(()) } fn foo10() -> Result<(), ()> { - let _ = await? bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks - //~^ ERROR incorrect use of `await` + let _ = await? bar(); //~ ERROR incorrect use of `await` Ok(()) } fn foo11() -> Result<(), ()> { @@ -63,8 +61,7 @@ fn foo11() -> Result<(), ()> { Ok(()) } fn foo12() -> Result<(), ()> { - let _ = (await bar())?; //~ ERROR `await` is only allowed inside `async` functions and blocks - //~^ ERROR incorrect use of `await` + let _ = (await bar())?; //~ ERROR incorrect use of `await` Ok(()) } fn foo13() -> Result<(), ()> { @@ -111,7 +108,6 @@ async fn foo27() -> Result<(), ()> { fn foo28() -> Result<(), ()> { fn foo() -> Result<(), ()> { let _ = await!(bar())?; //~ ERROR incorrect use of `await` - //~^ ERROR `await` is only allowed inside `async` functions Ok(()) } foo() @@ -119,7 +115,6 @@ fn foo28() -> Result<(), ()> { fn foo29() -> Result<(), ()> { let foo = || { let _ = await!(bar())?; //~ ERROR incorrect use of `await` - //~^ ERROR `await` is only allowed inside `async` functions Ok(()) }; foo() diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 7b03e56662a..928eb0b821d 100644 --- a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -59,61 +59,61 @@ LL | let _ = await bar(); | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:57:13 + --> $DIR/incorrect-syntax-suggestions.rs:56:13 | LL | let _ = await? bar(); | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:62:13 + --> $DIR/incorrect-syntax-suggestions.rs:60:13 | LL | let _ = await bar()?; | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:66:14 + --> $DIR/incorrect-syntax-suggestions.rs:64:14 | LL | let _ = (await bar())?; | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:71:24 + --> $DIR/incorrect-syntax-suggestions.rs:68:24 | LL | let _ = bar().await(); | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:76:24 + --> $DIR/incorrect-syntax-suggestions.rs:73:24 | LL | let _ = bar().await()?; | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:104:13 + --> $DIR/incorrect-syntax-suggestions.rs:101:13 | LL | let _ = await!(bar()); | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:108:13 + --> $DIR/incorrect-syntax-suggestions.rs:105:13 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:113:17 + --> $DIR/incorrect-syntax-suggestions.rs:110:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:121:17 + --> $DIR/incorrect-syntax-suggestions.rs:117:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: expected expression, found `=>` - --> $DIR/incorrect-syntax-suggestions.rs:129:25 + --> $DIR/incorrect-syntax-suggestions.rs:124:25 | LL | match await { await => () } | ----- ^^ expected expression @@ -121,13 +121,13 @@ LL | match await { await => () } | while parsing this incorrect await expression error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:129:11 + --> $DIR/incorrect-syntax-suggestions.rs:124:11 | LL | match await { await => () } | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await` error: expected one of `.`, `?`, `{`, or an operator, found `}` - --> $DIR/incorrect-syntax-suggestions.rs:132:1 + --> $DIR/incorrect-syntax-suggestions.rs:127:1 | LL | match await { await => () } | ----- - expected one of `.`, `?`, `{`, or an operator @@ -138,31 +138,7 @@ LL | } | ^ unexpected token error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:52:13 - | -LL | fn foo9() -> Result<(), ()> { - | ---- this is not `async` -LL | let _ = await bar(); - | ^^^^^ only allowed inside `async` functions and blocks - -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:57:13 - | -LL | fn foo10() -> Result<(), ()> { - | ----- this is not `async` -LL | let _ = await? bar(); - | ^^^^^ only allowed inside `async` functions and blocks - -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:66:14 - | -LL | fn foo12() -> Result<(), ()> { - | ----- this is not `async` -LL | let _ = (await bar())?; - | ^^^^^ only allowed inside `async` functions and blocks - -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:71:19 + --> $DIR/incorrect-syntax-suggestions.rs:68:19 | LL | fn foo13() -> Result<(), ()> { | ----- this is not `async` @@ -170,7 +146,7 @@ LL | let _ = bar().await(); | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:76:19 + --> $DIR/incorrect-syntax-suggestions.rs:73:19 | LL | fn foo14() -> Result<(), ()> { | ----- this is not `async` @@ -178,7 +154,7 @@ LL | let _ = bar().await()?; | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:81:19 + --> $DIR/incorrect-syntax-suggestions.rs:78:19 | LL | fn foo15() -> Result<(), ()> { | ----- this is not `async` @@ -186,7 +162,7 @@ LL | let _ = bar().await; | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:85:19 + --> $DIR/incorrect-syntax-suggestions.rs:82:19 | LL | fn foo16() -> Result<(), ()> { | ----- this is not `async` @@ -194,7 +170,7 @@ LL | let _ = bar().await?; | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:90:23 + --> $DIR/incorrect-syntax-suggestions.rs:87:23 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -202,29 +178,13 @@ LL | let _ = bar().await?; | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:97:23 + --> $DIR/incorrect-syntax-suggestions.rs:94:23 | LL | let foo = || { | -- this is not `async` LL | let _ = bar().await?; | ^^^^^ only allowed inside `async` functions and blocks -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:113:17 - | -LL | fn foo() -> Result<(), ()> { - | --- this is not `async` -LL | let _ = await!(bar())?; - | ^^^^^ only allowed inside `async` functions and blocks - -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:121:17 - | -LL | let foo = || { - | -- this is not `async` -LL | let _ = await!(bar())?; - | ^^^^^ only allowed inside `async` functions and blocks - -error: aborting due to 33 previous errors +error: aborting due to 28 previous errors For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs new file mode 100644 index 00000000000..57d68849251 --- /dev/null +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs @@ -0,0 +1,22 @@ +// edition:2015 +// check-pass +// issue: 114664 + +fn ice() -> impl AsRef<Fn(&())> { + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + Foo +} + +struct Foo; +impl AsRef<dyn Fn(&())> for Foo { + fn as_ref(&self) -> &(dyn for<'a> Fn(&'a ()) + 'static) { + todo!() + } +} + +pub fn main() {} diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr new file mode 100644 index 00000000000..fad0b812d43 --- /dev/null +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 + | +LL | fn ice() -> impl AsRef<Fn(&())> { + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | fn ice() -> impl AsRef<dyn Fn(&())> { + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 + | +LL | fn ice() -> impl AsRef<Fn(&())> { + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | fn ice() -> impl AsRef<dyn Fn(&())> { + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 + | +LL | fn ice() -> impl AsRef<Fn(&())> { + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | fn ice() -> impl AsRef<dyn Fn(&())> { + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs new file mode 100644 index 00000000000..b71bcd0fab5 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs @@ -0,0 +1,19 @@ +// check-pass + +// this test checks that the `dead_code` lint is *NOT* being emited +// for `foo` as `foo` is being used by `main`, and so the `#[expect]` +// is unfulfilled +// +// it also checks that the `dead_code` lint is also *NOT* emited +// for `bar` as it's suppresed by the `#[expect]` on `bar` + +#![feature(lint_reasons)] +#![warn(dead_code)] // to override compiletest + +fn bar() {} + +#[expect(dead_code)] +//~^ WARN this lint expectation is unfulfilled +fn foo() { bar() } + +fn main() { foo() } diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr new file mode 100644 index 00000000000..d5c4dabed01 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/allow-or-expect-dead_code-114557-2.rs:15:10 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs new file mode 100644 index 00000000000..f8a5d31a0f2 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs @@ -0,0 +1,13 @@ +// check-pass + +// this test makes sure that the `unfulfilled_lint_expectations` lint +// is being emited for `foo` as foo is not dead code, it's pub + +#![feature(lint_reasons)] +#![warn(dead_code)] // to override compiletest + +#[expect(dead_code)] +//~^ WARN this lint expectation is unfulfilled +pub fn foo() {} + +fn main() {} diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr new file mode 100644 index 00000000000..c954a75b394 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/allow-or-expect-dead_code-114557-3.rs:9:10 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs new file mode 100644 index 00000000000..24fafa3d1b8 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs @@ -0,0 +1,18 @@ +// check-pass +// revisions: allow expect + +// this test checks that no matter if we put #[allow(dead_code)] +// or #[expect(dead_code)], no warning is being emited + +#![feature(lint_reasons)] +#![warn(dead_code)] // to override compiletest + +fn f() {} + +#[cfg_attr(allow, allow(dead_code))] +#[cfg_attr(expect, expect(dead_code))] +fn g() { + f(); +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-113203.rs b/tests/ui/parser/issues/issue-113203.rs new file mode 100644 index 00000000000..1103251c140 --- /dev/null +++ b/tests/ui/parser/issues/issue-113203.rs @@ -0,0 +1,7 @@ +// Checks what happens when we attempt to use the await keyword as a prefix. Span +// incorrectly emitted an `.await` in E0277 which does not exist +// edition:2018 +fn main() { + await {}() + //~^ ERROR incorrect use of `await` +} diff --git a/tests/ui/parser/issues/issue-113203.stderr b/tests/ui/parser/issues/issue-113203.stderr new file mode 100644 index 00000000000..97304a89c9e --- /dev/null +++ b/tests/ui/parser/issues/issue-113203.stderr @@ -0,0 +1,8 @@ +error: incorrect use of `await` + --> $DIR/issue-113203.rs:5:5 + | +LL | await {}() + | ^^^^^^^^ help: `await` is a postfix operation: `{}.await` + +error: aborting due to previous error + diff --git a/triagebot.toml b/triagebot.toml index c513dce3f40..b2ea206a8a2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -490,7 +490,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "WaffleLapkin", "clubby789"] +users_on_vacation = ["jyn514", "WaffleLapkin", "clubby789", "oli-obk"] [assign.adhoc_groups] compiler-team = [ |
