diff options
| author | The Miri Cronjob Bot <miri@cron.bot> | 2024-09-02 05:12:42 +0000 |
|---|---|---|
| committer | The Miri Cronjob Bot <miri@cron.bot> | 2024-09-02 05:12:42 +0000 |
| commit | 9fe4539fa79358f4817503322c5cbb3fd6af5f09 (patch) | |
| tree | 0cabce5bc2445f5bd2bea6ed174d54736d5bd0e0 | |
| parent | 6c09243724aae85f3109a12913347d8affb1939b (diff) | |
| parent | e71f9529121ca8f687e4b725e3c9adc3f1ebab4d (diff) | |
| download | rust-9fe4539fa79358f4817503322c5cbb3fd6af5f09.tar.gz rust-9fe4539fa79358f4817503322c5cbb3fd6af5f09.zip | |
Merge from rustc
135 files changed, 1184 insertions, 1176 deletions
diff --git a/Cargo.lock b/Cargo.lock index 23c7a5bc60f..7244ae14fb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4978,15 +4978,15 @@ dependencies = [ [[package]] name = "stacker" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" dependencies = [ "cc", "cfg-if", "libc", "psm", - "winapi", + "windows-sys 0.59.0", ] [[package]] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index fe07ec48f1f..7b041768983 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -69,14 +69,14 @@ pub enum FnKind<'a> { Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>), /// E.g., `|x, y| body`. - Closure(&'a ClosureBinder, &'a FnDecl, &'a Expr), + Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr), } impl<'a> FnKind<'a> { pub fn header(&self) -> Option<&'a FnHeader> { match *self { FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header), - FnKind::Closure(_, _, _) => None, + FnKind::Closure(..) => None, } } @@ -90,7 +90,7 @@ impl<'a> FnKind<'a> { pub fn decl(&self) -> &'a FnDecl { match self { FnKind::Fn(_, _, sig, _, _, _) => &sig.decl, - FnKind::Closure(_, decl, _) => decl, + FnKind::Closure(_, _, decl, _) => decl, } } @@ -839,7 +839,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu try_visit!(walk_fn_decl(visitor, decl)); visit_opt!(visitor, visit_block, body); } - FnKind::Closure(binder, decl, body) => { + FnKind::Closure(binder, _coroutine_kind, decl, body) => { try_visit!(visitor.visit_closure_binder(binder)); try_visit!(walk_fn_decl(visitor, decl)); try_visit!(visitor.visit_expr(body)); @@ -1107,7 +1107,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V ExprKind::Closure(box Closure { binder, capture_clause, - coroutine_kind: _, + coroutine_kind, constness: _, movability: _, fn_decl, @@ -1116,7 +1116,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V fn_arg_span: _, }) => { try_visit!(visitor.visit_capture_by(capture_clause)); - try_visit!(visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id)) + try_visit!(visitor.visit_fn( + FnKind::Closure(binder, coroutine_kind, fn_decl, body), + *span, + *id + )) } ExprKind::Block(block, opt_label) => { visit_opt!(visitor, visit_label, opt_label); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bcc2c29a2ff..754fbae4d02 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,7 +45,6 @@ use std::collections::hash_map::Entry; use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; use rustc_ast::{self as ast, *}; -use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxIndexSet; @@ -837,7 +836,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) } - LifetimeRes::Static | LifetimeRes::Error => return None, + LifetimeRes::Static { .. } | LifetimeRes::Error => return None, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, ident.span @@ -1399,24 +1398,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span }); } - let span = t.span; - - // HACK: pprust breaks strings with newlines when the type - // gets too long. We don't want these to show up in compiler - // output or built artifacts, so replace them here... - // Perhaps we should instead format APITs more robustly. - let ident = Ident::from_str_and_span( - &pprust::ty_to_string(t).replace('\n', " "), - span, - ); - - self.create_def( - self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? - *def_node_id, - ident.name, - DefKind::TyParam, - span, - ); + let def_id = self.local_def_id(*def_node_id); + let name = self.tcx.item_name(def_id.to_def_id()); + let ident = Ident::new(name, span); let (param, bounds, path) = self.lower_universal_param_and_bounds( *def_node_id, span, @@ -1618,13 +1602,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_span: Span, lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>], ) -> hir::TyKind<'hir> { - let opaque_ty_def_id = self.create_def( - self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? - opaque_ty_node_id, - kw::Empty, - DefKind::OpaqueTy, - opaque_ty_span, - ); + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); debug!(?opaque_ty_def_id); // Map from captured (old) lifetime to synthetic (new) lifetime. @@ -1656,7 +1634,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Opaques do not capture `'static` - LifetimeRes::Static | LifetimeRes::Error => { + LifetimeRes::Static { .. } | LifetimeRes::Error => { continue; } @@ -2069,7 +2047,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::LifetimeName::Param(param) } LifetimeRes::Infer => hir::LifetimeName::Infer, - LifetimeRes::Static => hir::LifetimeName::Static, + LifetimeRes::Static { .. } => hir::LifetimeName::Static, LifetimeRes::Error => hir::LifetimeName::Error, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 77cc2a36a53..76c957afa54 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -27,7 +27,7 @@ impl<'ast> LifetimeCollectVisitor<'ast> { self.collected_lifetimes.insert(lifetime); } } - LifetimeRes::Static | LifetimeRes::Error => { + LifetimeRes::Static { .. } | LifetimeRes::Error => { self.collected_lifetimes.insert(lifetime); } LifetimeRes::Infer => {} diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a9b65456b8c..ed9672a9e79 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1485,7 +1485,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let disallowed = (!tilde_const_allowed).then(|| match fk { FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span }, - FnKind::Closure(_, _, _) => TildeConstReason::Closure, + FnKind::Closure(..) => TildeConstReason::Closure, }); self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 209750d6ba6..4ab20c154cc 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,6 +1,5 @@ use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage}; use rustc_hir as hir; @@ -9,7 +8,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_hir::{lang_items, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, }; use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; @@ -18,7 +17,6 @@ use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; -use rustc_target::abi::VariantIdx; use rustc_target::spec::{abi, SanitizerSet}; use crate::errors; @@ -80,13 +78,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; - let fn_sig_outer = || { - use DefKind::*; - - let def_kind = tcx.def_kind(did); - if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None } - }; - for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` // pass that check that they aren't used anywhere else, rather this module. @@ -94,12 +85,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. let fn_sig = || { - let sig = fn_sig_outer(); - if sig.is_none() { + use DefKind::*; + + let def_kind = tcx.def_kind(did); + if let Fn | AssocFn | Variant | Ctor(..) = def_kind { + Some(tcx.fn_sig(did)) + } else { tcx.dcx() .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); + None } - sig }; let Some(Ident { name, .. }) = attr.ident() else { @@ -618,93 +613,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - if let Some(sig) = fn_sig_outer() { - // Collect target features from types reachable from arguments. - // We define a type as "reachable" if: - // - it is a function argument - // - it is a field of a reachable struct - // - there is a reachable reference to it - // FIXME(struct_target_features): we may want to cache the result of this computation. - let mut visited_types = FxHashSet::default(); - let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned(); - let mut additional_tf = vec![]; - - while let Some(ty) = reachable_types.pop() { - if visited_types.contains(&ty) { - continue; - } - visited_types.insert(ty); - match ty.kind() { - ty::Alias(..) => { - if let Ok(t) = - tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty) - { - reachable_types.push(t) - } - } - - ty::Ref(_, inner, _) => reachable_types.push(*inner), - ty::Tuple(tys) => reachable_types.extend(tys.iter()), - ty::Adt(adt_def, args) => { - additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did())); - // This only recurses into structs as i.e. an Option<TargetFeature> is an ADT - // that doesn't actually always contain a TargetFeature. - if adt_def.is_struct() { - reachable_types.extend( - adt_def - .variant(VariantIdx::from_usize(0)) - .fields - .iter() - .map(|field| field.ty(tcx, args)), - ); - } - } - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Foreign(..) - | ty::Str - | ty::Array(..) - | ty::Pat(..) - | ty::Slice(..) - | ty::RawPtr(..) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::Dynamic(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Param(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Infer(..) - | ty::Error(..) => (), - } - } - - // FIXME(struct_target_features): is this really necessary? - if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust { - tcx.dcx().span_err( - tcx.hir().span(tcx.local_def_id_to_hir_id(did)), - "cannot use a struct with target features in a function with non-Rust ABI", - ); - } - if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { - tcx.dcx().span_err( - tcx.hir().span(tcx.local_def_id_to_hir_id(did)), - "cannot use a struct with target features in a #[inline(always)] function", - ); - } - codegen_fn_attrs - .target_features - .extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf })); - } - - // If a function uses non-default target_features it can't be inlined into general + // If a function uses #[target_feature] it can't be inlined into general // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. @@ -849,20 +758,6 @@ fn check_link_name_xor_ordinal( } } -fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] { - let mut features = vec![]; - let supported_features = tcx.supported_target_features(LOCAL_CRATE); - for attr in tcx.get_attrs(def_id, sym::target_feature) { - from_target_feature(tcx, attr, supported_features, &mut features); - } - tcx.arena.alloc_slice(&features) -} - pub fn provide(providers: &mut Providers) { - *providers = Providers { - codegen_fn_attrs, - should_inherit_track_caller, - struct_target_features, - ..*providers - }; + *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; } diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 69cbf8c4161..38c6c8a8d11 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -22,7 +22,7 @@ rustc_index = { path = "../rustc_index", package = "rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } -stacker = "0.1.15" +stacker = "0.1.17" tempfile = "3.2" thin-vec = "0.2.12" tracing = "0.1" diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 3303e4ee752..34aebadfdad 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -12,7 +12,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{AttrId, Span, DUMMY_SP}; use tracing::debug; use crate::snippet::Style; @@ -356,24 +356,19 @@ impl DiagInner { pub(crate) fn update_unstable_expectation_id( &mut self, - unstable_to_stable: &FxIndexMap<LintExpectationId, LintExpectationId>, + unstable_to_stable: &FxIndexMap<AttrId, LintExpectationId>, ) { if let Level::Expect(expectation_id) | Level::ForceWarning(Some(expectation_id)) = &mut self.level + && let LintExpectationId::Unstable { attr_id, lint_index } = *expectation_id { - if expectation_id.is_stable() { - return; - } - // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index. // The lint index inside the attribute is manually transferred here. - let lint_index = expectation_id.get_lint_index(); - expectation_id.set_lint_index(None); - let mut stable_id = unstable_to_stable - .get(expectation_id) - .expect("each unstable `LintExpectationId` must have a matching stable id") - .normalize(); + let Some(stable_id) = unstable_to_stable.get(&attr_id) else { + panic!("{expectation_id:?} must have a matching stable id") + }; + let mut stable_id = *stable_id; stable_id.set_lint_index(lint_index); *expectation_id = stable_id; } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 99ee8fb17d7..e08d28a156c 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -69,7 +69,7 @@ use rustc_macros::{Decodable, Encodable}; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; use rustc_span::source_map::SourceMap; pub use rustc_span::ErrorGuaranteed; -use rustc_span::{Loc, Span, DUMMY_SP}; +use rustc_span::{AttrId, Loc, Span, DUMMY_SP}; pub use snippet::Style; // Used by external projects such as `rust-gpu`. // See https://github.com/rust-lang/rust/pull/115393. @@ -1096,7 +1096,7 @@ impl<'a> DiagCtxtHandle<'a> { pub fn update_unstable_expectation_id( &self, - unstable_to_stable: &FxIndexMap<LintExpectationId, LintExpectationId>, + unstable_to_stable: FxIndexMap<AttrId, LintExpectationId>, ) { let mut inner = self.inner.borrow_mut(); let diags = std::mem::take(&mut inner.unstable_expect_diagnostics); @@ -1105,7 +1105,7 @@ impl<'a> DiagCtxtHandle<'a> { if !diags.is_empty() { inner.suppressed_expected_diag = true; for mut diag in diags.into_iter() { - diag.update_unstable_expectation_id(unstable_to_stable); + diag.update_unstable_expectation_id(&unstable_to_stable); // Here the diagnostic is given back to `emit_diagnostic` where it was first // intercepted. Now it should be processed as usual, since the unstable expectation @@ -1117,11 +1117,11 @@ impl<'a> DiagCtxtHandle<'a> { inner .stashed_diagnostics .values_mut() - .for_each(|(diag, _guar)| diag.update_unstable_expectation_id(unstable_to_stable)); + .for_each(|(diag, _guar)| diag.update_unstable_expectation_id(&unstable_to_stable)); inner .future_breakage_diagnostics .iter_mut() - .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); + .for_each(|diag| diag.update_unstable_expectation_id(&unstable_to_stable)); } /// This methods steals all [`LintExpectationId`]s that are stored inside @@ -1567,7 +1567,7 @@ impl DiagCtxtInner { if let LintExpectationId::Unstable { .. } = expect_id { unreachable!(); // this case was handled at the top of this function } - self.fulfilled_expectations.insert(expect_id.normalize()); + self.fulfilled_expectations.insert(expect_id); if let Expect(_) = diagnostic.level { // Nothing emitted here for expected lints. TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 7ea037ca8b2..ffeaa861220 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -597,8 +597,6 @@ declare_features! ( (unstable, strict_provenance, "1.61.0", Some(95228)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), - /// Allows structs to carry target_feature information. - (incomplete, struct_target_features, "CURRENT_RUSTC_VERSION", Some(129107)), /// Allows the use of `#[target_feature]` on safe functions. (unstable, target_feature_11, "1.45.0", Some(69098)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 36e29d2dcb2..bd55617d84e 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -326,41 +326,6 @@ impl DefKind { | DefKind::ExternCrate => false, } } - - /// Whether `query struct_target_features` should be used with this definition. - pub fn has_struct_target_features(self) -> bool { - match self { - DefKind::Struct | DefKind::Union | DefKind::Enum => true, - DefKind::Fn - | DefKind::AssocFn - | DefKind::Ctor(..) - | DefKind::Closure - | DefKind::Static { .. } - | DefKind::Mod - | DefKind::Variant - | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::Const - | DefKind::AssocConst - | DefKind::Macro(..) - | DefKind::Use - | DefKind::ForeignMod - | DefKind::OpaqueTy - | DefKind::Impl { .. } - | DefKind::Field - | DefKind::TyParam - | DefKind::ConstParam - | DefKind::LifetimeParam - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::SyntheticCoroutineBody - | DefKind::GlobalAsm - | DefKind::ExternCrate => false, - } - } } /// The resolution of a path or export. @@ -863,8 +828,13 @@ pub enum LifetimeRes { /// This variant is used for anonymous lifetimes that we did not resolve during /// late resolution. Those lifetimes will be inferred by typechecking. Infer, - /// Explicit `'static` lifetime. - Static, + /// `'static` lifetime. + Static { + /// We do not want to emit `elided_named_lifetimes` + /// when we are inside of a const item or a static, + /// because it would get too annoying. + suppress_elision_warning: bool, + }, /// Resolution failure. Error, /// HACK: This is used to recover the NodeId of an elided lifetime. diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 865e9be0a67..d97c590bd41 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -851,8 +851,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). - // FIXME(struct_target_features): should this be true also for functions that inherit - // target features from structs? if b_hdr.safety == hir::Safety::Safe && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 08a50050a36..31b7eb5ee7d 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -252,6 +252,10 @@ lint_duplicate_macro_attribute = lint_duplicate_matcher_binding = duplicate matcher binding +lint_elided_named_lifetime = elided lifetime has a name + .label_elided = this elided lifetime gets resolved as `{$name}` + .label_named = lifetime `{$name}` declared here + lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index f289d4c81b3..fd43afa1743 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -10,6 +10,7 @@ use rustc_errors::{ use rustc_middle::middle::stability; use rustc_session::lint::BuiltinLintDiag; use rustc_session::Session; +use rustc_span::symbol::kw; use rustc_span::BytePos; use tracing::debug; @@ -441,5 +442,17 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } + BuiltinLintDiag::ElidedIsStatic { elided } => { + lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None } + .decorate_lint(diag) + } + BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => { + lints::ElidedNamedLifetime { + elided, + name: param_name, + named_declaration: Some(param_span), + } + .decorate_lint(diag) + } } } diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 42b33f9882d..d8afba3d505 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,21 +1,66 @@ +use rustc_data_structures::fx::FxIndexMap; +use rustc_hir::{HirId, CRATE_OWNER_ID}; +use rustc_middle::lint::LintExpectation; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; -use rustc_session::lint::LintExpectationId; +use rustc_session::lint::{Level, LintExpectationId}; use rustc_span::Symbol; use crate::lints::{Expectation, ExpectationNote}; pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { check_expectations, ..*providers }; + *providers = Providers { lint_expectations, check_expectations, ..*providers }; +} + +fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { + let krate = tcx.hir_crate_items(()); + + let mut expectations = Vec::new(); + let mut unstable_to_stable_ids = FxIndexMap::default(); + + let mut record_stable = |attr_id, hir_id, attr_index| { + let expect_id = LintExpectationId::Stable { hir_id, attr_index, lint_index: None }; + unstable_to_stable_ids.entry(attr_id).or_insert(expect_id); + }; + let mut push_expectations = |owner| { + let lints = tcx.shallow_lint_levels_on(owner); + if lints.expectations.is_empty() { + return; + } + + expectations.extend_from_slice(&lints.expectations); + + let attrs = tcx.hir_attrs(owner); + for &(local_id, attrs) in attrs.map.iter() { + // Some attributes appear multiple times in HIR, to ensure they are correctly taken + // into account where they matter. This means we cannot just associate the AttrId to + // the first HirId where we see it, but need to check it actually appears in a lint + // level. + // FIXME(cjgillot): Can this cause an attribute to appear in multiple expectation ids? + if !lints.specs.contains_key(&local_id) { + continue; + } + for (attr_index, attr) in attrs.iter().enumerate() { + let Some(Level::Expect(_)) = Level::from_attr(attr) else { continue }; + record_stable(attr.id, HirId { owner, local_id }, attr_index.try_into().unwrap()); + } + } + }; + + push_expectations(CRATE_OWNER_ID); + for owner in krate.owners() { + push_expectations(owner); + } + + tcx.dcx().update_unstable_expectation_id(unstable_to_stable_ids); + expectations } fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) { let lint_expectations = tcx.lint_expectations(()); let fulfilled_expectations = tcx.dcx().steal_fulfilled_expectation_ids(); - tracing::debug!(?lint_expectations, ?fulfilled_expectations); - for (id, expectation) in lint_expectations { // This check will always be true, since `lint_expectations` only // holds stable ids diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 07ac63ec96c..65289de980e 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -115,34 +115,6 @@ impl LintLevelSets { } } -fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { - let store = unerased_lint_store(tcx.sess); - - let mut builder = LintLevelsBuilder { - sess: tcx.sess, - features: tcx.features(), - provider: QueryMapExpectationsWrapper { - tcx, - cur: hir::CRATE_HIR_ID, - specs: ShallowLintLevelMap::default(), - expectations: Vec::new(), - unstable_to_stable_ids: FxIndexMap::default(), - empty: FxIndexMap::default(), - }, - lint_added_lints: false, - store, - registered_tools: tcx.registered_tools(()), - }; - - builder.add_command_line(); - builder.add_id(hir::CRATE_HIR_ID); - tcx.hir().walk_toplevel_module(&mut builder); - - tcx.dcx().update_unstable_expectation_id(&builder.provider.unstable_to_stable_ids); - - builder.provider.expectations -} - #[instrument(level = "trace", skip(tcx), ret)] fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap { let store = unerased_lint_store(tcx.sess); @@ -207,7 +179,7 @@ pub trait LintLevelsProvider { fn current_specs(&self) -> &FxIndexMap<LintId, LevelAndSource>; fn insert(&mut self, id: LintId, lvl: LevelAndSource); fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource; - fn push_expectation(&mut self, _id: LintExpectationId, _expectation: LintExpectation) {} + fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation); } impl LintLevelsProvider for TopDown { @@ -222,6 +194,8 @@ impl LintLevelsProvider for TopDown { fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource { self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), sess) } + + fn push_expectation(&mut self, _: LintExpectationId, _: LintExpectation) {} } struct LintLevelQueryMap<'tcx> { @@ -243,47 +217,8 @@ impl LintLevelsProvider for LintLevelQueryMap<'_> { fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) } -} - -struct QueryMapExpectationsWrapper<'tcx> { - tcx: TyCtxt<'tcx>, - /// HirId of the currently investigated element. - cur: HirId, - /// Level map for `cur`. - specs: ShallowLintLevelMap, - expectations: Vec<(LintExpectationId, LintExpectation)>, - unstable_to_stable_ids: FxIndexMap<LintExpectationId, LintExpectationId>, - /// Empty hash map to simplify code. - empty: FxIndexMap<LintId, LevelAndSource>, -} - -impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> { - fn current_specs(&self) -> &FxIndexMap<LintId, LevelAndSource> { - self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty) - } - fn insert(&mut self, id: LintId, lvl: LevelAndSource) { - self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, lvl); - } - fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { - // We cannot use `tcx.lint_level_at_node` because we want to know in which order the - // attributes have been inserted, in particular whether an `expect` follows a `forbid`. - self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) - } fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) { - let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id - else { - bug!("unstable expectation id should already be mapped") - }; - let key = LintExpectationId::Unstable { attr_id, lint_index: None }; - - self.unstable_to_stable_ids.entry(key).or_insert(LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: None, - attr_id: None, - }); - - self.expectations.push((id.normalize(), expectation)); + self.specs.expectations.push((id, expectation)) } } @@ -368,80 +303,6 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> { } } -impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - fn add_id(&mut self, hir_id: HirId) { - // Change both the `HirId` and the associated specs. - self.provider.cur = hir_id; - self.provider.specs.specs.clear(); - self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id)); - } -} - -impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.provider.tcx.hir() - } - - fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - self.add_id(param.hir_id); - intravisit::walk_param(self, param); - } - - fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_item(self, it); - } - - fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_foreign_item(self, it); - } - - fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) { - // We will call `add_id` when we walk - // the `StmtKind`. The outer statement itself doesn't - // define the lint levels. - intravisit::walk_stmt(self, e); - } - - fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - self.add_id(e.hir_id); - intravisit::walk_expr(self, e); - } - - fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { - self.add_id(s.hir_id); - intravisit::walk_field_def(self, s); - } - - fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { - self.add_id(v.hir_id); - intravisit::walk_variant(self, v); - } - - fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) { - self.add_id(l.hir_id); - intravisit::walk_local(self, l); - } - - fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) { - self.add_id(a.hir_id); - intravisit::walk_arm(self, a); - } - - fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - self.add_id(trait_item.hir_id()); - intravisit::walk_trait_item(self, trait_item); - } - - fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { - self.add_id(impl_item.hir_id()); - intravisit::walk_impl_item(self, impl_item); - } -} - pub struct LintLevelsBuilder<'s, P> { sess: &'s Session, features: &'s Features, @@ -625,13 +486,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, (mut level, src): LevelAndSource) { + fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) { let (old_level, old_src) = self.provider.get_lint_level(id.lint, self.sess); - if let Level::Expect(id) = &mut level - && let LintExpectationId::Stable { .. } = id - { - *id = id.normalize(); - } + // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a // `#[forbid(..)]` attribute present, as that is overridden by `--cap-lints`. @@ -743,17 +600,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // This is the only lint level with a `LintExpectationId` that can be created from // an attribute. Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { - let LintExpectationId::Unstable { attr_id, lint_index } = unstable_id else { + let LintExpectationId::Unstable { lint_index: None, attr_id: _ } = unstable_id + else { bug!("stable id Level::from_attr") }; let stable_id = LintExpectationId::Stable { hir_id, attr_index: attr_index.try_into().unwrap(), - lint_index, - // We pass the previous unstable attr_id such that we can trace the ast id - // when building a map to go from unstable to stable id. - attr_id: Some(attr_id), + lint_index: None, }; Level::Expect(stable_id) @@ -840,59 +695,20 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let name = pprust::path_to_string(&meta_item.path); let lint_result = self.store.check_lint_name(&name, tool_name, self.registered_tools); - match &lint_result { + + let (ids, name) = match lint_result { CheckLintNameResult::Ok(ids) => { - // This checks for instances where the user writes - // `#[expect(unfulfilled_lint_expectations)]` in that case we want to avoid - // overriding the lint level but instead add an expectation that can't be - // fulfilled. The lint message will include an explanation, that the - // `unfulfilled_lint_expectations` lint can't be expected. - if let Level::Expect(expect_id) = level { - // The `unfulfilled_lint_expectations` lint is not part of any lint - // groups. Therefore. we only need to check the slice if it contains a - // single lint. - let is_unfulfilled_lint_expectations = match ids { - [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), - _ => false, - }; - self.provider.push_expectation( - expect_id, - LintExpectation::new( - reason, - sp, - is_unfulfilled_lint_expectations, - tool_name, - ), - ); - } - let src = LintLevelSource::Node { - name: meta_item - .path - .segments - .last() - .expect("empty lint name") - .ident - .name, - span: sp, - reason, - }; - for &id in *ids { - if self.check_gated_lint(id, attr.span, false) { - self.insert_spec(id, (level, src)); - } - } + let name = + meta_item.path.segments.last().expect("empty lint name").ident.name; + (ids, name) } CheckLintNameResult::Tool(ids, new_lint_name) => { - let src = match new_lint_name { + let name = match new_lint_name { None => { let complete_name = &format!("{}::{}", tool_ident.unwrap().name, name); - LintLevelSource::Node { - name: Symbol::intern(complete_name), - span: sp, - reason, - } + Symbol::intern(complete_name) } Some(new_lint_name) => { self.emit_span_lint( @@ -901,27 +717,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { DeprecatedLintName { name, suggestion: sp, - replace: new_lint_name, + replace: &new_lint_name, }, ); - LintLevelSource::Node { - name: Symbol::intern(new_lint_name), - span: sp, - reason, - } + Symbol::intern(&new_lint_name) } }; - for &id in *ids { - if self.check_gated_lint(id, attr.span, false) { - self.insert_spec(id, (level, src)); - } - } - if let Level::Expect(expect_id) = level { - self.provider.push_expectation( - expect_id, - LintExpectation::new(reason, sp, false, tool_name), - ); - } + (ids, name) } CheckLintNameResult::MissingTool => { @@ -929,9 +731,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // exist in the tool or the code was not compiled with the tool and // therefore the lint was never added to the `LintStore`. To detect // this is the responsibility of the lint tool. + continue; } - &CheckLintNameResult::NoTool => { + CheckLintNameResult::NoTool => { sess.dcx().emit_err(UnknownToolInScopedLint { span: tool_ident.map(|ident| ident.span), tool_name: tool_name.unwrap(), @@ -941,58 +744,88 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { continue; } - _ if !self.lint_added_lints => {} - CheckLintNameResult::Renamed(ref replace) => { - let suggestion = - RenamedLintSuggestion::WithSpan { suggestion: sp, replace }; - let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let lint = RenamedLint { name: name.as_str(), suggestion }; - self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + if self.lint_added_lints { + let suggestion = + RenamedLintSuggestion::WithSpan { suggestion: sp, replace }; + let name = + tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + let lint = RenamedLint { name: name.as_str(), suggestion }; + self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + } + + // If this lint was renamed, apply the new lint instead of ignoring the + // attribute. Ignore any errors or warnings that happen because the new + // name is inaccurate. + // NOTE: `new_name` already includes the tool name, so we don't + // have to add it again. + let CheckLintNameResult::Ok(ids) = + self.store.check_lint_name(replace, None, self.registered_tools) + else { + panic!("renamed lint does not exist: {replace}"); + }; + + (ids, Symbol::intern(&replace)) } CheckLintNameResult::Removed(ref reason) => { - let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let lint = RemovedLint { name: name.as_str(), reason }; - self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + if self.lint_added_lints { + let name = + tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + let lint = RemovedLint { name: name.as_str(), reason }; + self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + } + continue; } CheckLintNameResult::NoLint(suggestion) => { - let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let suggestion = suggestion.map(|(replace, from_rustc)| { - UnknownLintSuggestion::WithSpan { suggestion: sp, replace, from_rustc } - }); - let lint = UnknownLint { name, suggestion }; - self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint); - } - } - // If this lint was renamed, apply the new lint instead of ignoring the attribute. - // This happens outside of the match because the new lint should be applied even if - // we don't warn about the name change. - if let CheckLintNameResult::Renamed(new_name) = lint_result { - // Ignore any errors or warnings that happen because the new name is inaccurate - // NOTE: `new_name` already includes the tool name, so we don't have to add it - // again. - let CheckLintNameResult::Ok(ids) = - self.store.check_lint_name(&new_name, None, self.registered_tools) - else { - panic!("renamed lint does not exist: {new_name}"); - }; - - let src = - LintLevelSource::Node { name: Symbol::intern(&new_name), span: sp, reason }; - for &id in ids { - if self.check_gated_lint(id, attr.span, false) { - self.insert_spec(id, (level, src)); + if self.lint_added_lints { + let name = + tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + let suggestion = suggestion.map(|(replace, from_rustc)| { + UnknownLintSuggestion::WithSpan { + suggestion: sp, + replace, + from_rustc, + } + }); + let lint = UnknownLint { name, suggestion }; + self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint); } + continue; } - if let Level::Expect(expect_id) = level { - self.provider.push_expectation( - expect_id, - LintExpectation::new(reason, sp, false, tool_name), - ); + }; + + let src = LintLevelSource::Node { name, span: sp, reason }; + for &id in ids { + if self.check_gated_lint(id, attr.span, false) { + self.insert_spec(id, (level, src)); } } + + // This checks for instances where the user writes + // `#[expect(unfulfilled_lint_expectations)]` in that case we want to avoid + // overriding the lint level but instead add an expectation that can't be + // fulfilled. The lint message will include an explanation, that the + // `unfulfilled_lint_expectations` lint can't be expected. + if let Level::Expect(expect_id) = level { + // The `unfulfilled_lint_expectations` lint is not part of any lint + // groups. Therefore. we only need to check the slice if it contains a + // single lint. + let is_unfulfilled_lint_expectations = match ids { + [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), + _ => false, + }; + self.provider.push_expectation( + expect_id, + LintExpectation::new( + reason, + sp, + is_unfulfilled_lint_expectations, + tool_name, + ), + ); + } } } @@ -1100,7 +933,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers }; + *providers = Providers { shallow_lint_levels_on, ..*providers }; } pub(crate) fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c6bcb1f3e83..2712e25668a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2612,6 +2612,16 @@ pub(crate) struct ElidedLifetimesInPaths { } #[derive(LintDiagnostic)] +#[diag(lint_elided_named_lifetime)] +pub(crate) struct ElidedNamedLifetime { + #[label(lint_label_elided)] + pub elided: Span, + pub name: Symbol, + #[label(lint_label_named)] + pub named_declaration: Option<Span>, +} + +#[derive(LintDiagnostic)] #[diag(lint_invalid_crate_type_value)] pub(crate) struct UnknownCrateTypes { #[subdiagnostic] diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 04fd7c9c627..7063f488209 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -42,6 +42,7 @@ declare_lint_pass! { DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, ELIDED_LIFETIMES_IN_PATHS, + ELIDED_NAMED_LIFETIMES, EXPLICIT_BUILTIN_CFGS_IN_FLAGS, EXPORTED_PRIVATE_DEPENDENCIES, FFI_UNWIND_CALLS, @@ -1863,6 +1864,38 @@ declare_lint! { } declare_lint! { + /// The `elided_named_lifetimes` lint detects when an elided + /// lifetime ends up being a named lifetime, such as `'static` + /// or some lifetime parameter `'a`. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(elided_named_lifetimes)] + /// struct Foo; + /// impl Foo { + /// pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + /// unsafe { &mut *(x as *mut _) } + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Lifetime elision is quite useful, because it frees you from having + /// to give each lifetime its own name, but sometimes it can produce + /// somewhat surprising resolutions. In safe code, it is mostly okay, + /// because the borrow checker prevents any unsoundness, so the worst + /// case scenario is you get a confusing error message in some other place. + /// But with `unsafe` code, such unexpected resolutions may lead to unsound code. + pub ELIDED_NAMED_LIFETIMES, + Warn, + "detects when an elided lifetime gets resolved to be `'static` or some named parameter" +} + +declare_lint! { /// The `bare_trait_objects` lint suggests using `dyn Trait` for trait /// objects. /// diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c17b85db3b0..6ee33041623 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -98,7 +98,7 @@ pub enum LintExpectationId { /// stable and can be cached. The additional index ensures that nodes with /// several expectations can correctly match diagnostics to the individual /// expectation. - Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16>, attr_id: Option<AttrId> }, + Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16> }, } impl LintExpectationId { @@ -122,31 +122,13 @@ impl LintExpectationId { *lint_index = new_lint_index } - - /// Prepares the id for hashing. Removes references to the ast. - /// Should only be called when the id is stable. - pub fn normalize(self) -> Self { - match self { - Self::Stable { hir_id, attr_index, lint_index, .. } => { - Self::Stable { hir_id, attr_index, lint_index, attr_id: None } - } - Self::Unstable { .. } => { - unreachable!("`normalize` called when `ExpectationId` is unstable") - } - } - } } impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => { + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { hir_id.hash_stable(hcx, hasher); attr_index.hash_stable(hcx, hasher); lint_index.hash_stable(hcx, hasher); @@ -166,12 +148,9 @@ impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectation #[inline] fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => (*hir_id, *attr_index, *lint_index), + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { + (*hir_id, *attr_index, *lint_index) + } _ => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") } @@ -589,6 +568,13 @@ pub enum BuiltinLintDiag { }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), + ElidedIsStatic { + elided: Span, + }, + ElidedIsParam { + elided: Span, + param: (Symbol, Span), + }, UnknownCrateTypes { span: Span, candidate: Option<Symbol>, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a82340e3d61..0f46cacc27a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -254,7 +254,6 @@ provide! { tcx, def_id, other, cdata, variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } - struct_target_features => { table } impl_trait_header => { table } const_param_default => { table } object_lifetime_default => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 919623cff60..88256c4db04 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1392,9 +1392,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if def_kind.has_codegen_attrs() { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } - if def_kind.has_struct_target_features() { - record_array!(self.tables.struct_target_features[def_id] <- self.tcx.struct_target_features(def_id)); - } if should_encode_visibility(def_kind) { let vis = self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 987ee3f07e9..a84923130c3 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -19,7 +19,7 @@ use rustc_macros::{ Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; use rustc_middle::metadata::ModChild; -use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; @@ -427,7 +427,6 @@ define_tables! { variances_of: Table<DefIndex, LazyArray<ty::Variance>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::PolyFnSig<'static>>>>, codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>, - struct_target_features: Table<DefIndex, LazyArray<TargetFeature>>, impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>, const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, rustc_middle::ty::Const<'static>>>>, object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 8c27cac1ea8..70da66af64b 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -6,7 +6,7 @@ use rustc_errors::{Diag, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_macros::HashStable; use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS}; -use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintId}; +use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId}; use rustc_session::Session; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP}; @@ -61,6 +61,7 @@ pub type LevelAndSource = (Level, LintLevelSource); /// by the attributes for *a single HirId*. #[derive(Default, Debug, HashStable)] pub struct ShallowLintLevelMap { + pub expectations: Vec<(LintExpectationId, LintExpectation)>, pub specs: SortedMap<ItemLocalId, FxIndexMap<LintId, LevelAndSource>>, } diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index c098a739592..b7d290e58d2 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -26,8 +26,8 @@ pub struct CodegenFnAttrs { /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. pub link_ordinal: Option<u16>, - /// All the target features that are enabled for this function. Some features might be enabled - /// implicitly. + /// The `#[target_feature(enable = "...")]` attribute and the enabled + /// features (only enabled features are supported right now). pub target_features: Vec<TargetFeature>, /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. pub linkage: Option<Linkage>, @@ -55,8 +55,8 @@ pub struct CodegenFnAttrs { pub struct TargetFeature { /// The name of the target feature (e.g. "avx") pub name: Symbol, - /// The feature is implied by another feature or by an argument, rather than explicitly - /// added by the `#[target_feature]` attribute + /// The feature is implied by another feature, rather than explicitly added by the + /// `#[target_feature]` attribute pub implied: bool, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b6443778c93..d6bdc1af0d2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -47,7 +47,7 @@ use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; +use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; @@ -1249,11 +1249,6 @@ rustc_queries! { feedable } - query struct_target_features(def_id: DefId) -> &'tcx [TargetFeature] { - separate_provide_extern - desc { |tcx| "computing target features for struct `{}`", tcx.def_path_str(def_id) } - } - query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index be611e19b49..7e1255f606c 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,7 +59,6 @@ trivially_parameterized_over_tcx! { std::string::String, crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, - crate::middle::codegen_fn_attrs::TargetFeature, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, crate::middle::lib_features::FeatureStability, diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index a42e8ff0168..7a10e627ccd 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -125,17 +125,6 @@ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr -mir_build_initializing_type_with_target_feature_requires_unsafe = - initializing type with `target_feature` attr is unsafe and requires unsafe block - .note = this struct can only be constructed if the corresponding `target_feature`s are available - .label = initializing type with `target_feature` attr - -mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - initializing type with `target_feature` attr is unsafe and requires unsafe function or block - .note = this struct can only be constructed if the corresponding `target_feature`s are available - .label = initializing type with `target_feature` attr - - mir_build_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior @@ -398,11 +387,6 @@ mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr -mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe = - initializing type with `target_feature` attr is unsafe and requires unsafe block - .note = this struct can only be constructed if the corresponding `target_feature`s are available - .label = initializing type with `target_feature` attr - mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 4ce796cea7a..c7fcfe3ce2a 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -461,18 +461,14 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id)); } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() { - // If the called function has explicit target features the calling function hasn't, + // If the called function has target features the calling function hasn't, // the call requires `unsafe`. Don't check this on wasm // targets, though. For more information on wasm see the // is_like_wasm check in hir_analysis/src/collect.rs - // Implicit target features are OK because they are either a consequence of some - // explicit target feature (which is checked to be present in the caller) or - // come from a witness argument. let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; if !self.tcx.sess.target.options.is_like_wasm && !callee_features.iter().all(|feature| { - feature.implied - || self.body_target_features.iter().any(|f| f.name == feature.name) + self.body_target_features.iter().any(|f| f.name == feature.name) }) { let missing: Vec<_> = callee_features @@ -546,16 +542,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { user_ty: _, fields: _, base: _, - }) => { - match self.tcx.layout_scalar_valid_range(adt_def.did()) { - (Bound::Unbounded, Bound::Unbounded) => {} - _ => self.requires_unsafe(expr.span, InitializingTypeWith), - } - if !self.tcx.struct_target_features(adt_def.did()).is_empty() { - self.requires_unsafe(expr.span, ConstructingTargetFeaturesType) - } - } - + }) => match self.tcx.layout_scalar_valid_range(adt_def.did()) { + (Bound::Unbounded, Bound::Unbounded) => {} + _ => self.requires_unsafe(expr.span, InitializingTypeWith), + }, ExprKind::Closure(box ClosureExpr { closure_id, args: _, @@ -657,7 +647,6 @@ enum UnsafeOpKind { CallToUnsafeFunction(Option<DefId>), UseOfInlineAssembly, InitializingTypeWith, - ConstructingTargetFeaturesType, UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, @@ -739,15 +728,6 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }, ), - ConstructingTargetFeaturesType => tcx.emit_node_span_lint( - UNSAFE_OP_IN_UNSAFE_FN, - hir_id, - span, - UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { - span, - unsafe_not_inherited_note, - }, - ), UseOfMutableStatic => tcx.emit_node_span_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, @@ -905,20 +885,6 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }); } - ConstructingTargetFeaturesType if unsafe_op_in_unsafe_fn_allowed => { - dcx.emit_err( - InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { - span, - unsafe_not_inherited_note, - }, - ); - } - ConstructingTargetFeaturesType => { - dcx.emit_err(InitializingTypeWithTargetFeatureRequiresUnsafe { - span, - unsafe_not_inherited_note, - }); - } UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e7d6239aa9b..7f9eefd1d52 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -87,16 +87,6 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe, code = E0133)] -#[note] -pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { - #[label] - pub(crate) span: Span, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, -} - -#[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] #[note] pub(crate) struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { @@ -261,17 +251,6 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_initializing_type_with_target_feature_requires_unsafe, code = E0133)] -#[note] -pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafe { - #[primary_span] - #[label] - pub(crate) span: Span, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, -} - -#[derive(Diagnostic)] #[diag( mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133 @@ -286,20 +265,6 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag( - mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, - code = E0133 -)] -#[note] -pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { - #[primary_span] - #[label] - pub(crate) span: Span, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, -} - -#[derive(Diagnostic)] #[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] #[note] pub(crate) struct UseOfMutableStaticRequiresUnsafe { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 38450fc288a..e7f208d5ad5 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -672,10 +672,6 @@ passes_should_be_applied_to_fn = *[false] not a function definition } -passes_should_be_applied_to_fn_or_unit_struct = - attribute should be applied to a function definition or unit struct - .label = not a function definition or a unit struct - passes_should_be_applied_to_static = attribute should be applied to a static .label = not a static diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5dbb3854c8f..21478a44b0e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -747,35 +747,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature"); } - Target::Struct if self.tcx.features().struct_target_features => { - let ty = self.tcx.hir_node(hir_id).expect_item(); - match ty.kind { - ItemKind::Struct(data, _) => { - if data.fields().len() != 0 { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { - attr_span: attr.span, - defn_span: span, - }); - } - } - _ => { - panic!("Target::Struct for a non-struct"); - } - } - } _ => { - if self.tcx.features().struct_target_features { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { - attr_span: attr.span, - defn_span: span, - }); - } else { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); - } + self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { + attr_span: attr.span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); } } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1e9ab7af9be..f5d982e1a5c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -83,15 +83,6 @@ pub(crate) struct AttrShouldBeAppliedToFn { } #[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_fn_or_unit_struct)] -pub(crate) struct AttrShouldBeAppliedToFnOrUnitStruct { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn, code = E0739)] pub(crate) struct TrackedCallerWrongLocation { #[primary_span] diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 3595db78e93..a70d51606f7 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,6 +2,7 @@ use std::mem; use rustc_ast::visit::FnKind; use rustc_ast::*; +use rustc_ast_pretty::pprust; use rustc_expand::expand::AstFragment; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; @@ -120,8 +121,6 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_item(&mut self, i: &'a Item) { - debug!("visit_item: {:?}", i); - // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better let mut opt_macro_data = None; @@ -183,38 +182,51 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { - if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind { - match sig.header.coroutine_kind { - Some(coroutine_kind) => { - self.visit_generics(generics); - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. Besides that, - // we must mirror everything that `visit::walk_fn` below does. - self.visit_fn_header(&sig.header); - for param in &sig.decl.inputs { - self.visit_param(param); - } - self.visit_fn_ret_ty(&sig.decl.output); - // If this async fn has no body (i.e. it's an async fn signature in a trait) - // then the closure_def will never be used, and we should avoid generating a - // def-id for it. - if let Some(body) = body { - let closure_def = self.create_def( - coroutine_kind.closure_id(), - kw::Empty, - DefKind::Closure, - span, - ); - self.with_parent(closure_def, |this| this.visit_block(body)); - } - return; + match fn_kind { + FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) + if let Some(coroutine_kind) = header.coroutine_kind => + { + self.visit_fn_header(header); + self.visit_generics(generics); + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. Besides that, + // we must mirror everything that `visit::walk_fn` below does. + let FnDecl { inputs, output } = &**decl; + for param in inputs { + self.visit_param(param); + } + + let (return_id, return_span) = coroutine_kind.return_id(); + let return_def = + self.create_def(return_id, kw::Empty, DefKind::OpaqueTy, return_span); + self.with_parent(return_def, |this| this.visit_fn_ret_ty(output)); + + // If this async fn has no body (i.e. it's an async fn signature in a trait) + // then the closure_def will never be used, and we should avoid generating a + // def-id for it. + if let Some(body) = body { + let closure_def = self.create_def( + coroutine_kind.closure_id(), + kw::Empty, + DefKind::Closure, + span, + ); + self.with_parent(closure_def, |this| this.visit_block(body)); } - None => {} } - } + FnKind::Closure(binder, Some(coroutine_kind), decl, body) => { + self.visit_closure_binder(binder); + visit::walk_fn_decl(self, decl); - visit::walk_fn(self, fn_kind); + // Async closures desugar to closures inside of closures, so + // we must create two defs. + let coroutine_def = + self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span); + self.with_parent(coroutine_def, |this| visit::walk_expr(this, body)); + } + _ => visit::walk_fn(self, fn_kind), + } } fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { @@ -334,27 +346,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_expr(&mut self, expr: &'a Expr) { let parent_def = match expr.kind { ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), - ExprKind::Closure(ref closure) => { - // Async closures desugar to closures inside of closures, so - // we must create two defs. - let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span); - match closure.coroutine_kind { - Some(coroutine_kind) => { - self.with_parent(closure_def, |this| { - let coroutine_def = this.create_def( - coroutine_kind.closure_id(), - kw::Empty, - DefKind::Closure, - expr.span, - ); - this.with_parent(coroutine_def, |this| visit::walk_expr(this, expr)); - }); - return; - } - None => closure_def, - } - } - ExprKind::Gen(_, _, _, _) => { + ExprKind::Closure(..) | ExprKind::Gen(..) => { self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) } ExprKind::ConstBlock(ref constant) => { @@ -381,6 +373,26 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), // Anonymous structs or unions are visited later after defined. TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {} + TyKind::ImplTrait(id, _) => { + // HACK: pprust breaks strings with newlines when the type + // gets too long. We don't want these to show up in compiler + // output or built artifacts, so replace them here... + // Perhaps we should instead format APITs more robustly. + let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " ")); + let kind = match self.impl_trait_context { + ImplTraitContext::Universal => DefKind::TyParam, + ImplTraitContext::Existential => DefKind::OpaqueTy, + }; + let id = self.create_def(*id, name, kind, ty.span); + match self.impl_trait_context { + // Do not nest APIT, as we desugar them as `impl_trait: bounds`, + // so the `impl_trait` node is not a parent to `bounds`. + ImplTraitContext::Universal => visit::walk_ty(self, ty), + ImplTraitContext::Existential => { + self.with_parent(id, |this| visit::walk_ty(this, ty)) + } + }; + } _ => visit::walk_ty(self, ty), } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 40fdb01a72c..a0386ddcbb3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1010,7 +1010,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, this.in_func_body = previous_state; } } - FnKind::Closure(binder, declaration, body) => { + FnKind::Closure(binder, _, declaration, body) => { this.visit_closure_binder(binder); this.with_lifetime_rib( @@ -1557,14 +1557,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if ident.name == kw::StaticLifetime { self.record_lifetime_res( lifetime.id, - LifetimeRes::Static, + LifetimeRes::Static { suppress_elision_warning: false }, LifetimeElisionCandidate::Named, ); return; } if ident.name == kw::UnderscoreLifetime { - return self.resolve_anonymous_lifetime(lifetime, false); + return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false); } let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev(); @@ -1667,13 +1667,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) { + fn resolve_anonymous_lifetime( + &mut self, + lifetime: &Lifetime, + id_for_lint: NodeId, + elided: bool, + ) { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); let kind = if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore }; - let missing_lifetime = - MissingLifetime { id: lifetime.id, span: lifetime.ident.span, kind, count: 1 }; + let missing_lifetime = MissingLifetime { + id: lifetime.id, + span: lifetime.ident.span, + kind, + count: 1, + id_for_lint, + }; let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() { debug!(?rib.kind); @@ -1697,7 +1707,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if lifetimes_in_scope.is_empty() { self.record_lifetime_res( lifetime.id, - LifetimeRes::Static, + // We are inside a const item, so do not warn. + LifetimeRes::Static { suppress_elision_warning: true }, elision_candidate, ); return; @@ -1800,7 +1811,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) }, LifetimeElisionCandidate::Ignore, ); - self.resolve_anonymous_lifetime(<, true); + self.resolve_anonymous_lifetime(<, anchor_id, true); } #[instrument(level = "debug", skip(self))] @@ -1916,6 +1927,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }; let missing_lifetime = MissingLifetime { id: node_ids.start, + id_for_lint: segment_id, span: elided_lifetime_span, kind, count: expected_lifetimes, @@ -2039,8 +2051,44 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)") } + + match candidate { + LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => { + debug_assert_eq!(id, missing.id); + match res { + LifetimeRes::Static { suppress_elision_warning } => { + if !suppress_elision_warning { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id_for_lint, + missing.span, + BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + ); + } + } + LifetimeRes::Param { param, binder: _ } => { + let tcx = self.r.tcx(); + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id_for_lint, + missing.span, + BuiltinLintDiag::ElidedIsParam { + elided: missing.span, + param: (tcx.item_name(param.into()), tcx.source_span(param)), + }, + ); + } + LifetimeRes::Fresh { .. } + | LifetimeRes::Infer + | LifetimeRes::Error + | LifetimeRes::ElidedAnchor { .. } => {} + } + } + LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {} + } + match res { - LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { + LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => { if let Some(ref mut candidates) = self.lifetime_elision_candidates { candidates.push((res, candidate)); } @@ -2558,9 +2606,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { self.with_static_rib(def_kind, |this| { - this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { - this.visit_ty(ty); - }); + this.with_lifetime_rib( + LifetimeRibKind::Elided(LifetimeRes::Static { + suppress_elision_warning: true, + }), + |this| { + this.visit_ty(ty); + }, + ); if let Some(expr) = expr { // We already forbid generic params because of the above item rib, // so it doesn't matter whether this is a trivial constant. @@ -2589,7 +2642,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { this.visit_generics(generics); this.with_lifetime_rib( - LifetimeRibKind::Elided(LifetimeRes::Static), + LifetimeRibKind::Elided(LifetimeRes::Static { + suppress_elision_warning: true, + }), |this| this.visit_ty(ty), ); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f778b0ee3ac..8f516c2db09 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -102,6 +102,13 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str pub(super) struct MissingLifetime { /// Used to overwrite the resolution with the suggestion, to avoid cascading errors. pub id: NodeId, + /// As we cannot yet emit lints in this crate and have to buffer them instead, + /// we need to associate each lint with some `NodeId`, + /// however for some `MissingLifetime`s their `NodeId`s are "fake", + /// in a sense that they are temporary and not get preserved down the line, + /// which means that the lints for those nodes will not get emitted. + /// To combat this, we can try to use some other `NodeId`s as a fallback option. + pub id_for_lint: NodeId, /// Where to suggest adding the lifetime. pub span: Span, /// How the lifetime was introduced, to have the correct space and comma. @@ -3028,7 +3035,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), - (DUMMY_NODE_ID, LifetimeRes::Static), + (DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }), )]; } } else if elided_len == 0 { @@ -3040,7 +3047,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), - (DUMMY_NODE_ID, LifetimeRes::Static), + (DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }), )]; } } else if num_params == 1 { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 16f5e55835e..34765209605 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1858,7 +1858,6 @@ symbols! { stringify, struct_field_attributes, struct_inherit, - struct_target_features, struct_variant, structural_match, structural_peq, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d5f227a84a4..37665018219 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1837,6 +1837,7 @@ supported_targets! { ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), + ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700), ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710), ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), ("i586-pc-nto-qnx700", i586_pc_nto_qnx700), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs new file mode 100644 index 00000000000..ac1bec02ec8 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs @@ -0,0 +1,38 @@ +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +pub fn target() -> Target { + // In QNX, libc does not provide a compatible ABI between versions. + // To distinguish between QNX versions, we needed a stable conditional compilation switch, + // which is why we needed to implement different targets in the compiler. + Target { + llvm_target: "aarch64-unknown-unknown".into(), + metadata: crate::spec::TargetMetadata { + description: Some("ARM64 QNX Neutrino 7.0 RTOS".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 64, + // from: https://llvm.org/docs/LangRef.html#data-layout + // e = little endian + // m:e = ELF mangling: Private symbols get a .L prefix + // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 + // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 + // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 + // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 + // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. + // S128 = 128 bits are the natural alignment of the stack in bits. + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: TargetOptions { + features: "+v8a".into(), + max_atomic_width: Some(128), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntoaarch64le_cxx"], + ), + env: "nto70".into(), + ..base::nto_qnx::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs index 0e5a0b9b9a5..65a1863eb39 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs @@ -1,35 +1,8 @@ -use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::Target; pub fn target() -> Target { - Target { - llvm_target: "aarch64-unknown-unknown".into(), - metadata: crate::spec::TargetMetadata { - description: Some("ARM64 QNX Neutrino 7.1 RTOS".into()), - tier: Some(3), - host_tools: Some(false), - std: Some(true), - }, - pointer_width: 64, - // from: https://llvm.org/docs/LangRef.html#data-layout - // e = little endian - // m:e = ELF mangling: Private symbols get a .L prefix - // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 - // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 - // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 - // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 - // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. - // S128 = 128 bits are the natural alignment of the stack in bits. - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: "aarch64".into(), - options: TargetOptions { - features: "+v8a".into(), - max_atomic_width: Some(128), - pre_link_args: TargetOptions::link_args( - LinkerFlavor::Gnu(Cc::Yes, Lld::No), - &["-Vgcc_ntoaarch64le_cxx"], - ), - env: "nto71".into(), - ..base::nto_qnx::opts() - }, - } + let mut base = super::aarch64_unknown_nto_qnx700::target(); + base.metadata.description = Some("ARM64 QNX Neutrino 7.1 RTOS".into()); + base.options.env = "nto71".into(); + base } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 3fdfca50dce..effd9f8cb0c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -439,8 +439,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let is_target_feature_fn = if let ty::FnDef(def_id, _) = *leaf_trait_ref.skip_binder().self_ty().kind() { - // FIXME(struct_target_features): should a function that inherits - // target_features through arguments implement Fn traits? !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() } else { false diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 7895a420476..96faa5236b1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -546,8 +546,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). ty::FnDef(def_id, args) => { let tcx = self.tcx(); - // FIXME(struct_target_features): should a function that inherits target_features - // through an argument implement Fn traits? if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible() && tcx.codegen_fn_attrs(def_id).target_features.is_empty() { diff --git a/library/Cargo.toml b/library/Cargo.toml index d8ece6b0ebd..e744cfe5e0f 100644 --- a/library/Cargo.toml +++ b/library/Cargo.toml @@ -31,8 +31,10 @@ codegen-units = 10000 # helps to improve link times a little bit. [profile.release.package] addr2line.debug = 0 +addr2line.opt-level = "s" adler.debug = 0 gimli.debug = 0 +gimli.opt-level = "s" miniz_oxide.debug = 0 object.debug = 0 rustc-demangle.debug = 0 diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index db2d752cfde..cddf4f6f399 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -372,6 +372,7 @@ extern "Rust" { #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] #[cfg(all(not(no_global_oom_handling), not(test)))] #[cold] +#[optimize(size)] pub const fn handle_alloc_error(layout: Layout) -> ! { const fn ct_error(_: Layout) -> ! { panic!("allocation failed"); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c459a8da820..7aaa4e73df7 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -183,6 +183,7 @@ #![feature(multiple_supertrait_upcastable)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(optimize_attribute)] #![feature(rustc_allow_const_fn_unstable)] #![feature(rustc_attrs)] #![feature(slice_internals)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 9c8fa7ceff4..a651ba067e4 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -782,6 +782,7 @@ where // Central function for reserve error handling. #[cfg(not(no_global_oom_handling))] #[cold] +#[optimize(size)] fn handle_error(e: TryReserveError) -> ! { match e.kind() { CapacityOverflow => capacity_overflow(), diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e628be1546f..bc8b7e24bf1 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2313,7 +2313,7 @@ impl<'b> Pattern for &'b String { } #[inline] - fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&str> + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> where Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index cfd2e4a1512..162791ba59d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1519,6 +1519,7 @@ impl<T, A: Allocator> Vec<T, A> { #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] + #[optimize(size)] fn assert_failed(index: usize, len: usize) -> ! { panic!("swap_remove index (is {index}) should be < len (is {len})"); } @@ -1567,6 +1568,7 @@ impl<T, A: Allocator> Vec<T, A> { #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] + #[optimize(size)] fn assert_failed(index: usize, len: usize) -> ! { panic!("insertion index (is {index}) should be <= len (is {len})"); } @@ -1629,6 +1631,7 @@ impl<T, A: Allocator> Vec<T, A> { #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] + #[optimize(size)] fn assert_failed(index: usize, len: usize) -> ! { panic!("removal index (is {index}) should be < len (is {len})"); } @@ -2317,6 +2320,7 @@ impl<T, A: Allocator> Vec<T, A> { #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] + #[optimize(size)] fn assert_failed(at: usize, len: usize) -> ! { panic!("`at` split index (is {at}) should be <= len (is {len})"); } diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index e6574ac3c72..fa3c2075423 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -122,7 +122,7 @@ pub const fn from_u32(i: u32) -> Option<char> { self::convert::from_u32(i) } -/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`]. +/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`] /// instead. #[stable(feature = "char_from_unchecked", since = "1.5.0")] #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")] diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index f29ac99b292..eee4a9e4c6c 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -110,43 +110,43 @@ impl<'a> Argument<'a> { } #[inline(always)] - pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'_> { + pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'b> { Self::new(x, Display::fmt) } #[inline(always)] - pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'_> { + pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'b> { Self::new(x, Debug::fmt) } #[inline(always)] - pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'_> { + pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'b> { Self::new(x, |_, _| Ok(())) } #[inline(always)] - pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> { + pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'b> { Self::new(x, Octal::fmt) } #[inline(always)] - pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'_> { + pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'b> { Self::new(x, LowerHex::fmt) } #[inline(always)] - pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'_> { + pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'b> { Self::new(x, UpperHex::fmt) } #[inline(always)] - pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'_> { + pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'b> { Self::new(x, Pointer::fmt) } #[inline(always)] - pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'_> { + pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'b> { Self::new(x, Binary::fmt) } #[inline(always)] - pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'_> { + pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'b> { Self::new(x, LowerExp::fmt) } #[inline(always)] - pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'_> { + pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'b> { Self::new(x, UpperExp::fmt) } #[inline(always)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 06a745b690a..e60bcf3aa5d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -234,6 +234,7 @@ #![feature(never_type)] #![feature(no_core)] #![feature(no_sanitize)] +#![feature(optimize_attribute)] #![feature(prelude_import)] #![feature(repr_simd)] #![feature(rustc_allow_const_fn_unstable)] diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs index a8ec71f0dd8..73230f6ee5b 100644 --- a/library/core/src/net/parser.rs +++ b/library/core/src/net/parser.rs @@ -112,18 +112,18 @@ impl<'a> Parser<'a> { max_digits: Option<usize>, allow_zero_prefix: bool, ) -> Option<T> { - // If max_digits.is_some(), then we are parsing a `u8` or `u16` and - // don't need to use checked arithmetic since it fits within a `u32`. - if let Some(max_digits) = max_digits { - // u32::MAX = 4_294_967_295u32, which is 10 digits long. - // `max_digits` must be less than 10 to not overflow a `u32`. - debug_assert!(max_digits < 10); - - self.read_atomically(move |p| { - let mut result = 0_u32; - let mut digit_count = 0; - let has_leading_zero = p.peek_char() == Some('0'); + self.read_atomically(move |p| { + let mut digit_count = 0; + let has_leading_zero = p.peek_char() == Some('0'); + + // If max_digits.is_some(), then we are parsing a `u8` or `u16` and + // don't need to use checked arithmetic since it fits within a `u32`. + let result = if let Some(max_digits) = max_digits { + // u32::MAX = 4_294_967_295u32, which is 10 digits long. + // `max_digits` must be less than 10 to not overflow a `u32`. + debug_assert!(max_digits < 10); + let mut result = 0_u32; while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { result *= radix; result += digit; @@ -134,19 +134,9 @@ impl<'a> Parser<'a> { } } - if digit_count == 0 { - None - } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { - None - } else { - result.try_into().ok() - } - }) - } else { - self.read_atomically(move |p| { + result.try_into().ok() + } else { let mut result = T::ZERO; - let mut digit_count = 0; - let has_leading_zero = p.peek_char() == Some('0'); while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { result = result.checked_mul(radix)?; @@ -154,15 +144,17 @@ impl<'a> Parser<'a> { digit_count += 1; } - if digit_count == 0 { - None - } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { - None - } else { - Some(result) - } - }) - } + Some(result) + }; + + if digit_count == 0 { + None + } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { + None + } else { + result + } + }) } /// Reads an IPv4 address. diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 7affe638257..e4a62304087 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -264,7 +264,7 @@ pub const fn panic_display<T: fmt::Display>(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access @@ -276,7 +276,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { panic!("index out of bounds: the len is {len} but the index is {index}") } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref @@ -301,7 +301,7 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { /// /// This function is called directly by the codegen backend, and must not have /// any extra arguments (including those synthesized by track_caller). -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function #[rustc_nounwind] @@ -317,7 +317,7 @@ fn panic_cannot_unwind() -> ! { /// /// This function is called directly by the codegen backend, and must not have /// any extra arguments (including those synthesized by track_caller). -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function #[rustc_nounwind] @@ -350,7 +350,7 @@ pub enum AssertKind { } /// Internal function for `assert_eq!` and `assert_ne!` macros -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[doc(hidden)] @@ -368,7 +368,7 @@ where } /// Internal function for `assert_match!` -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[doc(hidden)] @@ -388,7 +388,7 @@ pub fn assert_matches_failed<T: fmt::Debug + ?Sized>( } /// Non-generic version of the above functions, to avoid code bloat. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] fn assert_failed_inner( diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index d19d0eae166..1769612def0 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -3,7 +3,8 @@ use super::{from_raw_parts, memchr}; use crate::cmp::{self, BytewiseEq, Ordering}; use crate::intrinsics::compare_bytes; -use crate::mem; +use crate::num::NonZero; +use crate::{ascii, mem}; #[stable(feature = "rust1", since = "1.0.0")] impl<T, U> PartialEq<[U]> for [T] @@ -182,19 +183,41 @@ impl<A: Ord> SliceOrd for A { } } -// `compare_bytes` compares a sequence of unsigned bytes lexicographically. -// this matches the order we want for [u8], but no others (not even [i8]). -impl SliceOrd for u8 { +/// Marks that a type should be treated as an unsigned byte for comparisons. +/// +/// # Safety +/// * The type must be readable as an `u8`, meaning it has to have the same +/// layout as `u8` and always be initialized. +/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same +/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`. +#[rustc_specialization_trait] +unsafe trait UnsignedBytewiseOrd {} + +unsafe impl UnsignedBytewiseOrd for bool {} +unsafe impl UnsignedBytewiseOrd for u8 {} +unsafe impl UnsignedBytewiseOrd for NonZero<u8> {} +unsafe impl UnsignedBytewiseOrd for Option<NonZero<u8>> {} +unsafe impl UnsignedBytewiseOrd for ascii::Char {} + +// `compare_bytes` compares a sequence of unsigned bytes lexicographically, so +// use it if the requirements for `UnsignedBytewiseOrd` are fulfilled. +impl<A: Ord + UnsignedBytewiseOrd> SliceOrd for A { #[inline] fn compare(left: &[Self], right: &[Self]) -> Ordering { - // Since the length of a slice is always less than or equal to isize::MAX, this never underflows. + // Since the length of a slice is always less than or equal to + // isize::MAX, this never underflows. let diff = left.len() as isize - right.len() as isize; - // This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags. + // This comparison gets optimized away (on x86_64 and ARM) because the + // subtraction updates flags. let len = if left.len() < right.len() { left.len() } else { right.len() }; - // SAFETY: `left` and `right` are references and are thus guaranteed to be valid. - // We use the minimum of both lengths which guarantees that both regions are - // valid for reads in that interval. - let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr(), len) as isize }; + let left = left.as_ptr().cast(); + let right = right.as_ptr().cast(); + // SAFETY: `left` and `right` are references and are thus guaranteed to + // be valid. `UnsignedBytewiseOrd` is only implemented for types that + // are valid u8s and can be compared the same way. We use the minimum + // of both lengths which guarantees that both regions are valid for + // reads in that interval. + let mut order = unsafe { compare_bytes(left, right, len) as isize }; if order == 0 { order = diff; } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5f0144922ca..82cfd603a21 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -35,7 +35,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.153", default-features = false, features = [ +libc = { version = "0.2.156", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index bea8eda2619..606d75668c4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -306,10 +306,12 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(no_sanitize)] +#![feature(optimize_attribute)] #![feature(prelude_import)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(staged_api)] +#![feature(stmt_expr_attributes)] #![feature(thread_local)] #![feature(try_blocks)] #![feature(type_alias_impl_trait)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 190eed94555..1c972d38100 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -231,6 +231,7 @@ where } /// The default panic handler. +#[optimize(size)] fn default_hook(info: &PanicHookInfo<'_>) { // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. @@ -249,7 +250,8 @@ fn default_hook(info: &PanicHookInfo<'_>) { let thread = thread::try_current(); let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>"); - let write = |err: &mut dyn crate::io::Write| { + let write = #[optimize(size)] + |err: &mut dyn crate::io::Write| { // Use a lock to prevent mixed output in multithreading context. // Some platforms also require it when printing a backtrace, like `SymFromAddr` on Windows. let mut lock = backtrace::lock(); @@ -527,6 +529,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> // optimizer (in most cases this function is not inlined even as a normal, // non-cold function, though, as of the writing of this comment). #[cold] + #[optimize(size)] unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> { // SAFETY: The whole unsafe block hinges on a correct implementation of // the panic handler `__rust_panic_cleanup`. As such we can only @@ -686,7 +689,7 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { // lang item for CTFE panic support // never inline unless panic_immediate_abort to avoid code // bloat at the call sites as much as possible -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[rustc_do_not_const_check] // hooked by const-eval @@ -756,6 +759,7 @@ fn payload_as_str(payload: &dyn Any) -> &str { /// Executes the primary logic for a panic, including checking for recursive /// panics, panic hooks, and finally dispatching to the panic runtime to either /// abort or unwind. +#[optimize(size)] fn rust_panic_with_hook( payload: &mut dyn PanicPayload, location: &Location<'_>, diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 56cf877ddc6..a51e5c1b76b 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -498,6 +498,7 @@ impl<T> OnceLock<T> { } #[cold] + #[optimize(size)] fn initialize<F, E>(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result<T, E>, diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index fc9d7e98883..7fa147c9754 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1717,7 +1717,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { run_path_with_cstr(original, &|original| { run_path_with_cstr(link, &|link| { cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita"))] { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nto"))] { // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves // it implementation-defined whether `link` follows symlinks, so rely on the // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 5552e9ac977..9d091f033e0 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -19,7 +19,8 @@ use crate::sys::process::process_common::*; use crate::{fmt, mem, sys}; cfg_if::cfg_if! { - if #[cfg(all(target_os = "nto", target_env = "nto71"))] { + // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 + if #[cfg(any(target_env = "nto70", target_env = "nto71"))] { use crate::thread; use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t}; use crate::time::Duration; @@ -189,7 +190,8 @@ impl Command { #[cfg(not(any( target_os = "watchos", target_os = "tvos", - all(target_os = "nto", target_env = "nto71"), + target_env = "nto70", + target_env = "nto71" )))] unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> { cvt(libc::fork()) @@ -199,7 +201,8 @@ impl Command { // or closed a file descriptor while the fork() was occurring". // Documentation says "... or try calling fork() again". This is what we do here. // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html - #[cfg(all(target_os = "nto", target_env = "nto71"))] + // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 + #[cfg(any(target_env = "nto70", target_env = "nto71"))] unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> { use crate::sys::os::errno; @@ -537,7 +540,7 @@ impl Command { // or closed a file descriptor while the posix_spawn() was occurring". // Documentation says "... or try calling posix_spawn() again". This is what we do here. // See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html - #[cfg(all(target_os = "nto", target_env = "nto71"))] + #[cfg(target_os = "nto")] unsafe fn retrying_libc_posix_spawnp( pid: *mut pid_t, file: *const c_char, diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index b3de71f29f3..250af912e07 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -165,8 +165,15 @@ extern "C" {} extern "C" {} #[cfg(target_os = "nto")] -#[link(name = "gcc_s")] -extern "C" {} +cfg_if::cfg_if! { + if #[cfg(target_env = "nto70")] { + #[link(name = "gcc")] + extern "C" {} + } else { + #[link(name = "gcc_s")] + extern "C" {} + } +} #[cfg(target_os = "hurd")] #[link(name = "gcc_s")] diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 0d79e5f4114..a2641b22753 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -256,6 +256,7 @@ target | std | host | notes [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? | | ARM64 TEEOS | +[`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD [`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 51a397a38d2..1c240d1255a 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -24,6 +24,7 @@ Currently, the following QNX Neutrino versions and compilation targets are suppo |----------------------|---------------------|:------------:|:----------------:| | 7.1 | AArch64 | ✓ | ✓ | | 7.1 | x86_64 | ✓ | ✓ | +| 7.0 | AArch64 | ? | ✓ | | 7.0 | x86 | | ✓ | Adding other architectures that are supported by QNX Neutrino is possible. @@ -43,6 +44,23 @@ When linking `no_std` applications, they must link against `libc.so` (see exampl required because applications always link against the `crt` library and `crt` depends on `libc.so`. This is done automatically when using the standard library. +### Disabling RELocation Read-Only (RELRO) + +While not recommended by default, some QNX kernel setups may require the `RELRO` to be disabled with `-C relro_level=off`, e.g. by adding it to the `.cargo/config.toml` file: + +```toml +[target.aarch64-unknown-nto-qnx700] +rustflags = ["-C", "relro_level=off"] +``` + +If your QNX kernel does not allow it, and `relro` is not disabled, running compiled binary would fail with `syntax error: ... unexpected` or similar. This is due to kernel trying to interpret compiled binary with `/bin/sh`, and obviously failing. To verify that this is really the case, run your binary with the `DL_DEBUG=all` env var, and look for this output. If you see it, you should disable `relro` as described above. + +```text +Resolution scope for Executable->/bin/sh: + Executable->/bin/sh + libc.so.4->/usr/lib/ldqnx-64.so.2 +``` + ### Small example application Small `no_std` example is shown below. Applications using the standard library work as well. diff --git a/src/doc/unstable-book/src/language-features/struct-target-features.md b/src/doc/unstable-book/src/language-features/struct-target-features.md deleted file mode 100644 index e814fe90072..00000000000 --- a/src/doc/unstable-book/src/language-features/struct-target-features.md +++ /dev/null @@ -1,7 +0,0 @@ -# `struct_target_features` - -The tracking issue for this feature is: [#129107] - -[#129107]: https://github.com/rust-lang/rust/issues/129107 - ------------------------- diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr index f325d27b8c7..50f845e2d92 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr +++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr @@ -1,3 +1,14 @@ +error: elided lifetime has a name + --> tests/ui/needless_lifetimes.rs:266:52 + | +LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: the following explicit lifetimes could be elided: 'a, 'b --> tests/ui/needless_lifetimes.rs:17:23 | @@ -553,5 +564,5 @@ LL - fn one_input<'a>(x: &'a u8) -> &'a u8 { LL + fn one_input(x: &u8) -> &u8 { | -error: aborting due to 46 previous errors +error: aborting due to 47 previous errors diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index 1848ef80fc4..4246453e64c 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -1,3 +1,12 @@ +error: elided lifetime has a name + --> tests/ui/ptr_arg.rs:295:56 + | +LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:13:14 | @@ -212,5 +221,5 @@ error: using a reference to `Cow` is not recommended LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` -error: aborting due to 24 previous errors +error: aborting due to 25 previous errors diff --git a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.stderr b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.stderr index 960cae90124..dfe3ed4b522 100644 --- a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.stderr +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: reading memory at ALLOC[0x0..0x10], but memory is uninitialized at [0x4..0x10], and this operation requires initialized memory --> RUSTLIB/core/src/slice/cmp.rs:LL:CC | -LL | let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr(), len) as isize }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x10], but memory is uninitialized at [0x4..0x10], and this operation requires initialized memory +LL | let mut order = unsafe { compare_bytes(left, right, len) as isize }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x10], but memory is uninitialized at [0x4..0x10], and this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr index 5439418f267..48ce9ae7656 100644 --- a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> RUSTLIB/core/src/slice/cmp.rs:LL:CC | -LL | let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr(), len) as isize }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory +LL | let mut order = unsafe { compare_bytes(left, right, len) as isize }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 198dc93f6b1..c0547bc3c8d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -117,7 +117,7 @@ impl Attrs { } impl Attrs { - pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'_> { + pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'attrs> { AttrQuery { attrs: self, key } } @@ -594,7 +594,7 @@ impl<'attr> AttrQuery<'attr> { /// #[doc(html_root_url = "url")] /// ^^^^^^^^^^^^^ key /// ``` - pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&str> { + pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&'attr str> { self.tt_values().find_map(|tt| { let name = tt.token_trees.iter() .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key)) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index f5fe8f87701..dde1f142ab0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -197,7 +197,7 @@ impl Body { pub fn blocks<'a>( &'a self, db: &'a dyn DefDatabase, - ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ { + ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + 'a { self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block))) } diff --git a/tests/assembly/struct-target-features.rs b/tests/assembly/struct-target-features.rs deleted file mode 100644 index cc86fbaa840..00000000000 --- a/tests/assembly/struct-target-features.rs +++ /dev/null @@ -1,37 +0,0 @@ -//@ compile-flags: -O -//@ assembly-output: emit-asm -//@ only-x86_64 - -#![crate_type = "lib"] -#![feature(struct_target_features)] - -// Check that a struct_target_features type causes the compiler to effectively inline intrinsics. - -use std::arch::x86_64::*; - -#[target_feature(enable = "avx")] -struct Avx {} - -#[target_feature(enable = "fma")] -struct Fma {} - -pub fn add_simple(_: Avx, v: __m256) -> __m256 { - // CHECK-NOT: call - // CHECK: vaddps - unsafe { _mm256_add_ps(v, v) } -} - -pub fn add_complex_type(_: (&Avx, ()), v: __m256) -> __m256 { - // CHECK-NOT: call - // CHECK: vaddps - unsafe { _mm256_add_ps(v, v) } -} - -pub fn add_fma_combined(_: (&Avx, &Fma), v: __m256) -> (__m256, __m256) { - // CHECK-NOT: call - // CHECK-DAG: vaddps - let r1 = unsafe { _mm256_add_ps(v, v) }; - // CHECK-DAG: vfmadd213ps - let r2 = unsafe { _mm256_fmadd_ps(v, v, v) }; - (r1, r2) -} diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 6f0a200a08c..b0c5eec1fe4 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -54,6 +54,9 @@ //@ revisions: aarch64_unknown_none_softfloat //@ [aarch64_unknown_none_softfloat] compile-flags: --target aarch64-unknown-none-softfloat //@ [aarch64_unknown_none_softfloat] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_nto_qnx700 +//@ [aarch64_unknown_nto_qnx700] compile-flags: --target aarch64-unknown-nto-qnx700 +//@ [aarch64_unknown_nto_qnx700] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_nto_qnx710 //@ [aarch64_unknown_nto_qnx710] compile-flags: --target aarch64-unknown-nto-qnx710 //@ [aarch64_unknown_nto_qnx710] needs-llvm-components: aarch64 diff --git a/tests/crashes/117460.rs b/tests/crashes/117460.rs new file mode 100644 index 00000000000..4878a35ffe5 --- /dev/null +++ b/tests/crashes/117460.rs @@ -0,0 +1,8 @@ +//@ known-bug: #117460 +#![feature(generic_const_exprs)] + +struct Matrix<D = [(); 2 + 2]> { + d: D, +} + +impl Matrix {} diff --git a/tests/crashes/119095.rs b/tests/crashes/119095.rs new file mode 100644 index 00000000000..28742e0d5da --- /dev/null +++ b/tests/crashes/119095.rs @@ -0,0 +1,48 @@ +//@ known-bug: #119095 +//@ compile-flags: --edition=2021 + +fn any<T>() -> T { + loop {} +} + +trait Acquire { + type Connection; +} + +impl Acquire for &'static () { + type Connection = (); +} + +trait Unit {} +impl Unit for () {} + +fn get_connection<T>() -> impl Unit +where + T: Acquire, + T::Connection: Unit, +{ + any::<T::Connection>() +} + +fn main() { + let future = async { async { get_connection::<&'static ()>() }.await }; + + future.resolve_me(); +} + +trait ResolveMe { + fn resolve_me(self); +} + +impl<S> ResolveMe for S +where + (): CheckSend<S>, +{ + fn resolve_me(self) {} +} + +trait CheckSend<F> {} +impl<F> CheckSend<F> for () where F: Send {} + +trait NeverImplemented {} +impl<E, F> CheckSend<F> for E where E: NeverImplemented {} diff --git a/tests/crashes/126443.rs b/tests/crashes/126443.rs new file mode 100644 index 00000000000..fba779444f9 --- /dev/null +++ b/tests/crashes/126443.rs @@ -0,0 +1,15 @@ +//@ known-bug: #126443 +//@ compile-flags: -Copt-level=0 +#![feature(generic_const_exprs)] + +fn double_up<const M: usize>() -> [(); M * 2] { + todo!() +} + +fn quadruple_up<const N: usize>() -> [(); N * 2 * 2] { + double_up() +} + +fn main() { + quadruple_up::<0>(); +} diff --git a/tests/crashes/128097.rs b/tests/crashes/128097.rs new file mode 100644 index 00000000000..6ffca640cbd --- /dev/null +++ b/tests/crashes/128097.rs @@ -0,0 +1,6 @@ +//@ known-bug: #128097 +#![feature(explicit_tail_calls)] +fn f(x: &mut ()) { + let _y: String; + become f(x); +} diff --git a/tests/debuginfo/option-like-enum.rs b/tests/debuginfo/option-like-enum.rs index d370796efa9..72a41986dce 100644 --- a/tests/debuginfo/option-like-enum.rs +++ b/tests/debuginfo/option-like-enum.rs @@ -8,22 +8,22 @@ // gdb-command:run // gdb-command:print some -// gdb-check:$1 = core::option::Option<&u32>::Some(0x12345678) +// gdb-check:$1 = core::option::Option<&u32>::Some(0x[...]) // gdb-command:print none // gdb-check:$2 = core::option::Option<&u32>::None // gdb-command:print full -// gdb-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988) +// gdb-check:$3 = option_like_enum::MoreFields::Full(454545, 0x[...], 9988) -// gdb-command:print empty_gdb.discr -// gdb-check:$4 = (*mut isize) 0x1 +// gdb-command:print empty +// gdb-check:$4 = option_like_enum::MoreFields::Empty // gdb-command:print droid -// gdb-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765} +// gdb-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x[...]} -// gdb-command:print void_droid_gdb.internals -// gdb-check:$6 = (*mut isize) 0x1 +// gdb-command:print void_droid +// gdb-check:$6 = option_like_enum::NamedFields::Void // gdb-command:print nested_non_zero_yep // gdb-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...]}) @@ -39,19 +39,19 @@ // lldb-command:run // lldb-command:v some -// lldb-check:[...] Some(&0x12345678) +// lldb-check:[...] Some(&0x[...]) // lldb-command:v none // lldb-check:[...] None // lldb-command:v full -// lldb-check:[...] Full(454545, &0x87654321, 9988) +// lldb-check:[...] Full(454545, &0x[...], 9988) // lldb-command:v empty // lldb-check:[...] Empty // lldb-command:v droid -// lldb-check:[...] Droid { id: 675675, range: 10000001, internals: &0x43218765 } +// lldb-check:[...] Droid { id: 675675, range: 10000001, internals: &0x[...] } // lldb-command:v void_droid // lldb-check:[...] Void @@ -76,11 +76,6 @@ // contains a non-nullable pointer, then this value is used as the discriminator. // The test cases in this file make sure that something readable is generated for // this kind of types. -// If the non-empty variant contains a single non-nullable pointer than the whole -// item is represented as just a pointer and not wrapped in a struct. -// Unfortunately (for these test cases) the content of the non-discriminant fields -// in the null-case is not defined. So we just read the discriminator field in -// this case (by casting the value to a memory-equivalent struct). enum MoreFields<'a> { Full(u32, &'a isize, i16), @@ -120,32 +115,26 @@ fn main() { let some_str: Option<&'static str> = Some("abc"); let none_str: Option<&'static str> = None; - let some: Option<&u32> = Some(unsafe { std::mem::transmute(0x12345678_usize) }); + let some: Option<&u32> = Some(&1234); let none: Option<&u32> = None; - let full = MoreFields::Full(454545, unsafe { std::mem::transmute(0x87654321_usize) }, 9988); - + let full = MoreFields::Full(454545, &1234, 9988); let empty = MoreFields::Empty; - let empty_gdb: &MoreFieldsRepr = unsafe { std::mem::transmute(&MoreFields::Empty) }; let droid = NamedFields::Droid { id: 675675, range: 10000001, - internals: unsafe { std::mem::transmute(0x43218765_usize) } + internals: &1234, }; - let void_droid = NamedFields::Void; - let void_droid_gdb: &NamedFieldsRepr = unsafe { std::mem::transmute(&NamedFields::Void) }; - let x = 'x'; let nested_non_zero_yep = NestedNonZero::Yep( 10.5, NestedNonZeroField { a: 10, b: 20, - c: &x + c: &'x', }); - let nested_non_zero_nope = NestedNonZero::Nope; zzz(); // #break diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index c1c2fdcfa94..109a41d1ef9 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -3,14 +3,14 @@ field_tys: { _0: CoroutineSavedTy { ty: Coroutine( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [ (), std::future::ResumeTy, (), (), CoroutineWitness( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [], ), (), @@ -24,14 +24,14 @@ }, _1: CoroutineSavedTy { ty: Coroutine( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [ (), std::future::ResumeTy, (), (), CoroutineWitness( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [], ), (), diff --git a/tests/ui/async-await/issues/issue-63388-1.rs b/tests/ui/async-await/issues/issue-63388-1.rs index 32026a22a16..a6f499ba94e 100644 --- a/tests/ui/async-await/issues/issue-63388-1.rs +++ b/tests/ui/async-await/issues/issue-63388-1.rs @@ -9,7 +9,7 @@ trait Foo {} impl Xyz { async fn do_sth<'a>( &'a self, foo: &dyn Foo - ) -> &dyn Foo + ) -> &dyn Foo //~ WARNING elided lifetime has a name { //~^ ERROR explicit lifetime required in the type of `foo` [E0621] foo diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index f7f285ad0cc..ef74bfe3237 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -1,3 +1,14 @@ +warning: elided lifetime has a name + --> $DIR/issue-63388-1.rs:12:10 + | +LL | async fn do_sth<'a>( + | -- lifetime `'a` declared here +LL | &'a self, foo: &dyn Foo +LL | ) -> &dyn Foo + | ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 | @@ -10,6 +21,6 @@ LL | | foo LL | | } | |_____^ lifetime `'a` required -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr new file mode 100644 index 00000000000..177ff20fbf9 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -0,0 +1,10 @@ +warning: elided lifetime has a name + --> $DIR/issue-71348.rs:18:68 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 858900a500d..5aee282952a 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -1,3 +1,11 @@ +warning: elided lifetime has a name + --> $DIR/issue-71348.rs:18:68 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 | @@ -30,5 +38,5 @@ help: add `#![feature(unsized_const_params)]` to the crate attributes to enable LL + #![feature(unsized_const_params)] | -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.rs b/tests/ui/const-generics/type-dependent/issue-71348.rs index 2ffbd015485..97e786405fe 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.rs +++ b/tests/ui/const-generics/type-dependent/issue-71348.rs @@ -17,6 +17,7 @@ trait Get<'a, const N: &'static str> { impl Foo { fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + //~^^ WARNING elided lifetime has a name where Self: Get<'a, N>, { diff --git a/tests/ui/consts/min_const_fn/min_const_fn.rs b/tests/ui/consts/min_const_fn/min_const_fn.rs index 76245c08ffc..f7663f6044e 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn.rs @@ -44,8 +44,8 @@ impl<T> Foo<T> { impl<'a, T> Foo<T> { const fn new_lt(t: T) -> Self { Foo(t) } const fn into_inner_lt(self) -> T { self.0 } //~ destructor of - const fn get_lt(&'a self) -> &T { &self.0 } - const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + const fn get_lt(&'a self) -> &T { &self.0 } //~ WARNING elided lifetime has a name + const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } //~ WARNING elided lifetime has a name //~^ mutable references //~| mutable references //~| mutable references diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index daa0ab2614f..4b348a182b8 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -1,3 +1,23 @@ +warning: elided lifetime has a name + --> $DIR/min_const_fn.rs:47:34 + | +LL | impl<'a, T> Foo<T> { + | -- lifetime `'a` declared here +... +LL | const fn get_lt(&'a self) -> &T { &self.0 } + | ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/min_const_fn.rs:48:42 + | +LL | impl<'a, T> Foo<T> { + | -- lifetime `'a` declared here +... +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^ this elided lifetime gets resolved as `'a` + error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | @@ -228,7 +248,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 24 previous errors +error: aborting due to 24 previous errors; 2 warnings emitted Some errors have detailed explanations: E0493, E0658. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr index 934ab08cf17..daf88fc1f23 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr @@ -10,7 +10,7 @@ note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-1.rs:35:9 | LL | let _non_send_gen = make_non_send_coroutine(); - | ------------- has type `Opaque(DefId(0:34 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send` + | ------------- has type `Opaque(DefId(0:24 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later note: required by a bound in `require_send` @@ -33,12 +33,12 @@ note: required because it's used within this coroutine | LL | #[coroutine] || { | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])` +note: required because it appears within the type `Opaque(DefId(0:29 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])` --> $DIR/coroutine-print-verbose-1.rs:41:30 | LL | pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `Opaque(DefId(0:36 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])` +note: required because it appears within the type `Opaque(DefId(0:32 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])` --> $DIR/coroutine-print-verbose-1.rs:47:34 | LL | fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> { diff --git a/tests/ui/error-codes/E0602.stderr b/tests/ui/error-codes/E0602.stderr index b0b6033aadd..b6b5cd5c3d3 100644 --- a/tests/ui/error-codes/E0602.stderr +++ b/tests/ui/error-codes/E0602.stderr @@ -13,11 +13,6 @@ warning[E0602]: unknown lint: `bogus` = note: requested on the command line with `-D bogus` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 4 warnings emitted +warning: 3 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.rs b/tests/ui/feature-gates/feature-gate-struct-target-features.rs deleted file mode 100644 index 85494881146..00000000000 --- a/tests/ui/feature-gates/feature-gate-struct-target-features.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[target_feature(enable = "avx")] //~ ERROR attribute should be applied to a function definition -struct Avx {} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.stderr b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr deleted file mode 100644 index 1e18d3ee1e1..00000000000 --- a/tests/ui/feature-gates/feature-gate-struct-target-features.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: attribute should be applied to a function definition - --> $DIR/feature-gate-struct-target-features.rs:1:1 - | -LL | #[target_feature(enable = "avx")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | struct Avx {} - | ------------- not a function definition - -error: aborting due to 1 previous error - diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed index 69db712f9dc..2776848c45f 100644 --- a/tests/ui/generics/generic-no-mangle.fixed +++ b/tests/ui/generics/generic-no-mangle.fixed @@ -1,5 +1,5 @@ //@ run-rustfix -#![allow(dead_code)] +#![allow(dead_code, elided_named_lifetimes)] #![deny(no_mangle_generic_items)] pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs index 2288b5bbe70..5314005d31f 100644 --- a/tests/ui/generics/generic-no-mangle.rs +++ b/tests/ui/generics/generic-no-mangle.rs @@ -1,5 +1,5 @@ //@ run-rustfix -#![allow(dead_code)] +#![allow(dead_code, elided_named_lifetimes)] #![deny(no_mangle_generic_items)] #[no_mangle] diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs index da7530b4e7a..a7f38b5c16a 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -13,6 +13,7 @@ fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + //~| WARNING elided lifetime has a name |x| x } diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 7d108b30b76..d0f8f7689d1 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/impl-fn-hrtb-bounds.rs:19:38 + --> $DIR/impl-fn-hrtb-bounds.rs:20:38 | LL | fn d() -> impl Fn() -> (impl Debug + '_) { | ^^ expected named lifetime parameter @@ -10,6 +10,14 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn d() -> impl Fn() -> (impl Debug + 'static) { | ~~~~~~~ +warning: elided lifetime has a name + --> $DIR/impl-fn-hrtb-bounds.rs:14:52 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 | @@ -46,7 +54,7 @@ note: lifetime declared here LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0106, E0657. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 8aba3de530b..2f17c0ff508 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { //~^ ERROR cannot resolve opaque type + //~| WARNING elided lifetime has a name |x| x //~^ ERROR expected generic lifetime parameter, found `'_` } diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index c2386e8c88b..50a9f3ebeab 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,9 +1,17 @@ +warning: elided lifetime has a name + --> $DIR/impl-fn-predefined-lifetimes.rs:4:48 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:6:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- this generic parameter must be used with a generic lifetime parameter -LL | +... LL | |x| x | ^ @@ -13,7 +21,7 @@ error[E0720]: cannot resolve opaque type LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | ^^^^^^^^^^^^^^^ cannot resolve opaque type -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted Some errors have detailed explanations: E0720, E0792. For more information about an error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs index 73c8a6c0aed..e48441f533d 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs @@ -1,6 +1,7 @@ //@ check-pass pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &u32)> { + //~^ WARNING elided lifetime has a name v.into_iter() } diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr new file mode 100644 index 00000000000..bff3ffd934a --- /dev/null +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -0,0 +1,10 @@ +warning: elided lifetime has a name + --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:82 + | +LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &u32)> { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs index d0a8fe795ef..63a2c9be9eb 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -47,5 +47,6 @@ fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } // This is ok because both `'a` are for the same parameter. fn m<'a>(_: &'a Foo<'a>) -> &str { "" } +//~^ WARNING elided lifetime has a name fn main() {} diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 23ef36888f0..f835d2655bb 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -105,6 +105,16 @@ help: consider using the `'a` lifetime LL | fn l<'a>(_: &'a str, _: &'a str) -> &'a str { "" } | ++ -error: aborting due to 7 previous errors +warning: elided lifetime has a name + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:49:29 + | +LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs index a1126d6bb15..598633d7576 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -4,6 +4,7 @@ struct Foo { impl Foo { fn foo<'a>(&'a self, x: &i32) -> &i32 { + //~^ WARNING elided lifetime has a name if true { &self.field } else { x } //~ ERROR explicit lifetime diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 6dda9e61a79..2d5d4fb0e72 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -1,12 +1,22 @@ +warning: elided lifetime has a name + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:6:36 + | +LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:8:36 + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 | LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -LL | +... LL | if true { &self.field } else { x } | ^ lifetime `'a` required -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/cli-unknown-force-warn.stderr index cfff190b54a..5084b4a4001 100644 --- a/tests/ui/lint/cli-unknown-force-warn.stderr +++ b/tests/ui/lint/cli-unknown-force-warn.stderr @@ -13,11 +13,6 @@ warning[E0602]: unknown lint: `foo_qux` = note: requested on the command line with `--force-warn foo_qux` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning[E0602]: unknown lint: `foo_qux` - | - = note: requested on the command line with `--force-warn foo_qux` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 4 warnings emitted +warning: 3 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs new file mode 100644 index 00000000000..eac7c32a9aa --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs @@ -0,0 +1,12 @@ +#![deny(elided_named_lifetimes)] + +struct Foo; + +impl Foo { + pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + //~^ ERROR elided lifetime has a name + unsafe { &mut *(x as *mut _) } + } +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr new file mode 100644 index 00000000000..8c5426a60cb --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr @@ -0,0 +1,14 @@ +error: elided lifetime has a name + --> $DIR/example-from-issue48686.rs:6:50 + | +LL | pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/example-from-issue48686.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs new file mode 100644 index 00000000000..2f9083ed65f --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs @@ -0,0 +1,27 @@ +#![deny(elided_named_lifetimes)] + +fn ampersand<'a>(x: &'a u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x +} + +struct Brackets<'a>(&'a u8); + +fn brackets<'a>(x: &'a u8) -> Brackets { + //~^ ERROR elided lifetime has a name + Brackets(x) +} + +struct Comma<'a, T>(&'a T); + +fn comma<'a>(x: &'a u8) -> Comma<u8> { + //~^ ERROR elided lifetime has a name + Comma(x) +} + +fn underscore<'a>(x: &'a u8) -> &'_ u8 { + //~^ ERROR elided lifetime has a name + x +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr new file mode 100644 index 00000000000..249ae146b16 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -0,0 +1,40 @@ +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:3:32 + | +LL | fn ampersand<'a>(x: &'a u8) -> &u8 { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | +note: the lint level is defined here + --> $DIR/missing-lifetime-kind.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:10:31 + | +LL | fn brackets<'a>(x: &'a u8) -> Brackets { + | -- ^^^^^^^^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:17:33 + | +LL | fn comma<'a>(x: &'a u8) -> Comma<u8> { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:22:34 + | +LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { + | -- ^^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs new file mode 100644 index 00000000000..4f9218130fb --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs @@ -0,0 +1,17 @@ +#![allow(elided_named_lifetimes)] + +#[warn(elided_named_lifetimes)] +mod foo { + fn bar(x: &'static u8) -> &u8 { + //~^ WARNING elided lifetime has a name + x + } + + #[deny(elided_named_lifetimes)] + fn baz(x: &'static u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x + } +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr new file mode 100644 index 00000000000..c465aab1a03 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr @@ -0,0 +1,26 @@ +warning: elided lifetime has a name + --> $DIR/not-tied-to-crate.rs:5:31 + | +LL | fn bar(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/not-tied-to-crate.rs:3:8 + | +LL | #[warn(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/not-tied-to-crate.rs:11:31 + | +LL | fn baz(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/not-tied-to-crate.rs:10:12 + | +LL | #[deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/lint/elided-named-lifetimes/static.rs b/tests/ui/lint/elided-named-lifetimes/static.rs new file mode 100644 index 00000000000..dc8222c6e6e --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/static.rs @@ -0,0 +1,46 @@ +#![deny(elided_named_lifetimes)] + +use std::borrow::Cow; + +const A: &[u8] = &[]; +static B: &str = "hello"; + +trait Trait { + const C: &u8 = &0; +} + +impl Trait for () { + const C: &u8 = &1; +} + +fn ampersand(x: &'static u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x +} + +struct Brackets<'a>(&'a u8); + +fn brackets(x: &'static u8) -> Brackets { + //~^ ERROR elided lifetime has a name + Brackets(x) +} + +struct Comma<'a, T>(&'a T); + +fn comma(x: &'static u8) -> Comma<u8> { + //~^ ERROR elided lifetime has a name + Comma(x) +} + +fn underscore(x: &'static u8) -> &'_ u8 { + //~^ ERROR elided lifetime has a name + x +} + +const NESTED: &Vec<&Box<Cow<str>>> = &vec![]; + +fn main() { + const HELLO: &str = "Hello"; + static WORLD: &str = "world"; + println!("{HELLO}, {WORLD}!") +} diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr new file mode 100644 index 00000000000..d2e9776cb4f --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/static.stderr @@ -0,0 +1,32 @@ +error: elided lifetime has a name + --> $DIR/static.rs:16:33 + | +LL | fn ampersand(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/static.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/static.rs:23:32 + | +LL | fn brackets(x: &'static u8) -> Brackets { + | ^^^^^^^^ this elided lifetime gets resolved as `'static` + +error: elided lifetime has a name + --> $DIR/static.rs:30:34 + | +LL | fn comma(x: &'static u8) -> Comma<u8> { + | ^ this elided lifetime gets resolved as `'static` + +error: elided lifetime has a name + --> $DIR/static.rs:35:35 + | +LL | fn underscore(x: &'static u8) -> &'_ u8 { + | ^^ this elided lifetime gets resolved as `'static` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr index 2a24e795f44..3321afa7fcd 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr @@ -26,10 +26,5 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` -error: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok - | - = note: requested on the command line with `-D raw_pointer_derive` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index 78ae2fd8fbf..fd63433c308 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -26,10 +26,5 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` -warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok - | - = note: requested on the command line with `-D raw_pointer_derive` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 1 previous error; 4 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr index 3c1a59ec1e1..0e182a4e5de 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr @@ -29,11 +29,5 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -error: lint `bare_trait_object` has been renamed to `bare_trait_objects` - | - = help: use the new name `bare_trait_objects` - = note: requested on the command line with `-D bare_trait_object` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index 6544416f611..d6bb72f34dc 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -29,11 +29,5 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` - | - = help: use the new name `bare_trait_objects` - = note: requested on the command line with `-D bare_trait_object` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 1 previous error; 4 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/lint/lint-unexported-no-mangle.stderr b/tests/ui/lint/lint-unexported-no-mangle.stderr index 39377b6fe84..0efec51abaf 100644 --- a/tests/ui/lint/lint-unexported-no-mangle.stderr +++ b/tests/ui/lint/lint-unexported-no-mangle.stderr @@ -45,15 +45,5 @@ LL | pub const PUB_FOO: u64 = 1; | | | help: try a static value: `pub static` -warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported - | - = note: requested on the command line with `-F private_no_mangle_fns` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported - | - = note: requested on the command line with `-F private_no_mangle_statics` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors; 8 warnings emitted +error: aborting due to 2 previous errors; 6 warnings emitted diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr index 1ce55706d76..f12ce03ddfc 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr @@ -30,17 +30,6 @@ error[E0602]: unknown lint: `dead_cod` = note: requested on the command line with `-D dead_cod` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr index 4e0c5dbcb07..f452fc9eb94 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline.stderr @@ -30,17 +30,6 @@ warning[E0602]: unknown lint: `dead_cod` = note: requested on the command line with `-D dead_cod` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 8 warnings emitted +warning: 6 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 3ceefbc4066..87bbd50a15c 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,16 +1,16 @@ -error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds +error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { | -- ------------ opaque type defined here | | - | hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here + | hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here LL | x | ^ | -help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` +help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_))` | -LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> { +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> { | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.rs b/tests/ui/object-lifetime/object-lifetime-default-elision.rs index f7c0261cfbb..ede6af51174 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.rs @@ -46,6 +46,8 @@ fn load1(ss: &dyn SomeTrait) -> &dyn SomeTrait { } fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + //~^ WARNING elided lifetime has a name + // Same as `load1` but with an explicit name thrown in for fun. ss diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index b5995687927..b44a184c684 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -1,5 +1,15 @@ +warning: elided lifetime has a name + --> $DIR/object-lifetime-default-elision.rs:48:40 + | +LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error: lifetime may not live long enough - --> $DIR/object-lifetime-default-elision.rs:71:5 + --> $DIR/object-lifetime-default-elision.rs:73:5 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | -- -- lifetime `'b` defined here @@ -11,5 +21,5 @@ LL | ss | = help: consider adding the following bound: `'a: 'b` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs index f7f61b8c810..cedc6f0f9bc 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs @@ -4,9 +4,11 @@ struct Foo<'a>(&'a str); impl<'b> Foo<'b> { fn a<'a>(self: Self, a: &'a str) -> &str { + //~^ WARNING elided lifetime has a name a } fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { + //~^ WARNING elided lifetime has a name a } } diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr new file mode 100644 index 00000000000..4465dbae529 --- /dev/null +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -0,0 +1,16 @@ +warning: elided lifetime has a name + --> $DIR/ignore-non-reference-lifetimes.rs:6:41 + | +LL | fn a<'a>(self: Self, a: &'a str) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/ignore-non-reference-lifetimes.rs:10:44 + | +LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/self/elision/lt-ref-self-async.fixed b/tests/ui/self/elision/lt-ref-self-async.fixed index aa1d62012da..914511641b8 100644 --- a/tests/ui/self/elision/lt-ref-self-async.fixed +++ b/tests/ui/self/elision/lt-ref-self-async.fixed @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-rustfix -#![allow(non_snake_case, dead_code)] +#![allow(non_snake_case, dead_code, elided_named_lifetimes)] use std::pin::Pin; diff --git a/tests/ui/self/elision/lt-ref-self-async.rs b/tests/ui/self/elision/lt-ref-self-async.rs index 38de0fd39f0..0c11b271c35 100644 --- a/tests/ui/self/elision/lt-ref-self-async.rs +++ b/tests/ui/self/elision/lt-ref-self-async.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-rustfix -#![allow(non_snake_case, dead_code)] +#![allow(non_snake_case, dead_code, elided_named_lifetimes)] use std::pin::Pin; diff --git a/tests/ui/self/self_lifetime-async.rs b/tests/ui/self/self_lifetime-async.rs index 7d6eb3f5eaf..fd690207118 100644 --- a/tests/ui/self/self_lifetime-async.rs +++ b/tests/ui/self/self_lifetime-async.rs @@ -4,11 +4,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + //~^ WARNING elided lifetime has a name } type Alias = Foo<'static>; impl Alias { async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + //~^ WARNING elided lifetime has a name } fn main() {} diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr new file mode 100644 index 00000000000..32de3fd18c9 --- /dev/null +++ b/tests/ui/self/self_lifetime-async.stderr @@ -0,0 +1,18 @@ +warning: elided lifetime has a name + --> $DIR/self_lifetime-async.rs:6:44 + | +LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + | -- ^ this elided lifetime gets resolved as `'b` + | | + | lifetime `'b` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/self_lifetime-async.rs:12:52 + | +LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/self/self_lifetime.rs b/tests/ui/self/self_lifetime.rs index 3f655b960b1..0607c3b9317 100644 --- a/tests/ui/self/self_lifetime.rs +++ b/tests/ui/self/self_lifetime.rs @@ -5,11 +5,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + //~^ WARNING elided lifetime has a name } type Alias = Foo<'static>; impl Alias { fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + //~^ WARNING elided lifetime has a name } fn main() {} diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr new file mode 100644 index 00000000000..cd8f4d8adf8 --- /dev/null +++ b/tests/ui/self/self_lifetime.stderr @@ -0,0 +1,18 @@ +warning: elided lifetime has a name + --> $DIR/self_lifetime.rs:7:38 + | +LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + | -- ^ this elided lifetime gets resolved as `'b` + | | + | lifetime `'b` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/self_lifetime.rs:13:46 + | +LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs index 735efe89cba..daec66709b6 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -64,6 +64,7 @@ mod in_path { // This must not err, as the `&` actually resolves to `'a`. fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { + //~^ WARNING elided lifetime has a name f("f"); } diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 61a2925f582..30f4509d49d 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -124,6 +124,14 @@ LL - fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } LL + fn g(mut x: impl Foo<()>) -> Option<()> { x.next() } | +warning: elided lifetime has a name + --> $DIR/impl-trait-missing-lifetime-gated.rs:66:57 + | +LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 | @@ -244,7 +252,7 @@ help: consider introducing a named lifetime parameter LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() } | ++++ +++ -error: aborting due to 16 previous errors +error: aborting due to 16 previous errors; 1 warning emitted Some errors have detailed explanations: E0106, E0658. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index b641f5941dc..b61bea16e3b 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -100,6 +100,7 @@ where // This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a +//~^ WARNING elided lifetime has a name where G: Get<T>, { diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 88a18e9d06d..ea01dcd5020 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,6 +6,14 @@ LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` +warning: elided lifetime has a name + --> $DIR/missing-lifetimes-in-signature.rs:102:64 + | +LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds --> $DIR/missing-lifetimes-in-signature.rs:19:5 | @@ -125,7 +133,7 @@ help: consider adding an explicit lifetime bound LL | G: Get<T> + 'a, | ++++ -error: aborting due to 8 previous errors +error: aborting due to 8 previous errors; 1 warning emitted Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/target-feature/struct-target-features.rs b/tests/ui/target-feature/struct-target-features.rs deleted file mode 100644 index feb479b6dc8..00000000000 --- a/tests/ui/target-feature/struct-target-features.rs +++ /dev/null @@ -1,98 +0,0 @@ -//@ only-x86_64 -#![feature(struct_target_features)] -//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes -#![feature(target_feature_11)] - -use std::arch::x86_64::*; - -#[target_feature(enable = "avx")] -//~^ ERROR attribute should be applied to a function definition or unit struct -struct Invalid(u32); - -#[target_feature(enable = "avx")] -struct Avx {} - -#[target_feature(enable = "sse")] -struct Sse(); - -#[target_feature(enable = "avx")] -fn avx() {} - -trait TFAssociatedType { - type Assoc; -} - -impl TFAssociatedType for () { - type Assoc = Avx; -} - -fn avx_self(_: <() as TFAssociatedType>::Assoc) { - avx(); -} - -fn avx_avx(_: Avx) { - avx(); -} - -extern "C" fn bad_fun(_: Avx) {} -//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI - -#[inline(always)] -//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]` -fn inline_fun(_: Avx) {} -//~^ ERROR cannot use a struct with target features in a #[inline(always)] function - -trait Simd { - fn do_something(&self); -} - -impl Simd for Avx { - fn do_something(&self) { - unsafe { - println!("{:?}", _mm256_setzero_ps()); - } - } -} - -impl Simd for Sse { - fn do_something(&self) { - unsafe { - println!("{:?}", _mm_setzero_ps()); - } - } -} - -struct WithAvx { - #[allow(dead_code)] - avx: Avx, -} - -impl Simd for WithAvx { - fn do_something(&self) { - unsafe { - println!("{:?}", _mm256_setzero_ps()); - } - } -} - -#[inline(never)] -fn dosomething<S: Simd>(simd: &S) { - simd.do_something(); -} - -fn avxfn(_: &Avx) {} - -fn main() { - Avx {}; - //~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133] - - if is_x86_feature_detected!("avx") { - let avx = unsafe { Avx {} }; - avxfn(&avx); - dosomething(&avx); - dosomething(&WithAvx { avx }); - } - if is_x86_feature_detected!("sse") { - dosomething(&unsafe { Sse {} }) - } -} diff --git a/tests/ui/target-feature/struct-target-features.stderr b/tests/ui/target-feature/struct-target-features.stderr deleted file mode 100644 index 5ef863f504e..00000000000 --- a/tests/ui/target-feature/struct-target-features.stderr +++ /dev/null @@ -1,47 +0,0 @@ -warning: the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/struct-target-features.rs:2:12 - | -LL | #![feature(struct_target_features)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #129107 <https://github.com/rust-lang/rust/issues/129107> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: attribute should be applied to a function definition or unit struct - --> $DIR/struct-target-features.rs:8:1 - | -LL | #[target_feature(enable = "avx")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct Invalid(u32); - | -------------------- not a function definition or a unit struct - -error: cannot use a struct with target features in a function with non-Rust ABI - --> $DIR/struct-target-features.rs:37:1 - | -LL | extern "C" fn bad_fun(_: Avx) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: cannot use a struct with target features in a #[inline(always)] function - --> $DIR/struct-target-features.rs:42:1 - | -LL | fn inline_fun(_: Avx) {} - | ^^^^^^^^^^^^^^^^^^^^^ - -error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/struct-target-features.rs:40:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - -error[E0133]: initializing type with `target_feature` attr is unsafe and requires unsafe function or block - --> $DIR/struct-target-features.rs:86:5 - | -LL | Avx {}; - | ^^^^^^ initializing type with `target_feature` attr - | - = note: this struct can only be constructed if the corresponding `target_feature`s are available - -error: aborting due to 5 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs index c584a58cb32..c178fcf5a91 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs @@ -2,7 +2,7 @@ type Opaque2<T> = impl Sized; type Opaque<'a, T> = Opaque2<T>; -fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } +fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } //~ WARNING elided lifetime has a name //~^ ERROR: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds fn main() {} diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 03cc943d509..e2c21f1636b 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -1,3 +1,13 @@ +warning: elided lifetime has a name + --> $DIR/missing_lifetime_bound.rs:5:41 + | +LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0700]: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 | @@ -9,6 +19,6 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } | | | hidden type `&'a i32` captures the lifetime `'a` as defined here -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0700`. |
