diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1245d48975470..fb42cfea30b41 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -98,7 +98,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let expr_hir_id = self.lower_node_id(e.id); - self.lower_attrs(expr_hir_id, &e.attrs, e.span); + let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span); let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), @@ -232,10 +232,10 @@ impl<'hir> LoweringContext<'_, 'hir> { *fn_arg_span, ), None => self.lower_expr_closure( + attrs, binder, *capture_clause, e.id, - expr_hir_id, *constness, *movability, fn_decl, @@ -1052,10 +1052,10 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_closure( &mut self, + attrs: &[rustc_hir::Attribute], binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, - closure_hir_id: hir::HirId, constness: Const, movability: Movability, decl: &FnDecl, @@ -1067,15 +1067,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { - let mut coroutine_kind = if this - .attrs - .get(&closure_hir_id.local_id) - .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) - { - Some(hir::CoroutineKind::Coroutine(Movability::Movable)) - } else { - None - }; + + let mut coroutine_kind = find_attr!(attrs, AttributeKind::Coroutine(_) => hir::CoroutineKind::Coroutine(Movability::Movable)); + // FIXME(contracts): Support contracts on closures? let body_id = this.lower_fn_body(decl, None, |this| { this.coroutine_kind = coroutine_kind; diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 42f3569f0f1e1..53e64439afc66 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -40,7 +40,7 @@ ast_passes_auto_generic = auto traits cannot have generic parameters ast_passes_auto_items = auto traits cannot have associated items .label = {ast_passes_auto_items} - .suggestion = remove these associated items + .suggestion = remove the associated items ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds .label = {ast_passes_auto_super_lifetime} diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ae482ceb9b72b..1c1c5f82f3ef3 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -699,19 +699,23 @@ impl<'a> AstValidator<'a> { } } - fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) { + fn deny_super_traits(&self, bounds: &GenericBounds, ident: Span) { if let [.., last] = &bounds[..] { - let span = ident_span.shrink_to_hi().to(last.span()); - self.dcx().emit_err(errors::AutoTraitBounds { span, ident: ident_span }); + let span = bounds.iter().map(|b| b.span()).collect(); + let removal = ident.shrink_to_hi().to(last.span()); + self.dcx().emit_err(errors::AutoTraitBounds { span, removal, ident }); } } - fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) { + fn deny_where_clause(&self, where_clause: &WhereClause, ident: Span) { if !where_clause.predicates.is_empty() { // FIXME: The current diagnostic is misleading since it only talks about // super trait and lifetime bounds while we should just say “bounds”. - self.dcx() - .emit_err(errors::AutoTraitBounds { span: where_clause.span, ident: ident_span }); + self.dcx().emit_err(errors::AutoTraitBounds { + span: vec![where_clause.span], + removal: where_clause.span, + ident, + }); } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 8b5873a3ef37a..60f47490f12a6 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -344,7 +344,7 @@ pub(crate) struct ModuleNonAscii { #[diag(ast_passes_auto_generic, code = E0567)] pub(crate) struct AutoTraitGeneric { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] pub span: Span, #[label] pub ident: Span, @@ -354,8 +354,9 @@ pub(crate) struct AutoTraitGeneric { #[diag(ast_passes_auto_super_lifetime, code = E0568)] pub(crate) struct AutoTraitBounds { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] - pub span: Span, + pub span: Vec, + #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + pub removal: Span, #[label] pub ident: Span, } @@ -365,7 +366,7 @@ pub(crate) struct AutoTraitBounds { pub(crate) struct AutoTraitItems { #[primary_span] pub spans: Vec, - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] pub total: Span, #[label] pub ident: Span, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 35ff48cb5f24b..aa8046add7145 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -32,6 +32,11 @@ attr_parsing_ill_formed_attribute_input = {$num_suggestions -> *[other] valid forms for the attribute are {$suggestions} } +attr_parsing_invalid_macro_export_arguments = {$num_suggestions -> + [1] attribute must be of the form {$suggestions} + *[other] valid forms for the attribute are {$suggestions} + } + attr_parsing_incorrect_repr_format_align_one_arg = incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses diff --git a/compiler/rustc_attr_parsing/src/attributes/body.rs b/compiler/rustc_attr_parsing/src/attributes/body.rs new file mode 100644 index 0000000000000..ab9330216f6c6 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/body.rs @@ -0,0 +1,15 @@ +//! Attributes that can be found in function body. + +use rustc_hir::attrs::AttributeKind; +use rustc_span::{Symbol, sym}; + +use super::{NoArgsAttributeParser, OnDuplicate}; +use crate::context::Stage; + +pub(crate) struct CoroutineParser; + +impl NoArgsAttributeParser for CoroutineParser { + const PATH: &[Symbol] = &[sym::coroutine]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const CREATE: fn(rustc_span::Span) -> AttributeKind = |span| AttributeKind::Coroutine(span); +} diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 886f7a889d303..122d80cca046e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -1,10 +1,14 @@ use rustc_errors::DiagArgValue; use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::{AttributeKind, MacroUseArgs}; +use rustc_hir::lints::AttributeLintKind; use rustc_span::{Span, Symbol, sym}; use thin_vec::ThinVec; -use crate::attributes::{AcceptMapping, AttributeParser, NoArgsAttributeParser, OnDuplicate}; +use crate::attributes::{ + AcceptMapping, AttributeOrder, AttributeParser, NoArgsAttributeParser, OnDuplicate, + SingleAttributeParser, +}; use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics; @@ -113,3 +117,58 @@ impl AttributeParser for MacroUseParser { Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state }) } } + +pub(crate) struct MacroExportParser; + +impl SingleAttributeParser for crate::attributes::macro_attrs::MacroExportParser { + const PATH: &[Symbol] = &[sym::macro_export]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word, List: "local_inner_macros"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let suggestions = + || >::TEMPLATE.suggestions(false, "macro_export"); + let local_inner_macros = match args { + ArgParser::NoArgs => false, + ArgParser::List(list) => { + let Some(l) = list.single() else { + let span = cx.attr_span; + cx.emit_lint( + AttributeLintKind::InvalidMacroExportArguments { + suggestions: suggestions(), + }, + span, + ); + return None; + }; + match l.meta_item().and_then(|i| i.path().word_sym()) { + Some(sym::local_inner_macros) => true, + _ => { + let span = cx.attr_span; + cx.emit_lint( + AttributeLintKind::InvalidMacroExportArguments { + suggestions: suggestions(), + }, + span, + ); + return None; + } + } + } + ArgParser::NameValue(_) => { + let span = cx.attr_span; + let suggestions = suggestions(); + cx.emit_err(session_diagnostics::IllFormedAttributeInputLint { + num_suggestions: suggestions.len(), + suggestions: DiagArgValue::StrListSepByAnd( + suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), + ), + span, + }); + return None; + } + }; + Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros }) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index c574ef78bdf79..f7946ade6d2b2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -26,6 +26,7 @@ use crate::parser::ArgParser; use crate::session_diagnostics::UnusedMultiple; pub(crate) mod allow_unstable; +pub(crate) mod body; pub(crate) mod cfg; pub(crate) mod cfg_old; pub(crate) mod codegen_attrs; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index c6599f20c2d1f..7f3e728d23f8e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -16,6 +16,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{ AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser, }; +use crate::attributes::body::CoroutineParser; use crate::attributes::codegen_attrs::{ ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser, @@ -32,7 +33,7 @@ use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, }; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; -use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser}; +use crate::attributes::macro_attrs::{MacroEscapeParser, MacroExportParser, MacroUseParser}; use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::non_exhaustive::NonExhaustiveParser; @@ -164,6 +165,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, @@ -184,6 +186,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs index 22f5531bc8079..359b0ef0dd12c 100644 --- a/compiler/rustc_attr_parsing/src/lints.rs +++ b/compiler/rustc_attr_parsing/src/lints.rs @@ -34,5 +34,17 @@ pub fn emit_attribute_lint(lint: &AttributeLint, lint_emi *first_span, session_diagnostics::EmptyAttributeList { attr_span: *first_span }, ), + AttributeLintKind::InvalidMacroExportArguments { suggestions } => lint_emitter + .emit_node_span_lint( + rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS, + *id, + *span, + session_diagnostics::IllFormedAttributeInput { + num_suggestions: suggestions.len(), + suggestions: DiagArgValue::StrListSepByAnd( + suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), + ), + }, + ), } } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 53899da183a3a..3b290e5a12919 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -262,6 +262,15 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, // only existed in 18 ("arm", "fp16") => Some(LLVMFeature::new("fullfp16")), + // NVPTX targets added in LLVM 20 + ("nvptx64", "sm_100") if get_version().0 < 20 => None, + ("nvptx64", "sm_100a") if get_version().0 < 20 => None, + ("nvptx64", "sm_101") if get_version().0 < 20 => None, + ("nvptx64", "sm_101a") if get_version().0 < 20 => None, + ("nvptx64", "sm_120") if get_version().0 < 20 => None, + ("nvptx64", "sm_120a") if get_version().0 < 20 => None, + ("nvptx64", "ptx86") if get_version().0 < 20 => None, + ("nvptx64", "ptx87") if get_version().0 < 20 => None, // Filter out features that are not supported by the current LLVM version ("loongarch64", "div32" | "lam-bh" | "lamcas" | "ld-seq-sa" | "scq") if get_version().0 < 20 => @@ -324,15 +333,12 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option TargetConfig { - // Add base features for the target. - // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below. - // The reason is that if LLVM considers a feature implied but we do not, we don't want that to - // show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of - // the target CPU, that is still expanded to target features (with all their implied features) - // by LLVM. let target_machine = create_informational_target_machine(sess, true); let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| { + // This closure determines whether the target CPU has the feature according to LLVM. We do + // *not* consider the `-Ctarget-feature`s here, as that will be handled later in + // `cfg_target_feature`. if let Some(feat) = to_llvm_features(sess, feature) { // All the LLVM features this expands to must be enabled. for llvm_feature in feat { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index d984156c674c7..7e4341a823667 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -197,7 +197,10 @@ fn parse_rust_feature_flag<'a>( /// 2nd component of the return value, respectively). /// /// `target_base_has_feature` should check whether the given feature (a Rust feature name!) is -/// enabled in the "base" target machine, i.e., without applying `-Ctarget-feature`. +/// enabled in the "base" target machine, i.e., without applying `-Ctarget-feature`. Note that LLVM +/// may consider features to be implied that we do not and vice-versa. We want `cfg` to be entirely +/// consistent with Rust feature implications, and thus only consult LLVM to expand the target CPU +/// to target features. /// /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled elsewhere. pub fn cfg_target_feature( @@ -211,7 +214,15 @@ pub fn cfg_target_feature( .rust_target_features() .iter() .filter(|(feature, _, _)| target_base_has_feature(feature)) - .map(|(feature, _, _)| Symbol::intern(feature)) + .flat_map(|(base_feature, _, _)| { + // Expand the direct base feature into all transitively-implied features. Note that we + // cannot simply use the `implied` field of the tuple since that only contains + // directly-implied features. + // + // Iteration order is irrelevant because we're collecting into an `UnordSet`. + #[allow(rustc::potential_query_instability)] + sess.target.implied_target_features(base_feature).into_iter().map(|f| Symbol::intern(f)) + }) .collect(); // Add enabled and remove disabled features. diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 1a9832b2fe26a..e1fd184533f6f 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -910,9 +910,9 @@ impl SyntaxExtension { let allow_internal_unsafe = ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some(); - let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export) - .and_then(|macro_export| macro_export.meta_item_list()) - .is_some_and(|l| ast::attr::list_contains_name(&l, sym::local_inner_macros)); + let local_inner_macros = + *find_attr!(attrs, AttributeKind::MacroExport {local_inner_macros: l, ..} => l) + .unwrap_or(&false); let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local); tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1303b3317e05a..266a940b05459 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -327,6 +327,7 @@ declare_features! ( (unstable, m68k_target_feature, "1.85.0", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), (unstable, movrs_target_feature, "1.88.0", Some(137976)), + (unstable, nvptx_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), (unstable, riscv_target_feature, "1.45.0", Some(44839)), diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 80618422b56d6..03eb9900e6571 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -297,6 +297,9 @@ pub enum AttributeKind { /// Represents `#[const_trait]`. ConstTrait(Span), + /// Represents `#[coroutine]`. + Coroutine(Span), + /// Represents `#[coverage(..)]`. Coverage(Span, CoverageAttrKind), @@ -360,6 +363,9 @@ pub enum AttributeKind { /// Represents `#[macro_escape]`. MacroEscape(Span), + /// Represents [`#[macro_export]`](https://doc.rust-lang.org/reference/macros-by-example.html#r-macro.decl.scope.path). + MacroExport { span: Span, local_inner_macros: bool }, + /// Represents `#[rustc_macro_transparency]`. MacroTransparency(Transparency), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 9644a597a3117..d61901397e73d 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -28,6 +28,7 @@ impl AttributeKind { ConstStability { .. } => Yes, ConstStabilityIndirect => No, ConstTrait(..) => No, + Coroutine(..) => No, Coverage(..) => No, DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, @@ -46,6 +47,7 @@ impl AttributeKind { LinkSection { .. } => Yes, // Needed for rustdoc LoopMatch(..) => No, MacroEscape(..) => No, + MacroExport { .. } => Yes, MacroTransparency(..) => Yes, MacroUse { .. } => No, Marker(..) => No, diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs index c55a41eb2b76b..b096c671edabe 100644 --- a/compiler/rustc_hir/src/lints.rs +++ b/compiler/rustc_hir/src/lints.rs @@ -31,7 +31,22 @@ pub struct AttributeLint { #[derive(Clone, Debug, HashStable_Generic)] pub enum AttributeLintKind { - UnusedDuplicate { this: Span, other: Span, warning: bool }, - IllFormedAttributeInput { suggestions: Vec }, - EmptyAttribute { first_span: Span }, + UnusedDuplicate { + this: Span, + other: Span, + warning: bool, + }, + IllFormedAttributeInput { + suggestions: Vec, + }, + EmptyAttribute { + first_span: Span, + }, + + /// Copy of `IllFormedAttributeInput` + /// specifically for the `invalid_macro_export_arguments` lint until that is removed, + /// see + InvalidMacroExportArguments { + suggestions: Vec, + }, } diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index b877f909fc029..d0254eccb39ef 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,11 +1,12 @@ use rustc_errors::MultiSpan; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor, VisitorExt}; -use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind}; +use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind, find_attr}; use rustc_middle::ty::TyCtxt; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; -use rustc_span::{ExpnKind, MacroKind, Span, kw, sym}; +use rustc_span::{ExpnKind, MacroKind, Span, kw}; use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; @@ -241,7 +242,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { ) } ItemKind::Macro(_, _macro, MacroKind::Bang) - if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) => + if find_attr!( + cx.tcx.get_all_attrs(item.owner_id.def_id), + AttributeKind::MacroExport { .. } + ) => { cx.emit_span_lint( NON_LOCAL_DEFINITIONS, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 3b84c6b611016..9e5ceb8977c13 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4188,8 +4188,13 @@ declare_lint! { /// You can't have multiple arguments in a `#[macro_export(..)]`, or mention arguments other than `local_inner_macros`. /// pub INVALID_MACRO_EXPORT_ARGUMENTS, - Warn, + Deny, "\"invalid_parameter\" isn't a valid argument for `#[macro_export]`", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseError, + reference: "issue #57571 ", + report_in_deps: true, + }; } declare_lint! { diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 3a7854a5e118d..7a848536d0e33 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -124,9 +124,19 @@ impl<'tcx> MatchPairTree<'tcx> { let test_case = match pattern.kind { PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None, - PatKind::Or { ref pats } => Some(TestCase::Or { - pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(), - }), + PatKind::Or { ref pats } => { + let pats: Box<[FlatPat<'tcx>]> = + pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(); + if !pats[0].extra_data.bindings.is_empty() { + // Hold a place for any bindings established in (possibly-nested) or-patterns. + // By only holding a place when bindings are present, we skip over any + // or-patterns that will be simplified by `merge_trivial_subcandidates`. In + // other words, we can assume this expands into subcandidates. + // FIXME(@dianne): this needs updating/removing if we always merge or-patterns + extra_data.bindings.push(super::SubpatternBindings::FromOrPattern); + } + Some(TestCase::Or { pats }) + } PatKind::Range(ref range) => { if range.is_full_range(cx.tcx) == Some(true) { @@ -194,12 +204,12 @@ impl<'tcx> MatchPairTree<'tcx> { // Then push this binding, after any bindings in the subpattern. if let Some(source) = place { - extra_data.bindings.push(super::Binding { + extra_data.bindings.push(super::SubpatternBindings::One(super::Binding { span: pattern.span, source, var_id: var, binding_mode: mode, - }); + })); } None diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 2c29b8628417f..4a60ff30dba86 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -5,11 +5,11 @@ //! This also includes code for pattern bindings in `let` statements and //! function parameters. -use std::assert_matches::assert_matches; use std::borrow::Borrow; use std::mem; use std::sync::Arc; +use itertools::{Itertools, Position}; use rustc_abi::VariantIdx; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -561,16 +561,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // return: it isn't bound by move until right before enter the arm. // To handle this we instead unschedule it's drop after each time // we lower the guard. + // As a result, we end up with the drop order of the last sub-branch we lower. To use + // the drop order for the first sub-branch, we lower sub-branches in reverse (#142163). let target_block = self.cfg.start_new_block(); - let mut schedule_drops = ScheduleDrops::Yes; - let arm = arm_match_scope.unzip().0; - // We keep a stack of all of the bindings and type ascriptions - // from the parent candidates that we visit, that also need to - // be bound for each candidate. - for sub_branch in branch.sub_branches { - if let Some(arm) = arm { - self.clear_top_scope(arm.scope); - } + for (pos, sub_branch) in branch.sub_branches.into_iter().rev().with_position() { + debug_assert!(pos != Position::Only); + let schedule_drops = + if pos == Position::Last { ScheduleDrops::Yes } else { ScheduleDrops::No }; let binding_end = self.bind_and_guard_matched_candidate( sub_branch, fake_borrow_temps, @@ -579,9 +576,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { schedule_drops, emit_storage_live, ); - if arm.is_none() { - schedule_drops = ScheduleDrops::No; - } self.cfg.goto(binding_end, outer_source_info, target_block); } @@ -996,7 +990,7 @@ struct PatternExtraData<'tcx> { span: Span, /// Bindings that must be established. - bindings: Vec>, + bindings: Vec>, /// Types that must be asserted. ascriptions: Vec>, @@ -1011,6 +1005,15 @@ impl<'tcx> PatternExtraData<'tcx> { } } +#[derive(Debug, Clone)] +enum SubpatternBindings<'tcx> { + /// A single binding. + One(Binding<'tcx>), + /// Holds the place for an or-pattern's bindings. This ensures their drops are scheduled in the + /// order the primary bindings appear. See rust-lang/rust#142163 for more information. + FromOrPattern, +} + /// A pattern in a form suitable for lowering the match tree, with all irrefutable /// patterns simplified away. /// @@ -1226,7 +1229,7 @@ fn traverse_candidate<'tcx, C, T, I>( } } -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] struct Binding<'tcx> { span: Span, source: Place<'tcx>, @@ -1452,12 +1455,7 @@ impl<'tcx> MatchTreeSubBranch<'tcx> { span: candidate.extra_data.span, success_block: candidate.pre_binding_block.unwrap(), otherwise_block: candidate.otherwise_block.unwrap(), - bindings: parent_data - .iter() - .flat_map(|d| &d.bindings) - .chain(&candidate.extra_data.bindings) - .cloned() - .collect(), + bindings: sub_branch_bindings(parent_data, &candidate.extra_data.bindings), ascriptions: parent_data .iter() .flat_map(|d| &d.ascriptions) @@ -1490,6 +1488,68 @@ impl<'tcx> MatchTreeBranch<'tcx> { } } +/// Collects the bindings for a [`MatchTreeSubBranch`], preserving the order they appear in the +/// pattern, as though the or-alternatives chosen in this sub-branch were inlined. +fn sub_branch_bindings<'tcx>( + parents: &[PatternExtraData<'tcx>], + leaf_bindings: &[SubpatternBindings<'tcx>], +) -> Vec> { + // In the common case, all bindings will be in leaves. Allocate to fit the leaf's bindings. + let mut all_bindings = Vec::with_capacity(leaf_bindings.len()); + let mut remainder = parents + .iter() + .map(|parent| parent.bindings.as_slice()) + .chain([leaf_bindings]) + // Skip over unsimplified or-patterns without bindings. + .filter(|bindings| !bindings.is_empty()); + if let Some(candidate_bindings) = remainder.next() { + push_sub_branch_bindings(&mut all_bindings, candidate_bindings, &mut remainder); + } + // Make sure we've included all bindings. For ill-formed patterns like `(x, _ | y)`, we may not + // have collected all bindings yet, since we only check the first alternative when determining + // whether to inline subcandidates' bindings. + // FIXME(@dianne): prevent ill-formed patterns from getting here + while let Some(candidate_bindings) = remainder.next() { + ty::tls::with(|tcx| { + tcx.dcx().delayed_bug("mismatched or-pattern bindings but no error emitted") + }); + // To recover, we collect the rest in an arbitrary order. + push_sub_branch_bindings(&mut all_bindings, candidate_bindings, &mut remainder); + } + all_bindings +} + +/// Helper for [`sub_branch_bindings`]. Collects bindings from `candidate_bindings` into +/// `flattened`. Bindings in or-patterns are collected recursively from `remainder`. +fn push_sub_branch_bindings<'c, 'tcx: 'c>( + flattened: &mut Vec>, + candidate_bindings: &'c [SubpatternBindings<'tcx>], + remainder: &mut impl Iterator]>, +) { + for subpat_bindings in candidate_bindings { + match subpat_bindings { + SubpatternBindings::One(binding) => flattened.push(*binding), + SubpatternBindings::FromOrPattern => { + // Inline bindings from an or-pattern. By construction, this always + // corresponds to a subcandidate and its closest descendants (i.e. those + // from nested or-patterns, but not adjacent or-patterns). To handle + // adjacent or-patterns, e.g. `(x | x, y | y)`, we update the `remainder` to + // point to the first descendant candidate from outside this or-pattern. + if let Some(subcandidate_bindings) = remainder.next() { + push_sub_branch_bindings(flattened, subcandidate_bindings, remainder); + } else { + // For ill-formed patterns like `x | _`, we may not have any subcandidates left + // to inline bindings from. + // FIXME(@dianne): prevent ill-formed patterns from getting here + ty::tls::with(|tcx| { + tcx.dcx().delayed_bug("mismatched or-pattern bindings but no error emitted") + }); + }; + } + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum HasMatchGuard { Yes, @@ -2453,11 +2513,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Bindings for guards require some extra handling to automatically // insert implicit references/dereferences. - self.bind_matched_candidate_for_guard( - block, - schedule_drops, - sub_branch.bindings.iter(), - ); + // This always schedules storage drops, so we may need to unschedule them below. + self.bind_matched_candidate_for_guard(block, sub_branch.bindings.iter()); let guard_frame = GuardFrame { locals: sub_branch .bindings @@ -2489,6 +2546,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) }); + // If this isn't the final sub-branch being lowered, we need to unschedule drops of + // bindings and temporaries created for and by the guard. As a result, the drop order + // for the arm will correspond to the binding order of the final sub-branch lowered. + if matches!(schedule_drops, ScheduleDrops::No) { + self.clear_top_scope(arm.scope); + } + let source_info = self.source_info(guard_span); let guard_end = self.source_info(tcx.sess.source_map().end_point(guard_span)); let guard_frame = self.guard_context.pop().unwrap(); @@ -2538,14 +2602,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let cause = FakeReadCause::ForGuardBinding; self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id)); } - assert_matches!( - schedule_drops, - ScheduleDrops::Yes, - "patterns with guards must schedule drops" - ); + // Only schedule drops for the last sub-branch we lower. self.bind_matched_candidate_for_arm_body( post_guard_block, - ScheduleDrops::Yes, + schedule_drops, by_value_bindings, emit_storage_live, ); @@ -2671,7 +2731,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn bind_matched_candidate_for_guard<'b>( &mut self, block: BasicBlock, - schedule_drops: ScheduleDrops, bindings: impl IntoIterator>, ) where 'tcx: 'b, @@ -2690,12 +2749,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // a reference R: &T pointing to the location matched by // the pattern, and every occurrence of P within a guard // denotes *R. + // Drops must be scheduled to emit `StorageDead` on the guard's failure/break branches. let ref_for_guard = self.storage_live_binding( block, binding.var_id, binding.span, RefWithinGuard, - schedule_drops, + ScheduleDrops::Yes, ); match binding.binding_mode.0 { ByRef::No => { @@ -2705,13 +2765,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.push_assign(block, source_info, ref_for_guard, rvalue); } ByRef::Yes(mutbl) => { - // The arm binding will be by reference, so eagerly create it now. + // The arm binding will be by reference, so eagerly create it now. Drops must + // be scheduled to emit `StorageDead` on the guard's failure/break branches. let value_for_arm = self.storage_live_binding( block, binding.var_id, binding.span, OutsideGuard, - schedule_drops, + ScheduleDrops::Yes, ); let rvalue = diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs index 589e350a03fc3..2c8ad95b6afdb 100644 --- a/compiler/rustc_mir_build/src/builder/matches/util.rs +++ b/compiler/rustc_mir_build/src/builder/matches/util.rs @@ -138,7 +138,9 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { fn visit_candidate(&mut self, candidate: &Candidate<'tcx>) { for binding in &candidate.extra_data.bindings { - self.visit_binding(binding); + if let super::SubpatternBindings::One(binding) = binding { + self.visit_binding(binding); + } } for match_pair in &candidate.match_pairs { self.visit_match_pair(match_pair); @@ -147,7 +149,9 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'tcx>) { for binding in &flat_pat.extra_data.bindings { - self.visit_binding(binding); + if let super::SubpatternBindings::One(binding) = binding { + self.visit_binding(binding); + } } for match_pair in &flat_pat.match_pairs { self.visit_match_pair(match_pair); diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index b4c8b20e50f9c..3ecccb422c463 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -60,9 +60,13 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { let BodyTy::Fn(caller_sig) = self.thir.body_type else { span_bug!( call.span, - "`become` outside of functions should have been disallowed by hit_typeck" + "`become` outside of functions should have been disallowed by hir_typeck" ) }; + // While the `caller_sig` does have its regions erased, it does not have its + // binders anonymized. We call `erase_regions` once again to anonymize any binders + // within the signature, such as in function pointer or `dyn Trait` args. + let caller_sig = self.tcx.erase_regions(caller_sig); let ExprKind::Scope { value, .. } = call.kind else { span_bug!(call.span, "expected scope, found: {call:?}") diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6a28fe2617edf..f9c0f43803bc8 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -399,10 +399,6 @@ passes_invalid_attr_at_crate_level = passes_invalid_attr_at_crate_level_item = the inner attribute doesn't annotate this {$kind} -passes_invalid_macro_export_arguments = invalid `#[macro_export]` argument - -passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments - passes_lang_item_fn = {$name -> [panic_impl] `#[panic_handler]` *[other] `{$name}` lang item diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2663d5fe99c7a..a4aae8d093bd9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -38,9 +38,8 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; use rustc_session::lint; use rustc_session::lint::builtin::{ - CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, - MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, - USELESS_DEPRECATED, + CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES, + MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, USELESS_DEPRECATED, }; use rustc_session::parse::feature_err; use rustc_span::edition::Edition; @@ -291,6 +290,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Dummy | AttributeKind::RustcBuiltinMacro { .. }, ) => { /* do nothing */ } + Attribute::Parsed(AttributeKind::MacroExport { span, .. }) => { + self.check_macro_export(hir_id, *span, target) + } Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => { self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target) } @@ -324,6 +326,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::Coverage(attr_span, _)) => { self.check_coverage(attr_span, span, target) } + &Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => { + self.check_coroutine(attr_span, target) + } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -383,16 +388,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), [sym::path, ..] => self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod), - [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target), [sym::should_panic, ..] => { self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn) } [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } - [sym::coroutine, ..] => { - self.check_coroutine(attr, target); - } [sym::linkage, ..] => self.check_linkage(attr, span, target), [ // ok @@ -2432,32 +2433,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) { + fn check_macro_export(&self, hir_id: HirId, attr_span: Span, target: Target) { if target != Target::MacroDef { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, - attr.span(), + attr_span, errors::MacroExport::Normal, ); - } else if let Some(meta_item_list) = attr.meta_item_list() - && !meta_item_list.is_empty() - { - if meta_item_list.len() > 1 { - self.tcx.emit_node_span_lint( - INVALID_MACRO_EXPORT_ARGUMENTS, - hir_id, - attr.span(), - errors::MacroExport::TooManyItems, - ); - } else if !meta_item_list[0].has_name(sym::local_inner_macros) { - self.tcx.emit_node_span_lint( - INVALID_MACRO_EXPORT_ARGUMENTS, - hir_id, - meta_item_list[0].span(), - errors::MacroExport::InvalidArgument, - ); - } } else { // special case when `#[macro_export]` is applied to a macro 2.0 let (_, macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); @@ -2467,7 +2450,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, - attr.span(), + attr_span, errors::MacroExport::OnDeclMacro, ); } @@ -2651,11 +2634,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_coroutine(&self, attr: &Attribute, target: Target) { + fn check_coroutine(&self, attr_span: Span, target: Target) { match target { Target::Closure => return, _ => { - self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr.span() }); + self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr_span }); } } } @@ -2820,7 +2803,9 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // In the long run, the checks should be harmonized. if let ItemKind::Macro(_, macro_def, _) = item.kind { let def_id = item.owner_id.to_def_id(); - if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { + if macro_def.macro_rules + && !find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::MacroExport { .. }) + { check_non_exported_macro_for_invalid_attrs(self.tcx, item); } } @@ -2950,7 +2935,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { // which were unsuccessfully resolved due to cannot determine // resolution for the attribute macro error. const ATTRS_TO_CHECK: &[Symbol] = &[ - sym::macro_export, sym::rustc_main, sym::derive, sym::test, @@ -2975,6 +2959,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { (*span, sym::path) } else if let Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) = attr { (*span, sym::automatically_derived) + } else if let Attribute::Parsed(AttributeKind::MacroExport { span, .. }) = attr { + (*span, sym::macro_export) } else { continue; }; diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c6ab6b0d60179..ed9973df0e1d2 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -786,12 +786,6 @@ pub(crate) enum MacroExport { #[diag(passes_macro_export_on_decl_macro)] #[note] OnDeclMacro, - - #[diag(passes_invalid_macro_export_arguments)] - InvalidArgument, - - #[diag(passes_invalid_macro_export_arguments_too_many_items)] - TooManyItems, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d54175548e30e..752a335571821 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1512,6 +1512,7 @@ symbols! { not, notable_trait, note, + nvptx_target_feature, object_safe_for_dispatch, of, off, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b2af99228fe6d..297d9ed84c504 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -517,6 +517,71 @@ const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; +const NVPTX_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("sm_20", Unstable(sym::nvptx_target_feature), &[]), + ("sm_21", Unstable(sym::nvptx_target_feature), &["sm_20"]), + ("sm_30", Unstable(sym::nvptx_target_feature), &["sm_21"]), + ("sm_32", Unstable(sym::nvptx_target_feature), &["sm_30"]), + ("sm_35", Unstable(sym::nvptx_target_feature), &["sm_32"]), + ("sm_37", Unstable(sym::nvptx_target_feature), &["sm_35"]), + ("sm_50", Unstable(sym::nvptx_target_feature), &["sm_37"]), + ("sm_52", Unstable(sym::nvptx_target_feature), &["sm_50"]), + ("sm_53", Unstable(sym::nvptx_target_feature), &["sm_52"]), + ("sm_60", Unstable(sym::nvptx_target_feature), &["sm_53"]), + ("sm_61", Unstable(sym::nvptx_target_feature), &["sm_60"]), + ("sm_62", Unstable(sym::nvptx_target_feature), &["sm_61"]), + ("sm_70", Unstable(sym::nvptx_target_feature), &["sm_62"]), + ("sm_72", Unstable(sym::nvptx_target_feature), &["sm_70"]), + ("sm_75", Unstable(sym::nvptx_target_feature), &["sm_72"]), + ("sm_80", Unstable(sym::nvptx_target_feature), &["sm_75"]), + ("sm_86", Unstable(sym::nvptx_target_feature), &["sm_80"]), + ("sm_87", Unstable(sym::nvptx_target_feature), &["sm_86"]), + ("sm_89", Unstable(sym::nvptx_target_feature), &["sm_87"]), + ("sm_90", Unstable(sym::nvptx_target_feature), &["sm_89"]), + ("sm_90a", Unstable(sym::nvptx_target_feature), &["sm_90"]), + // tidy-alphabetical-end + // tidy-alphabetical-start + ("sm_100", Unstable(sym::nvptx_target_feature), &["sm_90"]), + ("sm_100a", Unstable(sym::nvptx_target_feature), &["sm_100"]), + ("sm_101", Unstable(sym::nvptx_target_feature), &["sm_100"]), + ("sm_101a", Unstable(sym::nvptx_target_feature), &["sm_101"]), + ("sm_120", Unstable(sym::nvptx_target_feature), &["sm_101"]), + ("sm_120a", Unstable(sym::nvptx_target_feature), &["sm_120"]), + // tidy-alphabetical-end + // tidy-alphabetical-start + ("ptx32", Unstable(sym::nvptx_target_feature), &[]), + ("ptx40", Unstable(sym::nvptx_target_feature), &["ptx32"]), + ("ptx41", Unstable(sym::nvptx_target_feature), &["ptx40"]), + ("ptx42", Unstable(sym::nvptx_target_feature), &["ptx41"]), + ("ptx43", Unstable(sym::nvptx_target_feature), &["ptx42"]), + ("ptx50", Unstable(sym::nvptx_target_feature), &["ptx43"]), + ("ptx60", Unstable(sym::nvptx_target_feature), &["ptx50"]), + ("ptx61", Unstable(sym::nvptx_target_feature), &["ptx60"]), + ("ptx62", Unstable(sym::nvptx_target_feature), &["ptx61"]), + ("ptx63", Unstable(sym::nvptx_target_feature), &["ptx62"]), + ("ptx64", Unstable(sym::nvptx_target_feature), &["ptx63"]), + ("ptx65", Unstable(sym::nvptx_target_feature), &["ptx64"]), + ("ptx70", Unstable(sym::nvptx_target_feature), &["ptx65"]), + ("ptx71", Unstable(sym::nvptx_target_feature), &["ptx70"]), + ("ptx72", Unstable(sym::nvptx_target_feature), &["ptx71"]), + ("ptx73", Unstable(sym::nvptx_target_feature), &["ptx72"]), + ("ptx74", Unstable(sym::nvptx_target_feature), &["ptx73"]), + ("ptx75", Unstable(sym::nvptx_target_feature), &["ptx74"]), + ("ptx76", Unstable(sym::nvptx_target_feature), &["ptx75"]), + ("ptx77", Unstable(sym::nvptx_target_feature), &["ptx76"]), + ("ptx78", Unstable(sym::nvptx_target_feature), &["ptx77"]), + ("ptx80", Unstable(sym::nvptx_target_feature), &["ptx78"]), + ("ptx81", Unstable(sym::nvptx_target_feature), &["ptx80"]), + ("ptx82", Unstable(sym::nvptx_target_feature), &["ptx81"]), + ("ptx83", Unstable(sym::nvptx_target_feature), &["ptx82"]), + ("ptx84", Unstable(sym::nvptx_target_feature), &["ptx83"]), + ("ptx85", Unstable(sym::nvptx_target_feature), &["ptx84"]), + ("ptx86", Unstable(sym::nvptx_target_feature), &["ptx85"]), + ("ptx87", Unstable(sym::nvptx_target_feature), &["ptx86"]), + // tidy-alphabetical-end +]; + static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("a", Stable, &["zaamo", "zalrsc"]), @@ -782,6 +847,7 @@ pub fn all_rust_features() -> impl Iterator { .chain(HEXAGON_FEATURES.iter()) .chain(POWERPC_FEATURES.iter()) .chain(MIPS_FEATURES.iter()) + .chain(NVPTX_FEATURES.iter()) .chain(RISCV_FEATURES.iter()) .chain(WASM_FEATURES.iter()) .chain(BPF_FEATURES.iter()) @@ -847,6 +913,7 @@ impl Target { "x86" | "x86_64" => X86_FEATURES, "hexagon" => HEXAGON_FEATURES, "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES, + "nvptx64" => NVPTX_FEATURES, "powerpc" | "powerpc64" => POWERPC_FEATURES, "riscv32" | "riscv64" => RISCV_FEATURES, "wasm32" | "wasm64" => WASM_FEATURES, @@ -873,7 +940,7 @@ impl Target { "sparc" | "sparc64" => SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI, "hexagon" => HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI, "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI, - "bpf" | "m68k" => &[], // no vector ABI + "nvptx64" | "bpf" | "m68k" => &[], // no vector ABI "csky" => CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI, // FIXME: for some tier3 targets, we are overly cautious and always give warnings // when passing args in vector registers. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3c33f4b136844..d5bce6ad233e9 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -195,6 +195,7 @@ #![feature(hexagon_target_feature)] #![feature(loongarch_target_feature)] #![feature(mips_target_feature)] +#![feature(nvptx_target_feature)] #![feature(powerpc_target_feature)] #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 26661b20c12d6..7489a8bb6e74b 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -187,6 +187,80 @@ impl ControlFlow { } } + /// Converts the `ControlFlow` into an `Result` which is `Ok` if the + /// `ControlFlow` was `Break` and `Err` if otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_ok)] + /// + /// use std::ops::ControlFlow; + /// + /// struct TreeNode { + /// value: T, + /// left: Option>>, + /// right: Option>>, + /// } + /// + /// impl TreeNode { + /// fn find<'a>(&'a self, mut predicate: impl FnMut(&T) -> bool) -> Result<&'a T, ()> { + /// let mut f = |t: &'a T| -> ControlFlow<&'a T> { + /// if predicate(t) { + /// ControlFlow::Break(t) + /// } else { + /// ControlFlow::Continue(()) + /// } + /// }; + /// + /// self.traverse_inorder(&mut f).break_ok() + /// } + /// + /// fn traverse_inorder<'a, B>( + /// &'a self, + /// f: &mut impl FnMut(&'a T) -> ControlFlow, + /// ) -> ControlFlow { + /// if let Some(left) = &self.left { + /// left.traverse_inorder(f)?; + /// } + /// f(&self.value)?; + /// if let Some(right) = &self.right { + /// right.traverse_inorder(f)?; + /// } + /// ControlFlow::Continue(()) + /// } + /// + /// fn leaf(value: T) -> Option>> { + /// Some(Box::new(Self { + /// value, + /// left: None, + /// right: None, + /// })) + /// } + /// } + /// + /// let node = TreeNode { + /// value: 0, + /// left: TreeNode::leaf(1), + /// right: Some(Box::new(TreeNode { + /// value: -1, + /// left: TreeNode::leaf(5), + /// right: TreeNode::leaf(2), + /// })), + /// }; + /// + /// let res = node.find(|val: &i32| *val > 3); + /// assert_eq!(res, Ok(&5)); + /// ``` + #[inline] + #[unstable(feature = "control_flow_ok", issue = "140266")] + pub fn break_ok(self) -> Result { + match self { + ControlFlow::Continue(c) => Err(c), + ControlFlow::Break(b) => Ok(b), + } + } + /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the break value in case it exists. #[inline] @@ -218,6 +292,79 @@ impl ControlFlow { } } + /// Converts the `ControlFlow` into an `Result` which is `Ok` if the + /// `ControlFlow` was `Continue` and `Err` if otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_ok)] + /// + /// use std::ops::ControlFlow; + /// + /// struct TreeNode { + /// value: T, + /// left: Option>>, + /// right: Option>>, + /// } + /// + /// impl TreeNode { + /// fn validate(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> Result<(), B> { + /// self.traverse_inorder(f).continue_ok() + /// } + /// + /// fn traverse_inorder(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> ControlFlow { + /// if let Some(left) = &self.left { + /// left.traverse_inorder(f)?; + /// } + /// f(&self.value)?; + /// if let Some(right) = &self.right { + /// right.traverse_inorder(f)?; + /// } + /// ControlFlow::Continue(()) + /// } + /// + /// fn leaf(value: T) -> Option>> { + /// Some(Box::new(Self { + /// value, + /// left: None, + /// right: None, + /// })) + /// } + /// } + /// + /// let node = TreeNode { + /// value: 0, + /// left: TreeNode::leaf(1), + /// right: Some(Box::new(TreeNode { + /// value: -1, + /// left: TreeNode::leaf(5), + /// right: TreeNode::leaf(2), + /// })), + /// }; + /// + /// let res = node.validate(&mut |val| { + /// if *val < 0 { + /// return ControlFlow::Break("negative value detected"); + /// } + /// + /// if *val > 4 { + /// return ControlFlow::Break("too big value detected"); + /// } + /// + /// ControlFlow::Continue(()) + /// }); + /// assert_eq!(res, Err("too big value detected")); + /// ``` + #[inline] + #[unstable(feature = "control_flow_ok", issue = "140266")] + pub fn continue_ok(self) -> Result { + match self { + ControlFlow::Continue(c) => Ok(c), + ControlFlow::Break(b) => Err(b), + } + } + /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the continue value in case it exists. #[inline] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 0a9c0c61c9584..a0c594d2d5961 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -22,6 +22,7 @@ #![feature(const_ref_cell)] #![feature(const_result_trait_fn)] #![feature(const_trait_impl)] +#![feature(control_flow_ok)] #![feature(core_float_math)] #![feature(core_intrinsics)] #![feature(core_intrinsics_fallbacks)] diff --git a/library/coretests/tests/ops/control_flow.rs b/library/coretests/tests/ops/control_flow.rs index eacfd63a6c48f..1df6599ac4a5a 100644 --- a/library/coretests/tests/ops/control_flow.rs +++ b/library/coretests/tests/ops/control_flow.rs @@ -16,3 +16,15 @@ fn control_flow_discriminants_match_result() { discriminant_value(&Result::::Ok(3)), ); } + +#[test] +fn control_flow_break_ok() { + assert_eq!(ControlFlow::::Break('b').break_ok(), Ok('b')); + assert_eq!(ControlFlow::::Continue(3).break_ok(), Err(3)); +} + +#[test] +fn control_flow_continue_ok() { + assert_eq!(ControlFlow::::Break('b').continue_ok(), Err('b')); + assert_eq!(ControlFlow::::Continue(3).continue_ok(), Ok(3)); +} diff --git a/library/std/src/sys/args/common.rs b/library/std/src/sys/args/common.rs index e787105a05a73..33f3794ee6339 100644 --- a/library/std/src/sys/args/common.rs +++ b/library/std/src/sys/args/common.rs @@ -12,7 +12,7 @@ impl !Sync for Args {} impl Args { #[inline] - pub(super) fn new(args: Vec) -> Self { + pub fn new(args: Vec) -> Self { Args { iter: args.into_iter() } } } diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index d0cee54adb6a0..c26d34273d7ec 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -181,4 +181,7 @@ the `deprecated_in_future` lint is triggered which is default `allow`, but most of the standard library raises it to a warning with `#![warn(deprecated_in_future)]`. +## unstable_feature_bound +The `#[unstable_feature_bound(foo)]` attribute can be used together with `#[unstable]` attribute to mark an `impl` of stable type and stable trait as unstable. In std/core, an item annotated with `#[unstable_feature_bound(foo)]` can only be used by another item that is also annotated with `#[unstable_feature_bound(foo)]`. Outside of std/core, using an item with `#[unstable_feature_bound(foo)]` requires the feature to be enabled with `#![feature(foo)]` attribute on the crate. Currently, only `impl`s and free functions can be annotated with `#[unstable_feature_bound]`. + [blog]: https://www.ralfj.de/blog/2018/07/19/const.html diff --git a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md index 106ec562bfc79..36598982481bf 100644 --- a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md +++ b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md @@ -10,6 +10,46 @@ platform. [@RDambrosio016](https://github.com/RDambrosio016) [@kjetilkjeka](https://github.com/kjetilkjeka) +## Requirements + +This target is `no_std` and will typically be built with crate-type `cdylib` and `-C linker-flavor=llbc`, which generates PTX. +The necessary components for this workflow are: + +- `rustup toolchain add nightly` +- `rustup component add llvm-tools --toolchain nightly` +- `rustup component add llvm-bitcode-linker --toolchain nightly` + +There are two options for using the core library: + +- `rustup component add rust-src --toolchain nightly` and build using `-Z build-std=core`. +- `rustup target add nvptx64-nvidia-cuda --toolchain nightly` + +### Target and features + +It is generally necessary to specify the target, such as `-C target-cpu=sm_89`, because the default is very old. This implies two target features: `sm_89` and `ptx78` (and all preceding features within `sm_*` and `ptx*`). Rust will default to using the oldest PTX version that supports the target processor (see [this table](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#release-notes-ptx-release-history)), which maximizes driver compatibility. +One can use `-C target-feature=+ptx80` to choose a later PTX version without changing the target (the default in this case, `ptx78`, requires CUDA driver version 11.8, while `ptx80` would require driver version 12.0). +Later PTX versions may allow more efficient code generation. + +Although Rust follows LLVM in representing `ptx*` and `sm_*` as target features, they should be thought of as having crate granularity, set via (either via `-Ctarget-cpu` and optionally `-Ctarget-feature`). +While the compiler accepts `#[target_feature(enable = "ptx80", enable = "sm_89")]`, it is not supported, may not behave as intended, and may become erroneous in the future. + +## Building Rust kernels + +A `no_std` crate containing one or more functions with `extern "ptx-kernel"` can be compiled to PTX using a command like the following. + +```console +$ RUSTFLAGS='-Ctarget-cpu=sm_89' cargo +nightly rustc --target=nvptx64-nvidia-cuda -Zbuild-std=core --crate-type=cdylib -- -Clinker-flavor=llbc -Zunstable-options +``` + +Intrinsics in `core::arch::nvptx` may use `#[cfg(target_feature = "...")]`, thus it's necessary to use `-Zbuild-std=core` with appropriate `RUSTFLAGS`. The following components are needed for this workflow: + +```console +$ rustup component add rust-src --toolchain nightly +$ rustup component add llvm-tools --toolchain nightly +$ rustup component add llvm-bitcode-linker --toolchain nightly +``` + + $DIR/invalid_macro_export_argument.rs:7:1 + | +LL | #[macro_export(hello, world)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +Future breakage diagnostic: +warning: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:14:1 + | +LL | #[macro_export(not_local_inner_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +Future breakage diagnostic: +warning: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:31:1 + | +LL | #[macro_export()] + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +Future breakage diagnostic: +warning: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:38:1 + | +LL | #[macro_export("blah")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + diff --git a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr index 9d44bd162c7b7..fd50b824d0a26 100644 --- a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr +++ b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr @@ -1,26 +1,103 @@ -error: `#[macro_export]` can only take 1 or 0 arguments +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` --> $DIR/invalid_macro_export_argument.rs:7:1 | LL | #[macro_export(hello, world)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 note: the lint level is defined here --> $DIR/invalid_macro_export_argument.rs:4:24 | LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: invalid `#[macro_export]` argument - --> $DIR/invalid_macro_export_argument.rs:13:16 +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:14:1 | LL | #[macro_export(not_local_inner_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:31:1 + | +LL | #[macro_export()] + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 -error: invalid `#[macro_export]` argument - --> $DIR/invalid_macro_export_argument.rs:33:16 +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:38:1 | LL | #[macro_export("blah")] - | ^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: aborting due to 4 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:7:1 + | +LL | #[macro_export(hello, world)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 +note: the lint level is defined here + --> $DIR/invalid_macro_export_argument.rs:4:24 + | +LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:14:1 + | +LL | #[macro_export(not_local_inner_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 +note: the lint level is defined here + --> $DIR/invalid_macro_export_argument.rs:4:24 + | +LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +Future breakage diagnostic: +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:31:1 + | +LL | #[macro_export()] + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 +note: the lint level is defined here + --> $DIR/invalid_macro_export_argument.rs:4:24 + | +LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/invalid_macro_export_argument.rs:38:1 + | +LL | #[macro_export("blah")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 +note: the lint level is defined here + --> $DIR/invalid_macro_export_argument.rs:4:24 + | +LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/attributes/invalid_macro_export_argument.rs b/tests/ui/attributes/invalid_macro_export_argument.rs index c5fe39d062a4e..05a40913434e8 100644 --- a/tests/ui/attributes/invalid_macro_export_argument.rs +++ b/tests/ui/attributes/invalid_macro_export_argument.rs @@ -5,13 +5,15 @@ #![cfg_attr(allow, allow(invalid_macro_export_arguments))] #[macro_export(hello, world)] -//[deny]~^ ERROR `#[macro_export]` can only take 1 or 0 arguments +//[deny]~^ ERROR valid forms for the attribute are +//[deny]~| WARN this was previously accepted macro_rules! a { () => () } #[macro_export(not_local_inner_macros)] -//[deny]~^ ERROR invalid `#[macro_export]` argument +//[deny]~^ ERROR valid forms for the attribute are +//[deny]~| WARN this was previously accepted macro_rules! b { () => () } @@ -20,18 +22,22 @@ macro_rules! b { macro_rules! c { () => () } + #[macro_export(local_inner_macros)] macro_rules! d { () => () } #[macro_export()] +//[deny]~^ ERROR valid forms for the attribute are +//[deny]~| WARN this was previously accepted macro_rules! e { () => () } #[macro_export("blah")] -//[deny]~^ ERROR invalid `#[macro_export]` argument +//[deny]~^ ERROR valid forms for the attribute are +//[deny]~| WARN this was previously accepted macro_rules! f { () => () } diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 0d5bf69d548ce..76e2e931f17b8 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -209,7 +209,7 @@ extern crate wloop; //~^ ERROR can't find crate for `wloop` [E0463] #[macro_export = 18] -//~^ ERROR malformed `macro_export` attribute input +//~^ ERROR valid forms for the attribute are #[allow_internal_unsafe = 1] //~^ ERROR malformed //~| ERROR allow_internal_unsafe side-steps the unsafe_code lint diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 1b51075b4e888..ce5bc52bb2080 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -55,12 +55,6 @@ error: malformed `patchable_function_entry` attribute input LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` -error: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:108:5 - | -LL | #[coroutine = 63] || {} - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[coroutine]` - error: malformed `must_not_suspend` attribute input --> $DIR/malformed-attrs.rs:129:1 | @@ -136,21 +130,6 @@ error: malformed `no_link` attribute input LL | #[no_link()] | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` -error: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:211:1 - | -LL | #[macro_export = 18] - | ^^^^^^^^^^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL - #[macro_export = 18] -LL + #[macro_export(local_inner_macros)] - | -LL - #[macro_export = 18] -LL + #[macro_export] - | - error: malformed `allow_internal_unsafe` attribute input --> $DIR/malformed-attrs.rs:213:1 | @@ -436,6 +415,15 @@ LL | #[proc_macro = 18] | | didn't expect any arguments here | help: must be of the form: `#[proc_macro]` +error[E0565]: malformed `coroutine` attribute input + --> $DIR/malformed-attrs.rs:108:5 + | +LL | #[coroutine = 63] || {} + | ^^^^^^^^^^^^----^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[coroutine]` + error[E0565]: malformed `proc_macro_attribute` attribute input --> $DIR/malformed-attrs.rs:113:1 | @@ -558,6 +546,12 @@ error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and ` LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ +error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` + --> $DIR/malformed-attrs.rs:211:1 + | +LL | #[macro_export = 18] + | ^^^^^^^^^^^^^^^^^^^^ + error[E0565]: malformed `type_const` attribute input --> $DIR/malformed-attrs.rs:140:5 | diff --git a/tests/ui/auto-traits/assoc-ty.current.stderr b/tests/ui/auto-traits/assoc-ty.current.stderr index 77a1c8fb654f1..d793ae6652675 100644 --- a/tests/ui/auto-traits/assoc-ty.current.stderr +++ b/tests/ui/auto-traits/assoc-ty.current.stderr @@ -5,7 +5,7 @@ LL | auto trait Trait { | ----- auto traits cannot have associated items LL | LL | type Output; - | -----^^^^^^- help: remove these associated items + | ^^^^^^ error[E0658]: auto traits are experimental and possibly buggy --> $DIR/assoc-ty.rs:8:1 diff --git a/tests/ui/auto-traits/assoc-ty.next.stderr b/tests/ui/auto-traits/assoc-ty.next.stderr index 4ce00d1747564..a41f7d9927858 100644 --- a/tests/ui/auto-traits/assoc-ty.next.stderr +++ b/tests/ui/auto-traits/assoc-ty.next.stderr @@ -5,7 +5,7 @@ LL | auto trait Trait { | ----- auto traits cannot have associated items LL | LL | type Output; - | -----^^^^^^- help: remove these associated items + | ^^^^^^ error[E0658]: auto traits are experimental and possibly buggy --> $DIR/assoc-ty.rs:8:1 diff --git a/tests/ui/auto-traits/auto-trait-validation.fixed b/tests/ui/auto-traits/auto-trait-validation.fixed index 8a445448c8581..b24dc1cb2c3d3 100644 --- a/tests/ui/auto-traits/auto-trait-validation.fixed +++ b/tests/ui/auto-traits/auto-trait-validation.fixed @@ -11,4 +11,15 @@ auto trait LifetimeBound {} //~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] auto trait MyTrait { } //~^ ERROR auto traits cannot have associated items [E0380] +auto trait AssocTy { } +//~^ ERROR auto traits cannot have associated items [E0380] +auto trait All { + //~^ ERROR auto traits cannot have generic parameters [E0567] + +} +// We can't test both generic params and super-traits because the suggestion span overlaps. +auto trait All2 { + //~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] + +} fn main() {} diff --git a/tests/ui/auto-traits/auto-trait-validation.rs b/tests/ui/auto-traits/auto-trait-validation.rs index b5e7505d86a24..9665e5bc3932f 100644 --- a/tests/ui/auto-traits/auto-trait-validation.rs +++ b/tests/ui/auto-traits/auto-trait-validation.rs @@ -11,4 +11,19 @@ auto trait LifetimeBound : 'static {} //~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] auto trait MyTrait { fn foo() {} } //~^ ERROR auto traits cannot have associated items [E0380] +auto trait AssocTy { type Bar; } +//~^ ERROR auto traits cannot have associated items [E0380] +auto trait All<'a, T> { + //~^ ERROR auto traits cannot have generic parameters [E0567] + type Bar; + //~^ ERROR auto traits cannot have associated items [E0380] + fn foo() {} +} +// We can't test both generic params and super-traits because the suggestion span overlaps. +auto trait All2: Copy + 'static { + //~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] + type Bar; + //~^ ERROR auto traits cannot have associated items [E0380] + fn foo() {} +} fn main() {} diff --git a/tests/ui/auto-traits/auto-trait-validation.stderr b/tests/ui/auto-traits/auto-trait-validation.stderr index a6e5ac54869d2..60757db6d1ed2 100644 --- a/tests/ui/auto-traits/auto-trait-validation.stderr +++ b/tests/ui/auto-traits/auto-trait-validation.stderr @@ -2,23 +2,23 @@ error[E0567]: auto traits cannot have generic parameters --> $DIR/auto-trait-validation.rs:6:19 | LL | auto trait Generic {} - | -------^^^ help: remove the parameters + | -------^^^ | | | auto trait cannot have generic parameters error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:8:17 + --> $DIR/auto-trait-validation.rs:8:20 | LL | auto trait Bound : Copy {} - | -----^^^^^^^ help: remove the super traits or lifetime bounds + | ----- ^^^^ | | | auto traits cannot have super traits or lifetime bounds error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:10:25 + --> $DIR/auto-trait-validation.rs:10:28 | LL | auto trait LifetimeBound : 'static {} - | -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds + | ------------- ^^^^^^^ | | | auto traits cannot have super traits or lifetime bounds @@ -26,12 +26,59 @@ error[E0380]: auto traits cannot have associated items --> $DIR/auto-trait-validation.rs:12:25 | LL | auto trait MyTrait { fn foo() {} } - | ------- ---^^^----- - | | | - | | help: remove these associated items + | ------- ^^^ + | | + | auto traits cannot have associated items + +error[E0380]: auto traits cannot have associated items + --> $DIR/auto-trait-validation.rs:14:27 + | +LL | auto trait AssocTy { type Bar; } + | ------- ^^^ + | | | auto traits cannot have associated items -error: aborting due to 4 previous errors +error[E0567]: auto traits cannot have generic parameters + --> $DIR/auto-trait-validation.rs:16:15 + | +LL | auto trait All<'a, T> { + | ---^^^^^^^ + | | + | auto trait cannot have generic parameters + +error[E0380]: auto traits cannot have associated items + --> $DIR/auto-trait-validation.rs:18:10 + | +LL | auto trait All<'a, T> { + | --- auto traits cannot have associated items +LL | +LL | type Bar; + | ^^^ +LL | +LL | fn foo() {} + | ^^^ + +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/auto-trait-validation.rs:23:18 + | +LL | auto trait All2: Copy + 'static { + | ---- ^^^^ ^^^^^^^ + | | + | auto traits cannot have super traits or lifetime bounds + +error[E0380]: auto traits cannot have associated items + --> $DIR/auto-trait-validation.rs:25:10 + | +LL | auto trait All2: Copy + 'static { + | ---- auto traits cannot have associated items +LL | +LL | type Bar; + | ^^^ +LL | +LL | fn foo() {} + | ^^^ + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0380, E0567, E0568. For more information about an error, try `rustc --explain E0380`. diff --git a/tests/ui/auto-traits/bad-generics-on-dyn.stderr b/tests/ui/auto-traits/bad-generics-on-dyn.stderr index 06c7cbcd76da6..a6977c2037e7f 100644 --- a/tests/ui/auto-traits/bad-generics-on-dyn.stderr +++ b/tests/ui/auto-traits/bad-generics-on-dyn.stderr @@ -2,7 +2,7 @@ error[E0567]: auto traits cannot have generic parameters --> $DIR/bad-generics-on-dyn.rs:3:18 | LL | auto trait Trait1<'a> {} - | ------^^^^ help: remove the parameters + | ------^^^^ | | | auto trait cannot have generic parameters diff --git a/tests/ui/auto-traits/has-arguments.stderr b/tests/ui/auto-traits/has-arguments.stderr index b8a680e6a5cad..5228b6d2d1ac8 100644 --- a/tests/ui/auto-traits/has-arguments.stderr +++ b/tests/ui/auto-traits/has-arguments.stderr @@ -2,7 +2,7 @@ error[E0567]: auto traits cannot have generic parameters --> $DIR/has-arguments.rs:3:18 | LL | auto trait Trait1<'outer> {} - | ------^^^^^^^^ help: remove the parameters + | ------^^^^^^^^ | | | auto trait cannot have generic parameters diff --git a/tests/ui/auto-traits/issue-117789.stderr b/tests/ui/auto-traits/issue-117789.stderr index 99efb21341758..1e047c7d2e07b 100644 --- a/tests/ui/auto-traits/issue-117789.stderr +++ b/tests/ui/auto-traits/issue-117789.stderr @@ -2,7 +2,7 @@ error[E0567]: auto traits cannot have generic parameters --> $DIR/issue-117789.rs:1:17 | LL | auto trait Trait

{} - | -----^^^ help: remove the parameters + | -----^^^ | | | auto trait cannot have generic parameters diff --git a/tests/ui/auto-traits/issue-23080-2.current.stderr b/tests/ui/auto-traits/issue-23080-2.current.stderr index 62c7b37041fea..3af97f57d484a 100644 --- a/tests/ui/auto-traits/issue-23080-2.current.stderr +++ b/tests/ui/auto-traits/issue-23080-2.current.stderr @@ -4,7 +4,7 @@ error[E0380]: auto traits cannot have associated items LL | unsafe auto trait Trait { | ----- auto traits cannot have associated items LL | type Output; - | -----^^^^^^- help: remove these associated items + | ^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/auto-traits/issue-23080-2.next.stderr b/tests/ui/auto-traits/issue-23080-2.next.stderr index 62c7b37041fea..3af97f57d484a 100644 --- a/tests/ui/auto-traits/issue-23080-2.next.stderr +++ b/tests/ui/auto-traits/issue-23080-2.next.stderr @@ -4,7 +4,7 @@ error[E0380]: auto traits cannot have associated items LL | unsafe auto trait Trait { | ----- auto traits cannot have associated items LL | type Output; - | -----^^^^^^- help: remove these associated items + | ^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/auto-traits/issue-23080.stderr b/tests/ui/auto-traits/issue-23080.stderr index 5cea45060c824..02a7551910291 100644 --- a/tests/ui/auto-traits/issue-23080.stderr +++ b/tests/ui/auto-traits/issue-23080.stderr @@ -1,13 +1,10 @@ error[E0380]: auto traits cannot have associated items --> $DIR/issue-23080.rs:5:8 | -LL | unsafe auto trait Trait { - | ----- auto traits cannot have associated items -LL | fn method(&self) { - | _____- ^^^^^^ -LL | | println!("Hello"); -LL | | } - | |_____- help: remove these associated items +LL | unsafe auto trait Trait { + | ----- auto traits cannot have associated items +LL | fn method(&self) { + | ^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/auto-traits/issue-84075.stderr b/tests/ui/auto-traits/issue-84075.stderr index 943d521ce9e27..4edf2ecdf06d3 100644 --- a/tests/ui/auto-traits/issue-84075.stderr +++ b/tests/ui/auto-traits/issue-84075.stderr @@ -2,7 +2,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds --> $DIR/issue-84075.rs:5:18 | LL | auto trait Magic where Self: Copy {} - | ----- ^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | ----- ^^^^^^^^^^^^^^^^ | | | auto traits cannot have super traits or lifetime bounds diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 27e38ce06a435..bc17fefc944da 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -1,8 +1,8 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:17 + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20 | LL | auto trait Magic : Sized where Option : Magic {} - | -----^^^^^^^^ help: remove the super traits or lifetime bounds + | ----- ^^^^^ | | | auto traits cannot have super traits or lifetime bounds @@ -10,7 +10,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:26 | LL | auto trait Magic : Sized where Option : Magic {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | auto traits cannot have super traits or lifetime bounds diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr index 23aae13639c77..bc9791a5799c8 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr @@ -1,8 +1,8 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/typeck-auto-trait-no-supertraits.rs:28:17 + --> $DIR/typeck-auto-trait-no-supertraits.rs:28:19 | LL | auto trait Magic: Copy {} - | -----^^^^^^ help: remove the super traits or lifetime bounds + | ----- ^^^^ | | | auto traits cannot have super traits or lifetime bounds diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index f422919983b75..44fc23b63906e 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -198,6 +198,35 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `power9-altivec` `power9-vector` `prfchw` +`ptx32` +`ptx40` +`ptx41` +`ptx42` +`ptx43` +`ptx50` +`ptx60` +`ptx61` +`ptx62` +`ptx63` +`ptx64` +`ptx65` +`ptx70` +`ptx71` +`ptx72` +`ptx73` +`ptx74` +`ptx75` +`ptx76` +`ptx77` +`ptx78` +`ptx80` +`ptx81` +`ptx82` +`ptx83` +`ptx84` +`ptx85` +`ptx86` +`ptx87` `quadword-atomics` `rand` `ras` @@ -222,6 +251,33 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `simd128` `sm3` `sm4` +`sm_100` +`sm_100a` +`sm_101` +`sm_101a` +`sm_120` +`sm_120a` +`sm_20` +`sm_21` +`sm_30` +`sm_32` +`sm_35` +`sm_37` +`sm_50` +`sm_52` +`sm_53` +`sm_60` +`sm_61` +`sm_62` +`sm_70` +`sm_72` +`sm_75` +`sm_80` +`sm_86` +`sm_87` +`sm_89` +`sm_90` +`sm_90a` `sme` `sme-b16b16` `sme-f16f16` diff --git a/tests/ui/drop/or-pattern-drop-order.rs b/tests/ui/drop/or-pattern-drop-order.rs index fdc28225c3591..cca81673ac3ac 100644 --- a/tests/ui/drop/or-pattern-drop-order.rs +++ b/tests/ui/drop/or-pattern-drop-order.rs @@ -1,6 +1,7 @@ //@ run-pass //! Test drop order for different ways of declaring pattern bindings involving or-patterns. -//! Currently, it's inconsistent between language constructs (#142163). +//! In particular, are ordered based on the order in which the first occurrence of each binding +//! appears (i.e. the "primary" bindings). Regression test for #142163. use std::cell::RefCell; use std::ops::Drop; @@ -43,11 +44,10 @@ fn main() { y = LogDrop(o, 1); }); - // When bindings are declared with `let pat = expr;`, bindings within or-patterns are seen last, - // thus they're dropped first. + // `let pat = expr;` should have the same drop order. assert_drop_order(1..=3, |o| { - // Drops are right-to-left, treating `y` as rightmost: `y`, `z`, `x`. - let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)); + // Drops are right-to-left: `z`, `y`, `x`. + let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)); }); assert_drop_order(1..=2, |o| { // The first or-pattern alternative determines the bindings' drop order: `y`, `x`. @@ -58,30 +58,29 @@ fn main() { let ((true, x, y) | (false, y, x)) = (false, LogDrop(o, 1), LogDrop(o, 2)); }); - // `match` treats or-patterns as last like `let pat = expr;`, but also determines drop order - // using the order of the bindings in the *last* or-pattern alternative. + // `match` should have the same drop order. assert_drop_order(1..=3, |o| { - // Drops are right-to-left, treating `y` as rightmost: `y`, `z`, `x`. - match (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)) { (x, Ok(y) | Err(y), z) => {} } + // Drops are right-to-left: `z`, `y` `x`. + match (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) { (x, Ok(y) | Err(y), z) => {} } }); assert_drop_order(1..=2, |o| { - // The last or-pattern alternative determines the bindings' drop order: `x`, `y`. - match (true, LogDrop(o, 1), LogDrop(o, 2)) { (true, x, y) | (false, y, x) => {} } + // The first or-pattern alternative determines the bindings' drop order: `y`, `x`. + match (true, LogDrop(o, 2), LogDrop(o, 1)) { (true, x, y) | (false, y, x) => {} } }); assert_drop_order(1..=2, |o| { - // That drop order is used regardless of which or-pattern alternative matches: `x`, `y`. - match (false, LogDrop(o, 2), LogDrop(o, 1)) { (true, x, y) | (false, y, x) => {} } + // That drop order is used regardless of which or-pattern alternative matches: `y`, `x`. + match (false, LogDrop(o, 1), LogDrop(o, 2)) { (true, x, y) | (false, y, x) => {} } }); // Function params are visited one-by-one, and the order of bindings within a param's pattern is - // the same as `let pat = expr`; + // the same as `let pat = expr;` assert_drop_order(1..=3, |o| { // Among separate params, the drop order is right-to-left: `z`, `y`, `x`. (|x, (Ok(y) | Err(y)), z| {})(LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)); }); assert_drop_order(1..=3, |o| { - // Within a param's pattern, or-patterns are treated as rightmost: `y`, `z`, `x`. - (|(x, Ok(y) | Err(y), z)| {})((LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2))); + // Within a param's pattern, likewise: `z`, `y`, `x`. + (|(x, Ok(y) | Err(y), z)| {})((LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1))); }); assert_drop_order(1..=2, |o| { // The first or-pattern alternative determines the bindings' drop order: `y`, `x`. @@ -89,12 +88,11 @@ fn main() { }); // `if let` and `let`-`else` see bindings in the same order as `let pat = expr;`. - // Vars in or-patterns are seen last (dropped first), and the first alternative's order is used. assert_drop_order(1..=3, |o| { - if let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)) {} + if let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) {} }); assert_drop_order(1..=3, |o| { - let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 1)), LogDrop(o, 2)) else { + let (x, Ok(y) | Err(y), z) = (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) else { unreachable!(); }; }); @@ -106,4 +104,21 @@ fn main() { unreachable!(); }; }); + + // Test nested and adjacent or-patterns, including or-patterns without bindings under a guard. + assert_drop_order(1..=6, |o| { + // The `LogDrop`s that aren't moved into bindings are dropped last. + match [ + [LogDrop(o, 6), LogDrop(o, 4)], + [LogDrop(o, 3), LogDrop(o, 2)], + [LogDrop(o, 1), LogDrop(o, 5)], + ] { + [ + [_ | _, w | w] | [w | w, _ | _], + [x | x, y | y] | [y | y, x | x], + [z | z, _ | _] | [_ | _, z | z], + ] if true => {} + _ => unreachable!(), + } + }); } diff --git a/tests/ui/dropck/eager-by-ref-binding-for-guards.rs b/tests/ui/dropck/eager-by-ref-binding-for-guards.rs index 3f47583917172..90ff9a747aece 100644 --- a/tests/ui/dropck/eager-by-ref-binding-for-guards.rs +++ b/tests/ui/dropck/eager-by-ref-binding-for-guards.rs @@ -17,15 +17,15 @@ fn main() { (mut long2, ref short2) if true => long2.0 = &short2, _ => unreachable!(), } - // This depends on the binding modes of the final or-pattern alternatives (see #142163): + // This depends on the binding modes of the first or-pattern alternatives: let res: &Result = &Ok(1); match (Struct(&&0), res) { (mut long3, Ok(short3) | &Err(short3)) if true => long3.0 = &short3, - //~^ ERROR `short3` does not live long enough _ => unreachable!(), } match (Struct(&&0), res) { (mut long4, &Err(short4) | Ok(short4)) if true => long4.0 = &short4, + //~^ ERROR `short4` does not live long enough _ => unreachable!(), } } diff --git a/tests/ui/dropck/eager-by-ref-binding-for-guards.stderr b/tests/ui/dropck/eager-by-ref-binding-for-guards.stderr index cb1a04cd4447b..2648ce6f99c34 100644 --- a/tests/ui/dropck/eager-by-ref-binding-for-guards.stderr +++ b/tests/ui/dropck/eager-by-ref-binding-for-guards.stderr @@ -11,15 +11,15 @@ LL | (mut long1, ref short1) => long1.0 = &short1, | = note: values in a scope are dropped in the opposite order they are defined -error[E0597]: `short3` does not live long enough - --> $DIR/eager-by-ref-binding-for-guards.rs:23:69 +error[E0597]: `short4` does not live long enough + --> $DIR/eager-by-ref-binding-for-guards.rs:27:69 | -LL | (mut long3, Ok(short3) | &Err(short3)) if true => long3.0 = &short3, - | ------ ^^^^^^- - | | | | - | | | `short3` dropped here while still borrowed - | | | borrow might be used here, when `long3` is dropped and runs the `Drop` code for type `Struct` - | binding `short3` declared here borrowed value does not live long enough +LL | (mut long4, &Err(short4) | Ok(short4)) if true => long4.0 = &short4, + | ------ ^^^^^^- + | | | | + | | | `short4` dropped here while still borrowed + | | | borrow might be used here, when `long4` is dropped and runs the `Drop` code for type `Struct` + | binding `short4` declared here borrowed value does not live long enough | = note: values in a scope are dropped in the opposite order they are defined diff --git a/tests/ui/explicit-tail-calls/higher-ranked-arg.rs b/tests/ui/explicit-tail-calls/higher-ranked-arg.rs new file mode 100644 index 0000000000000..e60686ab5111d --- /dev/null +++ b/tests/ui/explicit-tail-calls/higher-ranked-arg.rs @@ -0,0 +1,13 @@ +// Regression test for . +//@ check-pass + +#![feature(explicit_tail_calls)] +#![expect(incomplete_features)] + +fn foo(x: fn(&i32)) { + become bar(x); +} + +fn bar(_: fn(&i32)) {} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 4cba54bf67c12..6d3b1e4e27380 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -91,21 +91,6 @@ error[E0518]: attribute should be applied to function or closure LL | #![inline] | ^^^^^^^^^^ not a function or closure -error: `macro_export` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 - | -LL | #![macro_export] - | ^^^^^^^^^^^^^^^^ -... -LL | mod inline { - | ------ the inner attribute doesn't annotate this module - | -help: perhaps you meant to use an outer attribute - | -LL - #![macro_export] -LL + #[macro_export] - | - error: `rustc_main` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1 | @@ -136,6 +121,21 @@ LL - #![repr()] LL + #[repr()] | +error: `macro_export` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 + | +LL | #![macro_export] + | ^^^^^^^^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module + | +help: perhaps you meant to use an outer attribute + | +LL - #![macro_export] +LL + #[macro_export] + | + error: `path` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 | diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index e277f5203c698..817556aa165be 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -104,18 +104,6 @@ note: attribute also specified here LL | #![no_builtins] | ^^^^^^^^^^^^^^^ -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:40:5 - | -LL | #[macro_export] - | ^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:39:5 - | -LL | #[macro_export] - | ^^^^^^^^^^^^^^^ - error: unused attribute --> $DIR/unused-attr-duplicate.rs:37:1 | @@ -128,6 +116,18 @@ note: attribute also specified here LL | #[macro_use] | ^^^^^^^^^^^^ +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:40:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:39:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ + error: unused attribute --> $DIR/unused-attr-duplicate.rs:47:1 | diff --git a/tests/ui/methods/issues/issue-105732.stderr b/tests/ui/methods/issues/issue-105732.stderr index 6244f983550ee..93ce695f27b84 100644 --- a/tests/ui/methods/issues/issue-105732.stderr +++ b/tests/ui/methods/issues/issue-105732.stderr @@ -4,7 +4,7 @@ error[E0380]: auto traits cannot have associated items LL | auto trait Foo { | --- auto traits cannot have associated items LL | fn g(&self); - | ---^-------- help: remove these associated items + | ^ error[E0599]: no method named `g` found for reference `&Self` in the current scope --> $DIR/issue-105732.rs:10:14 diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.rs index 1555da2fd1fc3..dd23acfa23549 100644 --- a/tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.rs +++ b/tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.rs @@ -1,16 +1,15 @@ -//@ known-bug: unknown +//@ run-pass #![allow(unused)] struct A(u32); pub fn main() { - // The or-pattern bindings are lowered after `x`, which triggers the error. + // Bindings are lowered in the order they appear syntactically, so this works. let x @ (A(a) | A(a)) = A(10); - // ERROR: use of moved value assert!(x.0 == 10); assert!(a == 10); - // This works. + // This also works. let (x @ A(a) | x @ A(a)) = A(10); assert!(x.0 == 10); assert!(a == 10); diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.stderr b/tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.stderr deleted file mode 100644 index 7980818635836..0000000000000 --- a/tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0382]: use of moved value - --> $DIR/bind-by-copy-or-pat.rs:8:16 - | -LL | let x @ (A(a) | A(a)) = A(10); - | - ^ ----- move occurs because value has type `A`, which does not implement the `Copy` trait - | | | - | | value used here after move - | value moved here - | -help: borrow this binding in the pattern to avoid moving the value - | -LL | let ref x @ (A(a) | A(a)) = A(10); - | +++ - -error[E0382]: use of moved value - --> $DIR/bind-by-copy-or-pat.rs:8:23 - | -LL | let x @ (A(a) | A(a)) = A(10); - | - ^ ----- move occurs because value has type `A`, which does not implement the `Copy` trait - | | | - | | value used here after move - | value moved here - | -help: borrow this binding in the pattern to avoid moving the value - | -LL | let ref x @ (A(a) | A(a)) = A(10); - | +++ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 9244a98d82fdf..81ed8b3de760f 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -6,6 +6,7 @@ // gate-test-arm_target_feature // gate-test-hexagon_target_feature // gate-test-mips_target_feature +// gate-test-nvptx_target_feature // gate-test-wasm_target_feature // gate-test-adx_target_feature // gate-test-cmpxchg16b_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 32d60ce438227..3e9374be73db8 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `x87` is currently unstable - --> $DIR/gate.rs:29:18 + --> $DIR/gate.rs:30:18 | LL | #[target_feature(enable = "x87")] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/implied-features-nvptx.rs b/tests/ui/target-feature/implied-features-nvptx.rs new file mode 100644 index 0000000000000..1550c99f67a8d --- /dev/null +++ b/tests/ui/target-feature/implied-features-nvptx.rs @@ -0,0 +1,28 @@ +//@ assembly-output: ptx-linker +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_80 -Z unstable-options -Clinker-flavor=llbc +//@ only-nvptx64 +//@ build-pass +#![no_std] +#![allow(dead_code)] + +#[panic_handler] +pub fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +// -Ctarget-cpu=sm_80 directly enables sm_80 and ptx70 +#[cfg(not(all(target_feature = "sm_80", target_feature = "ptx70")))] +compile_error!("direct target features not enabled"); + +// -Ctarget-cpu=sm_80 implies all earlier sm_* and ptx* features. +#[cfg(not(all( + target_feature = "sm_60", + target_feature = "sm_70", + target_feature = "ptx50", + target_feature = "ptx60", +)))] +compile_error!("implied target features not enabled"); + +// -Ctarget-cpu=sm_80 implies all earlier sm_* and ptx* features. +#[cfg(target_feature = "ptx71")] +compile_error!("sm_80 requires only ptx70, but ptx71 enabled"); diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index 3a3b99f6c5b10..45602d676b31f 100644 --- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -1,8 +1,8 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/supertrait-auto-trait.rs:8:17 + --> $DIR/supertrait-auto-trait.rs:8:19 | LL | auto trait Magic: Copy {} - | -----^^^^^^ help: remove the super traits or lifetime bounds + | ----- ^^^^ | | | auto traits cannot have super traits or lifetime bounds