diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 370b15d2871a9..e1fccead4d21a 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -56,6 +56,8 @@ ast_lowering_coroutine_too_many_parameters = ast_lowering_default_field_in_tuple = default fields are not supported in tuple structs .label = default fields are only supported on structs +ast_lowering_delegation_cycle_in_signature_resolution = encountered a cycle during delegation signature resolution +ast_lowering_delegation_unresolved_callee = failed to resolve delegation callee ast_lowering_does_not_support_modifiers = the `{$class_name}` register class does not support template modifiers diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 82bade8829a2f..532a0ce520cd6 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -44,6 +44,7 @@ use hir::{BodyId, HirId}; use rustc_abi::ExternAbi; use rustc_ast::*; use rustc_attr_parsing::{AttributeParser, ShouldEmit}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::ErrorGuaranteed; use rustc_hir::Target; use rustc_hir::attrs::{AttributeKind, InlineAttr}; @@ -55,6 +56,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; use {rustc_ast as ast, rustc_hir as hir}; use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; +use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee}; use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt}; pub(crate) struct DelegationResults<'hir> { @@ -119,10 +121,14 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, delegation: &Delegation, item_id: NodeId, - is_in_trait_impl: bool, ) -> DelegationResults<'hir> { let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span); - let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl); + + let sig_id = self.get_delegation_sig_id( + self.resolver.delegation_sig_resolution_nodes[&self.local_def_id(item_id)], + span, + ); + match sig_id { Ok(sig_id) => { self.add_attributes_if_needed(span, sig_id); @@ -238,24 +244,48 @@ impl<'hir> LoweringContext<'_, 'hir> { fn get_delegation_sig_id( &self, - item_id: NodeId, - path_id: NodeId, + mut node_id: NodeId, span: Span, - is_in_trait_impl: bool, ) -> Result { - let sig_id = if is_in_trait_impl { item_id } else { path_id }; - self.get_resolution_id(sig_id, span) + let mut visited: FxHashSet = Default::default(); + + loop { + visited.insert(node_id); + + let Some(def_id) = self.get_resolution_id(node_id) else { + return Err(self.tcx.dcx().span_delayed_bug( + span, + format!( + "LoweringContext: couldn't resolve node {:?} in delegation item", + node_id + ), + )); + }; + + // If def_id is in local crate and it corresponds to another delegation + // it means that we refer to another delegation as a callee, so in order to obtain + // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it. + if let Some(local_id) = def_id.as_local() + && let Some(next_node_id) = + self.resolver.delegation_sig_resolution_nodes.get(&local_id) + { + node_id = *next_node_id; + if visited.contains(&node_id) { + // We encountered a cycle in the resolution, or delegation callee refers to non-existent + // entity, in this case emit an error. + return Err(match visited.len() { + 1 => self.dcx().emit_err(UnresolvedDelegationCallee { span }), + _ => self.dcx().emit_err(CycleInDelegationSignatureResolution { span }), + }); + } + } else { + return Ok(def_id); + } + } } - fn get_resolution_id(&self, node_id: NodeId, span: Span) -> Result { - let def_id = - self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()); - def_id.ok_or_else(|| { - self.tcx.dcx().span_delayed_bug( - span, - format!("LoweringContext: couldn't resolve node {:?} in delegation item", node_id), - ) - }) + fn get_resolution_id(&self, node_id: NodeId) -> Option { + self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()) } fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> { @@ -271,8 +301,6 @@ impl<'hir> LoweringContext<'_, 'hir> { // Function parameter count, including C variadic `...` if present. fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) { if let Some(local_sig_id) = sig_id.as_local() { - // Map may be filled incorrectly due to recursive delegation. - // Error will be emitted later during HIR ty lowering. match self.resolver.delegation_fn_sigs.get(&local_sig_id) { Some(sig) => (sig.param_count, sig.c_variadic), None => (0, false), @@ -489,8 +517,8 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation.path.segments.iter().rev().skip(1).any(|segment| segment.args.is_some()); let call = if self - .get_resolution_id(delegation.id, span) - .and_then(|def_id| Ok(self.is_method(def_id, span))) + .get_resolution_id(delegation.id) + .map(|def_id| self.is_method(def_id, span)) .unwrap_or_default() && delegation.qself.is_none() && !has_generic_args diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 83f3a976e83f7..35c37fe91d494 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -475,3 +475,17 @@ pub(crate) struct UnionWithDefault { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(ast_lowering_delegation_unresolved_callee)] +pub(crate) struct UnresolvedDelegationCallee { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_lowering_delegation_cycle_in_signature_resolution)] +pub(crate) struct CycleInDelegationSignatureResolution { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a68d63bf1464c..bfce7c25b75db 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -541,7 +541,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Macro(ident, macro_def, macro_kinds) } ItemKind::Delegation(box delegation) => { - let delegation_results = self.lower_delegation(delegation, id, false); + let delegation_results = self.lower_delegation(delegation, id); hir::ItemKind::Fn { sig: delegation_results.sig, ident: delegation_results.ident, @@ -1026,7 +1026,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (*ident, generics, kind, ty.is_some()) } AssocItemKind::Delegation(box delegation) => { - let delegation_results = self.lower_delegation(delegation, i.id, false); + let delegation_results = self.lower_delegation(delegation, i.id); let item_kind = hir::TraitItemKind::Fn( delegation_results.sig, hir::TraitFn::Provided(delegation_results.body_id), @@ -1196,7 +1196,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } AssocItemKind::Delegation(box delegation) => { - let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl); + let delegation_results = self.lower_delegation(delegation, i.id); ( delegation.ident, ( diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 0c0915558089e..00a2d12106e76 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -28,6 +28,33 @@ pub struct CfgSelectBranches { pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, } +impl CfgSelectBranches { + /// Removes the top-most branch for which `predicate` returns `true`, + /// or the wildcard if none of the reachable branches satisfied the predicate. + pub fn pop_first_match(&mut self, predicate: F) -> Option<(TokenStream, Span)> + where + F: Fn(&CfgEntry) -> bool, + { + for (index, (cfg, _, _)) in self.reachable.iter().enumerate() { + if predicate(cfg) { + let matched = self.reachable.remove(index); + return Some((matched.1, matched.2)); + } + } + + self.wildcard.take().map(|(_, tts, span)| (tts, span)) + } + + /// Consume this value and iterate over all the `TokenStream`s that it stores. + pub fn into_iter_tts(self) -> impl Iterator { + let it1 = self.reachable.into_iter().map(|(_, tts, span)| (tts, span)); + let it2 = self.wildcard.into_iter().map(|(_, tts, span)| (tts, span)); + let it3 = self.unreachable.into_iter().map(|(_, tts, span)| (tts, span)); + + it1.chain(it2).chain(it3) + } +} + pub fn parse_cfg_select( p: &mut Parser<'_>, sess: &Session, diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 7910443787b4f..8005dd76b2a3d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -117,11 +117,35 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { } } +pub(crate) struct RustcLintOptDenyFieldAccessParser; + +impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { + const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]); + const TEMPLATE: AttributeTemplate = template!(Word); + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(arg) = args.list().and_then(MetaItemListParser::single) else { + cx.expected_single_argument(cx.attr_span); + return None; + }; + + let MetaItemOrLitParser::Lit(MetaItemLit { kind: LitKind::Str(lint_message, _), .. }) = arg + else { + cx.expected_string_literal(arg.span(), arg.lit()); + return None; + }; + + Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message: *lint_message }) + } +} + pub(crate) struct RustcLintOptTyParser; impl NoArgsAttributeParser for RustcLintOptTyParser { const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy; } @@ -130,7 +154,7 @@ pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { const PATH: &[Symbol] = &[sym::rustc_lint_query_instability]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b4854c430cae0..e5448e7792a88 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -61,9 +61,9 @@ use crate::attributes::prototype::CustomMirParser; use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser}; use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, - RustcLegacyConstGenericsParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser, - RustcMainParser, RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, - RustcObjectLifetimeDefaultParser, RustcScalableVectorParser, + RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, + RustcLintQueryInstabilityParser, RustcMainParser, RustcNeverReturnsNullPointerParser, + RustcNoImplicitAutorefsParser, RustcObjectLifetimeDefaultParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser, }; use crate::attributes::semantics::MayDangleParser; @@ -213,6 +213,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs index dc8077b2a1ffb..f11190b281053 100644 --- a/compiler/rustc_builtin_macros/src/cfg_select.rs +++ b/compiler/rustc_builtin_macros/src/cfg_select.rs @@ -1,22 +1,65 @@ use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{Expr, ast}; use rustc_attr_parsing as attr; use rustc_attr_parsing::{ CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, parse_cfg_select, }; -use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult}; use rustc_span::{Ident, Span, sym}; +use smallvec::SmallVec; use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable}; -/// Selects the first arm whose predicate evaluates to true. -fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> { - for (cfg, tt, arm_span) in branches.reachable { - if let EvalConfigResult::True = attr::eval_config_entry(&ecx.sess, &cfg) { - return Some((tt, arm_span)); - } +/// This intermediate structure is used to emit parse errors for the branches that are not chosen. +/// The `MacResult` instance below parses all branches, emitting any errors it encounters, but only +/// keeps the parse result for the selected branch. +struct CfgSelectResult<'cx, 'sess> { + ecx: &'cx mut ExtCtxt<'sess>, + site_span: Span, + selected_tts: TokenStream, + selected_span: Span, + other_branches: CfgSelectBranches, +} + +fn tts_to_mac_result<'cx, 'sess>( + ecx: &'cx mut ExtCtxt<'sess>, + site_span: Span, + tts: TokenStream, + span: Span, +) -> Box { + match ExpandResult::from_tts(ecx, tts, site_span, span, Ident::with_dummy_span(sym::cfg_select)) + { + ExpandResult::Ready(x) => x, + _ => unreachable!("from_tts always returns Ready"), } +} + +macro_rules! forward_to_parser_any_macro { + ($method_name:ident, $ret_ty:ty) => { + fn $method_name(self: Box) -> Option<$ret_ty> { + let CfgSelectResult { ecx, site_span, selected_tts, selected_span, .. } = *self; + + for (tts, span) in self.other_branches.into_iter_tts() { + let _ = tts_to_mac_result(ecx, site_span, tts, span).$method_name(); + } + + tts_to_mac_result(ecx, site_span, selected_tts, selected_span).$method_name() + } + }; +} + +impl<'cx, 'sess> MacResult for CfgSelectResult<'cx, 'sess> { + forward_to_parser_any_macro!(make_expr, Box); + forward_to_parser_any_macro!(make_stmts, SmallVec<[ast::Stmt; 1]>); + forward_to_parser_any_macro!(make_items, SmallVec<[Box; 1]>); + + forward_to_parser_any_macro!(make_impl_items, SmallVec<[Box; 1]>); + forward_to_parser_any_macro!(make_trait_impl_items, SmallVec<[Box; 1]>); + forward_to_parser_any_macro!(make_trait_items, SmallVec<[Box; 1]>); + forward_to_parser_any_macro!(make_foreign_items, SmallVec<[Box; 1]>); - branches.wildcard.map(|(_, tt, span)| (tt, span)) + forward_to_parser_any_macro!(make_ty, Box); + forward_to_parser_any_macro!(make_pat, Box); } pub(super) fn expand_cfg_select<'cx>( @@ -31,7 +74,7 @@ pub(super) fn expand_cfg_select<'cx>( Some(ecx.ecfg.features), ecx.current_expansion.lint_node_id, ) { - Ok(branches) => { + Ok(mut branches) => { if let Some((underscore, _, _)) = branches.wildcard { // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. for (predicate, _, _) in &branches.unreachable { @@ -44,14 +87,17 @@ pub(super) fn expand_cfg_select<'cx>( } } - if let Some((tts, arm_span)) = select_arm(ecx, branches) { - return ExpandResult::from_tts( + if let Some((selected_tts, selected_span)) = branches.pop_first_match(|cfg| { + matches!(attr::eval_config_entry(&ecx.sess, cfg), EvalConfigResult::True) + }) { + let mac = CfgSelectResult { ecx, - tts, - sp, - arm_span, - Ident::with_dummy_span(sym::cfg_select), - ); + selected_tts, + selected_span, + other_branches: branches, + site_span: sp, + }; + return ExpandResult::Ready(Box::new(mac)); } else { // Emit a compiler error when none of the predicates matched. let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp }); diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 0930b924d1773..07d9af4a9b54a 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -28,7 +28,7 @@ jobs: - name: Avoid installing rustc-dev run: | - sed -i 's/components.*/components = ["rustfmt"]/' rust-toolchain + sed -i 's/components.*/components = ["rustfmt"]/' rust-toolchain.toml rustfmt -v - name: Rustfmt @@ -88,7 +88,7 @@ jobs: uses: actions/cache@v4 with: path: build/cg_clif - key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }} - name: Set MinGW as the default toolchain if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' @@ -158,7 +158,7 @@ jobs: uses: actions/cache@v4 with: path: build/cg_clif - key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }} - name: Install hyperfine run: | @@ -207,7 +207,7 @@ jobs: uses: actions/cache@v4 with: path: build/cg_clif - key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-cargo-build-target-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }} - name: Set MinGW as the default toolchain if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml index 9253ab96353c3..b22725fdc9d41 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml @@ -20,7 +20,7 @@ jobs: uses: actions/cache@v4 with: path: build/cg_clif - key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }} + key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain.toml', 'Cargo.lock') }} - name: Test run: ./scripts/test_bootstrap.sh @@ -40,7 +40,7 @@ jobs: uses: actions/cache@v4 with: path: build/cg_clif - key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }} + key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain.toml', 'Cargo.lock') }} - name: Install ripgrep run: | diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index c569ef0ef8297..33db75f0943a9 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -259,6 +259,9 @@ unsafe fn test_simd() { test_mm_cvttps_epi32(); test_mm_cvtsi128_si64(); + #[cfg(not(jit))] + test_mm_cvtps_ph(); + test_mm_extract_epi8(); test_mm_insert_epi16(); test_mm_shuffle_epi8(); @@ -558,6 +561,21 @@ unsafe fn test_mm_cvttps_epi32() { } } +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "f16c")] +#[cfg(not(jit))] +unsafe fn test_mm_cvtps_ph() { + const F16_ONE: i16 = 0x3c00; + const F16_TWO: i16 = 0x4000; + const F16_THREE: i16 = 0x4200; + const F16_FOUR: i16 = 0x4400; + + let a = _mm_set_ps(1.0, 2.0, 3.0, 4.0); + let r = _mm_cvtps_ph::<_MM_FROUND_CUR_DIRECTION>(a); + let e = _mm_set_epi16(0, 0, 0, 0, F16_ONE, F16_TWO, F16_THREE, F16_FOUR); + assert_eq_m128i(r, e); +} + fn test_checked_mul() { let u: Option = u8::from_str_radix("1000", 10).ok(); assert_eq!(u, None); diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain deleted file mode 100644 index 461dbcdb0fb5d..0000000000000 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ /dev/null @@ -1,4 +0,0 @@ -[toolchain] -channel = "nightly-2025-12-08" -components = ["rust-src", "rustc-dev", "llvm-tools"] -profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml new file mode 100644 index 0000000000000..6ce49eb4ccf07 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2025-12-18" +components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] +profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index 1a82193303e23..e26be307328f0 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -22,8 +22,7 @@ case $1 in "prepare") echo "=> Installing new nightly" rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists - sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain - rustup component add rustfmt || true + sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain.toml echo "=> Uninstalling all old nightlies" for nightly in $(rustup toolchain list | grep nightly | grep -v "$TOOLCHAIN" | grep -v nightly-x86_64); do @@ -35,7 +34,7 @@ case $1 in ./y.sh prepare ;; "commit") - git add rust-toolchain + git add rust-toolchain.toml git commit -m "Rustup to $(rustc -V)" ;; "push") diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index b5af585a732e3..b25269d1430ae 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -35,6 +35,7 @@ git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic rm tests/ui/simd/dont-invalid-bitcast-x86_64.rs # unimplemented llvm.x86.sse41.round.ps rm tests/ui/simd/intrinsic/generic-arithmetic-pass.rs # unimplemented simd_funnel_{shl,shr} +rm -r tests/ui/scalable-vectors # scalable vectors are unsupported # exotic linkages rm tests/incremental/hashes/function_interfaces.rs @@ -53,23 +54,29 @@ rm tests/ui/sanitizer/kcfi-c-variadic.rs # same rm tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs # variadics for calling conventions other than C unsupported rm tests/ui/delegation/fn-header.rs +# inline assembly features +rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly +rm tests/ui/asm/global-asm-mono-sym-fn.rs # same +rm tests/ui/asm/naked-asm-mono-sym-fn.rs # same +rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported +rm tests/ui/asm/label-operand.rs # same +rm tests/ui/asm/may_unwind.rs # asm unwinding not supported +rm tests/ui/asm/aarch64/may_unwind.rs # same + # misc unimplemented things rm tests/ui/target-feature/missing-plusminus.rs # error not implemented rm -r tests/run-make/repr128-dwarf # debuginfo test rm -r tests/run-make/split-debuginfo # same rm -r tests/run-make/target-specs # i686 not supported by Cranelift rm -r tests/run-make/mismatching-target-triples # same -rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly -rm tests/ui/asm/global-asm-mono-sym-fn.rs # same -rm tests/ui/asm/naked-asm-mono-sym-fn.rs # same -rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported -rm tests/ui/asm/label-operand.rs # same rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes rm -r tests/run-make/used-proc-macro # used(linker) isn't supported yet rm tests/ui/linking/no-gc-encapsulation-symbols.rs # same rm tests/ui/attributes/fn-align-dyn.rs # per-function alignment not supported rm -r tests/ui/explicit-tail-calls # tail calls rm -r tests/run-make/pointer-auth-link-with-c # pointer auth +rm -r tests/ui/eii # EII not yet implemented +rm -r tests/run-make/forced-unwind-terminate-pof # forced unwinding doesn't take precedence # requires LTO rm -r tests/run-make/cdylib @@ -78,6 +85,7 @@ rm -r tests/run-make/lto-* rm -r tests/run-make/reproducible-build-2 rm -r tests/run-make/no-builtins-lto rm -r tests/run-make/reachable-extern-fn-available-lto +rm -r tests/run-make/no-builtins-linker-plugin-lto # coverage instrumentation rm tests/ui/consts/precise-drop-with-coverage.rs @@ -87,6 +95,7 @@ rm -r tests/ui/instrument-coverage/ # ================== rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations rm tests/ui/codegen/init-large-type.rs # same +rm tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs # same rm tests/ui/statics/const_generics.rs # tests an optimization rm tests/ui/linking/executable-no-mangle-strip.rs # requires --gc-sections to work for statics @@ -143,6 +152,15 @@ rm tests/ui/errors/remap-path-prefix-sysroot.rs # different sysroot source path rm -r tests/run-make/export/extern-opt # something about rustc version mismatches rm -r tests/run-make/export # same rm -r tests/ui/compiletest-self-test/compile-flags-incremental.rs # needs compiletest compiled with panic=unwind +rm tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs # something going wrong with stdlib source remapping +rm tests/ui/consts/miri_unleashed/drop.rs # same +rm tests/ui/error-emitter/multiline-removal-suggestion.rs # same +rm tests/ui/lint/lint-const-item-mutation.rs # same +rm tests/ui/lint/use-redundant/use-redundant-issue-71450.rs # same +rm tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs # same +rm tests/ui/specialization/const_trait_impl.rs # same +rm tests/ui/thir-print/offset_of.rs # same +rm tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs # same # genuine bugs # ============ @@ -157,6 +175,7 @@ rm tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs # same rm tests/ui/async-await/async-drop/async-drop-initial.rs # same (rust-lang/rust#140493) rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables rm -r tests/run-make-cargo/rustdoc-scrape-examples-paths # FIXME(rust-lang/rust#145580) incr comp bug +rm -r tests/incremental/extern_static/issue-49153.rs # assumes reference to undefined static gets optimized away rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # really slow with unoptimized libstd rm tests/ui/process/process-panic-after-fork.rs # same diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 9dba46363936f..3a8ca25a5fc00 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -190,7 +190,7 @@ fn dep_symbol_lookup_fn( diag.emit(); } Linkage::Dynamic => { - dylib_paths.push(src.dylib.as_ref().unwrap().0.clone()); + dylib_paths.push(src.dylib.as_ref().unwrap().clone()); } } } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index 37fbe4be1b0fe..61f48fa977435 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -1313,6 +1313,35 @@ pub(super) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.write_cvalue_transmute(fx, res); } + "llvm.x86.vcvtps2ph.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_ph + intrinsic_args!(fx, args => (a, _imm8); intrinsic); + let a = a.load_scalar(fx); + + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1].node) { + imm8 + } else { + fx.tcx + .dcx() + .span_fatal(span, "Index argument for `_mm_cvtps_ph` is not a constant"); + }; + + let imm8 = imm8.to_u32(); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("vcvtps2ph xmm0, xmm0, {imm8}").into())], + &[CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + _ => { fx.tcx .dcx() diff --git a/compiler/rustc_codegen_cranelift/triagebot.toml b/compiler/rustc_codegen_cranelift/triagebot.toml index 13da0a87def3c..eb0c7b011f605 100644 --- a/compiler/rustc_codegen_cranelift/triagebot.toml +++ b/compiler/rustc_codegen_cranelift/triagebot.toml @@ -2,6 +2,3 @@ # Prevents un-canonicalized issue links (to avoid wrong issues being linked in r-l/rust) [issue-links] - -# Prevents mentions in commits to avoid users being spammed -[no-mentions] diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index fe053935f9e64..f0a1f14168597 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -221,7 +221,7 @@ declare_features! ( (internal, compiler_builtins, "1.13.0", None), /// Allows writing custom MIR (internal, custom_mir, "1.65.0", None), - /// Implementation details of externally implementatble items + /// Implementation details of externally implementable items (internal, eii_internals, "CURRENT_RUSTC_VERSION", None), /// Outputs useful `assert!` messages (unstable, generic_assert, "1.63.0", None), @@ -503,7 +503,7 @@ declare_features! ( (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), /// Allows using `#[export_stable]` which indicates that an item is exportable. (incomplete, export_stable, "1.88.0", Some(139939)), - /// Externally implementatble items + /// Externally implementable items (unstable, extern_item_impls, "CURRENT_RUSTC_VERSION", Some(125418)), /// Allows defining `extern type`s. (unstable, extern_types, "1.23.0", Some(43467)), diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 5e650fbb9bd0b..5991fb5ab24e6 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -931,6 +931,9 @@ pub enum AttributeKind { /// Represents `#[rustc_legacy_const_generics]` RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, attr_span: Span }, + /// Represents `#[rustc_lint_opt_deny_field_access]` + RustcLintOptDenyFieldAccess { lint_message: Symbol }, + /// Represents `#[rustc_lint_opt_ty]` RustcLintOptTy, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index f99069e416bd2..64aa9c2a45bc3 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -94,6 +94,7 @@ impl AttributeKind { RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcLegacyConstGenerics { .. } => Yes, + RustcLintOptDenyFieldAccess { .. } => Yes, RustcLintOptTy => Yes, RustcLintQueryInstability => Yes, RustcMain => No, diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 125fc21a5cc1c..4ab13140bf9c9 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -401,12 +401,6 @@ fn check_constraints<'tcx>( })); }; - if let Some(local_sig_id) = sig_id.as_local() - && tcx.hir_opt_delegation_sig_id(local_sig_id).is_some() - { - emit("recursive delegation is not supported yet"); - } - if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic { // See issue #127443 for explanation. emit("delegation to C-variadic functions is not allowed"); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index c32fed3674fcc..d6f20a4c85a4f 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -668,17 +668,12 @@ impl LateLintPass<'_> for BadOptAccess { for field in adt_def.all_fields() { if field.name == target.name - && let Some(attr) = - cx.tcx.get_attr(field.did, sym::rustc_lint_opt_deny_field_access) - && let Some(items) = attr.meta_item_list() - && let Some(item) = items.first() - && let Some(lit) = item.lit() - && let ast::LitKind::Str(val, _) = lit.kind + && let Some(lint_message) = find_attr!(cx.tcx.get_all_attrs(field.did), AttributeKind::RustcLintOptDenyFieldAccess { lint_message, } => lint_message) { cx.emit_span_lint( BAD_OPT_ACCESS, expr.span, - BadOptAccessDiag { msg: val.as_str() }, + BadOptAccessDiag { msg: lint_message.as_str() }, ); } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2021f175cd848..c967312d8bb8f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -221,6 +221,9 @@ pub struct ResolverAstLowering { /// Information about functions signatures for delegation items expansion pub delegation_fn_sigs: LocalDefIdMap, + // NodeIds (either delegation.id or item_id in case of a trait impl) for signature resolution, + // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914 + pub delegation_sig_resolution_nodes: LocalDefIdMap, } bitflags::bitflags! { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 5a9b759575172..7ebfca91d499d 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -473,9 +473,6 @@ passes_rustc_legacy_const_generics_only = #[rustc_legacy_const_generics] functions must only have const generics .label = non-const generic parameter -passes_rustc_lint_opt_deny_field_access = - `#[rustc_lint_opt_deny_field_access]` should be applied to a field - .label = not a field passes_rustc_pub_transparent = attribute should be applied to `#[repr(transparent)]` types diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d03da2e06cf13..33a3477bcf691 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -258,6 +258,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcNoImplicitAutorefs | AttributeKind::RustcLayoutScalarValidRangeStart(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) + | AttributeKind::RustcLintOptDenyFieldAccess { .. } | AttributeKind::RustcLintOptTy | AttributeKind::RustcLintQueryInstability | AttributeKind::RustcNeverReturnsNullPointer @@ -314,9 +315,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_lint_diagnostics, ..] => { self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } - [sym::rustc_lint_opt_deny_field_access, ..] => { - self.check_rustc_lint_opt_deny_field_access(attr, span, target) - } [sym::rustc_clean, ..] | [sym::rustc_dirty, ..] | [sym::rustc_if_this_changed, ..] @@ -1251,18 +1249,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that the `#[rustc_lint_opt_deny_field_access]` attribute is only applied to a field. - fn check_rustc_lint_opt_deny_field_access(&self, attr: &Attribute, span: Span, target: Target) { - match target { - Target::Field => {} - _ => { - self.tcx - .dcx() - .emit_err(errors::RustcLintOptDenyFieldAccess { attr_span: attr.span(), span }); - } - } - } - /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph /// option is passed to the compiler. fn check_rustc_dirty_clean(&self, attr: &Attribute) { diff --git a/compiler/rustc_passes/src/eii.rs b/compiler/rustc_passes/src/eii.rs index 691576e6a05fc..ab3f9f0d21825 100644 --- a/compiler/rustc_passes/src/eii.rs +++ b/compiler/rustc_passes/src/eii.rs @@ -116,7 +116,8 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, (): } if default_impls.len() > 1 { - panic!("multiple not supported right now"); + let decl_span = tcx.def_ident_span(decl_did).unwrap(); + tcx.dcx().span_delayed_bug(decl_span, "multiple not supported right now"); } let (local_impl, is_default) = diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f2b7d3740cb64..895cefe672baa 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -412,15 +412,6 @@ pub(crate) struct UnusedMultiple { pub name: Symbol, } -#[derive(Diagnostic)] -#[diag(passes_rustc_lint_opt_deny_field_access)] -pub(crate) struct RustcLintOptDenyFieldAccess { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(passes_collapse_debuginfo)] pub(crate) struct CollapseDebuginfo { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5a4fbad6aaf88..d3428a4af348a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2928,7 +2928,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { item.id, LifetimeBinderKind::Function, span, - |this| this.resolve_delegation(delegation), + |this| this.resolve_delegation(delegation, item.id, false), ); } @@ -3257,7 +3257,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { item.id, LifetimeBinderKind::Function, delegation.path.segments.last().unwrap().ident.span, - |this| this.resolve_delegation(delegation), + |this| this.resolve_delegation(delegation, item.id, false), ); } AssocItemKind::Type(box TyAlias { generics, .. }) => self @@ -3550,7 +3550,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |i, s, c| MethodNotMemberOfTrait(i, s, c), ); - this.resolve_delegation(delegation) + this.resolve_delegation(delegation, item.id, trait_id.is_some()); }, ); } @@ -3699,17 +3699,30 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }) } - fn resolve_delegation(&mut self, delegation: &'ast Delegation) { + fn resolve_delegation( + &mut self, + delegation: &'ast Delegation, + item_id: NodeId, + is_in_trait_impl: bool, + ) { self.smart_resolve_path( delegation.id, &delegation.qself, &delegation.path, PathSource::Delegation, ); + if let Some(qself) = &delegation.qself { self.visit_ty(&qself.ty); } + self.visit_path(&delegation.path); + + self.r.delegation_sig_resolution_nodes.insert( + self.r.local_def_id(item_id), + if is_in_trait_impl { item_id } else { delegation.id }, + ); + let Some(body) = &delegation.body else { return }; self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| { let span = delegation.path.segments.last().unwrap().ident.span; @@ -4294,7 +4307,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - #[instrument(level = "debug", skip(self))] fn smart_resolve_path_fragment( &mut self, qself: &Option>, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5d4134fd91c32..097345395ba4a 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1275,6 +1275,7 @@ pub struct Resolver<'ra, 'tcx> { /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap, delegation_fn_sigs: LocalDefIdMap, + delegation_sig_resolution_nodes: LocalDefIdMap, main_def: Option = None, trait_impls: FxIndexMap>, @@ -1693,6 +1694,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { current_crate_outer_attr_insert_span, mods_with_parse_errors: Default::default(), impl_trait_names: Default::default(), + delegation_sig_resolution_nodes: Default::default(), .. }; @@ -1821,6 +1823,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), delegation_fn_sigs: self.delegation_fn_sigs, + delegation_sig_resolution_nodes: self.delegation_sig_resolution_nodes, }; ResolverOutputs { global_ctxt, ast_lowering } } diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs index e13dc5cd44d5c..34e1ea66c99ad 100644 --- a/library/core/src/bstr/mod.rs +++ b/library/core/src/bstr/mod.rs @@ -68,6 +68,30 @@ impl ByteStr { ByteStr::from_bytes(bytes.as_ref()) } + /// Returns the same string as `&ByteStr`. + /// + /// This method is redundant when used directly on `&ByteStr`, but + /// it helps dereferencing other "container" types, + /// for example `Box` or `Arc`. + #[inline] + // #[unstable(feature = "str_as_str", issue = "130366")] + #[unstable(feature = "bstr", issue = "134915")] + pub const fn as_byte_str(&self) -> &ByteStr { + self + } + + /// Returns the same string as `&mut ByteStr`. + /// + /// This method is redundant when used directly on `&mut ByteStr`, but + /// it helps dereferencing other "container" types, + /// for example `Box` or `MutexGuard`. + #[inline] + // #[unstable(feature = "str_as_str", issue = "130366")] + #[unstable(feature = "bstr", issue = "134915")] + pub const fn as_mut_byte_str(&mut self) -> &mut ByteStr { + self + } + #[doc(hidden)] #[unstable(feature = "bstr_internals", issue = "none")] #[inline] diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 9a35ed07b89ac..621277179bb38 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -648,6 +648,17 @@ impl CStr { pub fn display(&self) -> impl fmt::Display { crate::bstr::ByteStr::from_bytes(self.to_bytes()) } + + /// Returns the same string as a string slice `&CStr`. + /// + /// This method is redundant when used directly on `&CStr`, but + /// it helps dereferencing other string-like types to string slices, + /// for example references to `Box` or `Arc`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_c_str(&self) -> &CStr { + self + } } #[stable(feature = "c_string_eq_c_str", since = "1.90.0")] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index dc34d2a21ee96..256252f73e0be 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4908,6 +4908,28 @@ impl [T] { if start <= self.len() && end <= self.len() { Some(start..end) } else { None } } + + /// Returns the same slice `&[T]`. + /// + /// This method is redundant when used directly on `&[T]`, but + /// it helps dereferencing other "container" types to slices, + /// for example `Box<[T]>` or `Arc<[T]>`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_slice(&self) -> &[T] { + self + } + + /// Returns the same slice `&mut [T]`. + /// + /// This method is redundant when used directly on `&mut [T]`, but + /// it helps dereferencing other "container" types to slices, + /// for example `Box<[T]>` or `MutexGuard<[T]>`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_mut_slice(&mut self) -> &mut [T] { + self + } } impl [MaybeUninit] { diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index d390c82021c7c..4e4d377ae2708 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1278,6 +1278,17 @@ impl OsStr { pub fn display(&self) -> Display<'_> { Display { os_str: self } } + + /// Returns the same string as a string slice `&OsStr`. + /// + /// This method is redundant when used directly on `&OsStr`, but + /// it helps dereferencing other string-like types to string slices, + /// for example references to `Box` or `Arc`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_os_str(&self) -> &OsStr { + self + } } #[stable(feature = "box_from_os_str", since = "1.17.0")] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 2a57a1ed59600..e8eda3c5f76bb 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3206,6 +3206,17 @@ impl Path { Display { inner: self.inner.display() } } + /// Returns the same path as `&Path`. + /// + /// This method is redundant when used directly on `&Path`, but + /// it helps dereferencing other `PathBuf`-like types to `Path`s, + /// for example references to `Box` or `Arc`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_path(&self) -> &Path { + self + } + /// Queries the file system to get information about a file, directory, etc. /// /// This function will traverse symbolic links to query information about the diff --git a/library/std_detect/src/detect/os/darwin/aarch64.rs b/library/std_detect/src/detect/os/darwin/aarch64.rs index 8c9fd9647b8a2..a23d65a23d811 100644 --- a/library/std_detect/src/detect/os/darwin/aarch64.rs +++ b/library/std_detect/src/detect/os/darwin/aarch64.rs @@ -76,6 +76,8 @@ pub(crate) fn detect_features() -> cache::Initializer { let sme = _sysctlbyname(c"hw.optional.arm.FEAT_SME"); let sme2 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2"); let sme2p1 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2p1"); + let sme_b16b16 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_B16B16"); + let sme_f16f16 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_F16F16"); let sme_f64f64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_F64F64"); let sme_i16i64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_I16I64"); let ssbs = _sysctlbyname(c"hw.optional.arm.FEAT_SSBS"); @@ -153,6 +155,8 @@ pub(crate) fn detect_features() -> cache::Initializer { enable_feature(Feature::sme, sme); enable_feature(Feature::sme2, sme2); enable_feature(Feature::sme2p1, sme2p1); + enable_feature(Feature::sme_b16b16, sme_b16b16); + enable_feature(Feature::sme_f16f16, sme_f16f16); enable_feature(Feature::sme_f64f64, sme_f64f64); enable_feature(Feature::sme_i16i64, sme_i16i64); enable_feature(Feature::ssbs, ssbs); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index b86582807f722..fa36a6471cae5 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -932,6 +932,7 @@ impl Step for Rustc { // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 // If there is any bug, please comment out the next line. cargo.rustdocflag("--generate-link-to-definition"); + cargo.rustdocflag("--generate-macro-expansion"); compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates); cargo.arg("-Zskip-rustdoc-fingerprint"); diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index 3287e018b4044..d1b51068fce5a 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -7,7 +7,7 @@ //@ [strong] compile-flags: -Z stack-protector=strong //@ [basic] compile-flags: -Z stack-protector=basic //@ [none] compile-flags: -Z stack-protector=none -//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled +//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort -Cdebuginfo=1 #![crate_type = "lib"] #![allow(internal_features)] @@ -39,6 +39,8 @@ pub fn array_char(f: fn(*const char)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: array_u8_1 @@ -55,6 +57,8 @@ pub fn array_u8_1(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: array_u8_small: @@ -72,6 +76,8 @@ pub fn array_u8_small(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: array_u8_large: @@ -88,6 +94,8 @@ pub fn array_u8_large(f: fn(*const u8)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } #[derive(Copy, Clone)] @@ -107,6 +115,8 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: local_var_addr_used_indirectly @@ -134,6 +144,8 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: local_string_addr_taken @@ -143,28 +155,15 @@ pub fn local_string_addr_taken(f: fn(&String)) { f(&x); // Taking the address of the local variable `x` leads to stack smash - // protection with the `strong` heuristic, but not with the `basic` - // heuristic. It does not matter that the reference is not mut. - // - // An interesting note is that a similar function in C++ *would* be - // protected by the `basic` heuristic, because `std::string` has a char - // array internally as a small object optimization: - // ``` - // cat < - // void f(void (*g)(const std::string&)) { - // std::string x; - // g(x); - // } - // EOF - // ``` - // + // protection. It does not matter that the reference is not mut. // all: __security_check_cookie - // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } pub trait SelfByRef { @@ -194,6 +193,8 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } pub struct Gigastruct { @@ -231,6 +232,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: local_large_var_cloned @@ -260,6 +263,8 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } extern "C" { @@ -300,6 +305,8 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: alloca_large_compile_time_constant_arg @@ -312,6 +319,8 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: alloca_dynamic_arg @@ -324,14 +333,14 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // The question then is: in what ways can Rust code generate array-`alloca` // LLVM instructions? This appears to only be generated by // rustc_codegen_ssa::traits::Builder::array_alloca() through -// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT -// this is support for the "unsized locals" unstable feature: -// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). // CHECK-LABEL: unsized_fn_param #[no_mangle] @@ -346,14 +355,11 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // alloca, and is therefore not protected by the `strong` or `basic` // heuristics. - // We should have a __security_check_cookie call in `all` and `strong` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 // all-NOT: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index 9a3dabc74dded..56a6f08da5877 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -7,7 +7,7 @@ //@ [strong] compile-flags: -Z stack-protector=strong //@ [basic] compile-flags: -Z stack-protector=basic //@ [none] compile-flags: -Z stack-protector=none -//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled +//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort #![crate_type = "lib"] #![feature(unsized_fn_params)] @@ -25,6 +25,7 @@ pub fn emptyfn() { // CHECK-LABEL: array_char #[no_mangle] pub fn array_char(f: fn(*const char)) { + // CHECK-DAG: .seh_endprologue let a = ['c'; 1]; let b = ['d'; 3]; let c = ['e'; 15]; @@ -38,11 +39,14 @@ pub fn array_char(f: fn(*const char)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: array_u8_1 #[no_mangle] pub fn array_u8_1(f: fn(*const u8)) { + // CHECK-DAG: .seh_endprologue let a = [0u8; 1]; f(&a as *const _); @@ -54,11 +58,14 @@ pub fn array_u8_1(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: array_u8_small: #[no_mangle] pub fn array_u8_small(f: fn(*const u8)) { + // CHECK-DAG: .seh_endprologue let a = [0u8; 2]; let b = [0u8; 7]; f(&a as *const _); @@ -71,11 +78,14 @@ pub fn array_u8_small(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: array_u8_large: #[no_mangle] pub fn array_u8_large(f: fn(*const u8)) { + // CHECK-DAG: .seh_endprologue let a = [0u8; 9]; f(&a as *const _); @@ -87,6 +97,8 @@ pub fn array_u8_large(f: fn(*const u8)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } #[derive(Copy, Clone)] @@ -95,6 +107,7 @@ pub struct ByteSizedNewtype(u8); // CHECK-LABEL: array_bytesizednewtype_9: #[no_mangle] pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + // CHECK-DAG: .seh_endprologue let a = [ByteSizedNewtype(0); 9]; f(&a as *const _); @@ -106,11 +119,14 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: local_var_addr_used_indirectly #[no_mangle] pub fn local_var_addr_used_indirectly(f: fn(bool)) { + // CHECK-DAG: .seh_endprologue let a = 5; let a_addr = &a as *const _ as usize; f(a_addr & 0x10 == 0); @@ -133,6 +149,8 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: local_string_addr_taken @@ -143,31 +161,11 @@ pub fn local_string_addr_taken(f: fn(&String)) { f(&x); // Taking the address of the local variable `x` leads to stack smash - // protection with the `strong` heuristic, but not with the `basic` - // heuristic. It does not matter that the reference is not mut. - // - // An interesting note is that a similar function in C++ *would* be - // protected by the `basic` heuristic, because `std::string` has a char - // array internally as a small object optimization: - // ``` - // cat < - // void f(void (*g)(const std::string&)) { - // std::string x; - // g(x); - // } - // EOF - // ``` - // - - // We should have a __security_check_cookie call in `all` and `strong` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 - // all-NOT: __security_check_cookie - // strong-NOT: __security_check_cookie + // protection. It does not matter that the reference is not mut. - // basic-NOT: __security_check_cookie + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -187,6 +185,7 @@ impl SelfByRef for i32 { // CHECK-LABEL: local_var_addr_taken_used_locally_only #[no_mangle] pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) { + // CHECK-DAG: .seh_endprologue let x = factory(); let g = x.f(); sink(g); @@ -201,6 +200,8 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } pub struct Gigastruct { @@ -214,6 +215,7 @@ pub struct Gigastruct { // CHECK-LABEL: local_large_var_moved #[no_mangle] pub fn local_large_var_moved(f: fn(Gigastruct)) { + // CHECK-DAG: .seh_endprologue let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; f(x); @@ -238,11 +240,14 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: local_large_var_cloned #[no_mangle] pub fn local_large_var_cloned(f: fn(Gigastruct)) { + // CHECK-DAG: .seh_endprologue f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); // A new instance of `Gigastruct` is passed to `f()`, without any apparent @@ -267,6 +272,8 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } extern "C" { @@ -300,6 +307,7 @@ extern "C" { // CHECK-LABEL: alloca_small_compile_time_constant_arg #[no_mangle] pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + // CHECK-DAG: .seh_endprologue f(unsafe { alloca(8) }); // all: __security_check_cookie @@ -307,11 +315,14 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: alloca_large_compile_time_constant_arg #[no_mangle] pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + // CHECK-DAG: .seh_endprologue f(unsafe { alloca(9) }); // all: __security_check_cookie @@ -319,11 +330,14 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: alloca_dynamic_arg #[no_mangle] pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + // CHECK-DAG: .seh_endprologue f(unsafe { alloca(n) }); // all: __security_check_cookie @@ -331,18 +345,19 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // The question then is: in what ways can Rust code generate array-`alloca` // LLVM instructions? This appears to only be generated by // rustc_codegen_ssa::traits::Builder::array_alloca() through -// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT -// this is support for the "unsized locals" unstable feature: -// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). // CHECK-LABEL: unsized_fn_param #[no_mangle] pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + // CHECK-DAG: .seh_endprologue let n = if l { 1 } else { 2 }; f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from @@ -353,14 +368,11 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // alloca, and is therefore not protected by the `strong` or `basic` // heuristics. - // We should have a __security_check_cookie call in `all` and `strong` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 // all-NOT: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } diff --git a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs index 0218fe0a52f8a..9f182985d1573 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs @@ -173,7 +173,7 @@ //@ [r84] needs-llvm-components: x86 //@ [r85] compile-flags: --target x86_64-unknown-redox //@ [r85] needs-llvm-components: x86 -//@ compile-flags: -Z stack-protector=all +//@ compile-flags: -Z stack-protector=all -Cpanic=abort //@ compile-flags: -C opt-level=2 #![crate_type = "lib"] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/Cargo.toml b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/Cargo.toml new file mode 100644 index 0000000000000..870d333da3a4f --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "consumer" +version = "0.1.0" + +[dependencies] +mylib_v1 = { path = "../mylib_v1", package = "mylib" } +mylib_v2 = { path = "../mylib_v2", package = "mylib" } + +# Avoid interference with root workspace when casually testing +[workspace] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/src/main.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/src/main.rs new file mode 100644 index 0000000000000..80e76ae281171 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/src/main.rs @@ -0,0 +1,7 @@ +fn main() { + let v1 = mylib_v1::my_macro!(); + assert_eq!(v1, "version 1"); + + let v2 = mylib_v2::my_macro!(); + assert_eq!(v2, "version 2"); +} diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/Cargo.toml b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/Cargo.toml new file mode 100644 index 0000000000000..69f80bfc89ed6 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "mylib" +version = "1.0.0" + +# Avoid interference with root workspace when casually testing +[workspace] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/src/lib.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/src/lib.rs new file mode 100644 index 0000000000000..0603b754ea82c --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/src/lib.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! my_macro { + () => { + "version 1" + }; +} diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/Cargo.toml b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/Cargo.toml new file mode 100644 index 0000000000000..f164616393ba1 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "mylib" +version = "2.0.0" + +# Avoid interference with root workspace when casually testing +[workspace] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/src/lib.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/src/lib.rs new file mode 100644 index 0000000000000..352c7c514f832 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/src/lib.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! my_macro { + () => { + "version 2" + }; +} diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/rmake.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/rmake.rs new file mode 100644 index 0000000000000..cce98cebb8044 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/rmake.rs @@ -0,0 +1,13 @@ +//! Regression test for +//! +//! (that particular comment describes the issue well). +//! +//! We test that two library crates with the same name can export macros with +//! the same name without causing interference when both are used in another +//! crate. + +use run_make_support::cargo; + +fn main() { + cargo().current_dir("consumer").arg("run").run(); +} diff --git a/tests/ui/delegation/auxiliary/recursive-delegation-aux.rs b/tests/ui/delegation/auxiliary/recursive-delegation-aux.rs new file mode 100644 index 0000000000000..5df644974f3ef --- /dev/null +++ b/tests/ui/delegation/auxiliary/recursive-delegation-aux.rs @@ -0,0 +1,7 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +fn foo() {} + +reuse foo as bar; +pub reuse bar as goo; diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs index 3e0a5b36ddcf3..6bf3a08ba5b49 100644 --- a/tests/ui/delegation/ice-issue-124347.rs +++ b/tests/ui/delegation/ice-issue-124347.rs @@ -1,12 +1,12 @@ #![feature(fn_delegation)] #![allow(incomplete_features)] -// FIXME(fn_delegation): `recursive delegation` error should be emitted here trait Trait { reuse Trait::foo { &self.0 } + //~^ ERROR failed to resolve delegation callee } reuse foo; -//~^ ERROR cycle detected when computing generics of `foo` +//~^ ERROR failed to resolve delegation callee fn main() {} diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 2955c04420348..40be6be4abfa1 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -1,17 +1,14 @@ -error[E0391]: cycle detected when computing generics of `foo` - --> $DIR/ice-issue-124347.rs:9:7 +error: failed to resolve delegation callee + --> $DIR/ice-issue-124347.rs:5:18 | -LL | reuse foo; - | ^^^ - | - = note: ...which immediately requires computing generics of `foo` again -note: cycle used when checking that `foo` is well-formed +LL | reuse Trait::foo { &self.0 } + | ^^^ + +error: failed to resolve delegation callee --> $DIR/ice-issue-124347.rs:9:7 | LL | reuse foo; | ^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/delegation/recursive-delegation-errors.rs b/tests/ui/delegation/recursive-delegation-errors.rs new file mode 100644 index 0000000000000..194182e20ed02 --- /dev/null +++ b/tests/ui/delegation/recursive-delegation-errors.rs @@ -0,0 +1,54 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + + +mod first_mod { + reuse foo; + //~^ ERROR failed to resolve delegation callee +} + +mod second_mod { + reuse foo as bar; + //~^ ERROR encountered a cycle during delegation signature resolution + reuse bar as foo; + //~^ ERROR encountered a cycle during delegation signature resolution +} + +mod third_mod { + reuse foo as foo1; + //~^ ERROR encountered a cycle during delegation signature resolution + reuse foo1 as foo2; + //~^ ERROR encountered a cycle during delegation signature resolution + reuse foo2 as foo3; + //~^ ERROR encountered a cycle during delegation signature resolution + reuse foo3 as foo4; + //~^ ERROR encountered a cycle during delegation signature resolution + reuse foo4 as foo5; + //~^ ERROR encountered a cycle during delegation signature resolution + reuse foo5 as foo; + //~^ ERROR encountered a cycle during delegation signature resolution +} + +mod fourth_mod { + trait Trait { + reuse Trait::foo as bar; + //~^ ERROR encountered a cycle during delegation signature resolution + reuse Trait::bar as foo; + //~^ ERROR encountered a cycle during delegation signature resolution + } +} + +mod fifth_mod { + reuse super::fifth_mod::{bar as foo, foo as bar}; + //~^ ERROR encountered a cycle during delegation signature resolution + //~| ERROR encountered a cycle during delegation signature resolution + + trait GlobReuse { + reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; + //~^ ERROR encountered a cycle during delegation signature resolution + //~| ERROR encountered a cycle during delegation signature resolution + //~| ERROR encountered a cycle during delegation signature resolution + } +} + +fn main() {} diff --git a/tests/ui/delegation/recursive-delegation-errors.stderr b/tests/ui/delegation/recursive-delegation-errors.stderr new file mode 100644 index 0000000000000..9c4e316745aea --- /dev/null +++ b/tests/ui/delegation/recursive-delegation-errors.stderr @@ -0,0 +1,98 @@ +error: failed to resolve delegation callee + --> $DIR/recursive-delegation-errors.rs:6:11 + | +LL | reuse foo; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:11:11 + | +LL | reuse foo as bar; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:13:11 + | +LL | reuse bar as foo; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:18:11 + | +LL | reuse foo as foo1; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:20:11 + | +LL | reuse foo1 as foo2; + | ^^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:22:11 + | +LL | reuse foo2 as foo3; + | ^^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:24:11 + | +LL | reuse foo3 as foo4; + | ^^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:26:11 + | +LL | reuse foo4 as foo5; + | ^^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:28:11 + | +LL | reuse foo5 as foo; + | ^^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:34:22 + | +LL | reuse Trait::foo as bar; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:36:22 + | +LL | reuse Trait::bar as foo; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:42:30 + | +LL | reuse super::fifth_mod::{bar as foo, foo as bar}; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:42:42 + | +LL | reuse super::fifth_mod::{bar as foo, foo as bar}; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:47:27 + | +LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:47:39 + | +LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; + | ^^^ + +error: encountered a cycle during delegation signature resolution + --> $DIR/recursive-delegation-errors.rs:47:51 + | +LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; + | ^^^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/delegation/recursive-delegation-pass.rs b/tests/ui/delegation/recursive-delegation-pass.rs new file mode 100644 index 0000000000000..93f8fa401b555 --- /dev/null +++ b/tests/ui/delegation/recursive-delegation-pass.rs @@ -0,0 +1,68 @@ +//@ check-pass +//@ edition:2018 +//@ aux-crate:recursive_delegation_aux=recursive-delegation-aux.rs + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod first_mod { + pub mod to_reuse { + pub fn foo(x: usize) -> usize { + x + 1 + } + } + + mod single_reuse { + reuse crate::first_mod::to_reuse::foo; + reuse foo as bar; + reuse foo as bar1; + reuse bar as goo; + reuse goo as koo; + reuse koo as too; + } + + mod glob_reuse { + reuse super::to_reuse::{foo as bar, foo as bar1} { self } + reuse super::glob_reuse::{bar as goo, goo as koo, koo as too} { self } + } +} + +mod second_mod { + trait T { + fn foo(&self); + reuse T::foo as bar; + reuse T::bar as goo; + reuse T::goo as poo; + } + + trait TGlob { + fn xd(&self) -> &Self; + fn foo1(&self); + fn foo2(&self); + fn foo3(&self); + fn foo4(&self); + + reuse TGlob::{foo1 as bar1, foo3 as bar3, bar1 as bar11, bar11 as bar111} { self.xd() } + } +} + +mod third_mod { + reuse crate::first_mod::to_reuse::foo { + reuse foo as bar { + reuse bar as goo { + bar(123) + } + + goo(123) + } + + bar(123) + } +} + +mod fourth_mod { + reuse recursive_delegation_aux::goo as bar; + reuse bar as foo; +} + +fn main() {} diff --git a/tests/ui/delegation/unsupported.current.stderr b/tests/ui/delegation/unsupported.current.stderr index 5c4115630c002..2bb0633621f21 100644 --- a/tests/ui/delegation/unsupported.current.stderr +++ b/tests/ui/delegation/unsupported.current.stderr @@ -36,24 +36,15 @@ LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: recursive delegation is not supported yet - --> $DIR/unsupported.rs:46:22 - | -LL | pub reuse to_reuse2::foo; - | --- callee defined here -... -LL | reuse to_reuse1::foo; - | ^^^ - error[E0283]: type annotations needed - --> $DIR/unsupported.rs:55:18 + --> $DIR/unsupported.rs:54:18 | LL | reuse Trait::foo; | ^^^ cannot infer type | = note: cannot satisfy `_: effects::Trait` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0283, E0391. For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/delegation/unsupported.next.stderr b/tests/ui/delegation/unsupported.next.stderr index a626da9a1442c..1665d1f39d6d0 100644 --- a/tests/ui/delegation/unsupported.next.stderr +++ b/tests/ui/delegation/unsupported.next.stderr @@ -28,24 +28,15 @@ LL | reuse ToReuse::opaque_ret; = note: cycle used when computing implied outlives bounds for `::opaque_ret::{anon_assoc#0}` (hack disabled = false) = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: recursive delegation is not supported yet - --> $DIR/unsupported.rs:46:22 - | -LL | pub reuse to_reuse2::foo; - | --- callee defined here -... -LL | reuse to_reuse1::foo; - | ^^^ - error[E0283]: type annotations needed - --> $DIR/unsupported.rs:55:18 + --> $DIR/unsupported.rs:54:18 | LL | reuse Trait::foo; | ^^^ cannot infer type | = note: cannot satisfy `_: effects::Trait` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0283, E0391. For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs index 5e2bd832a4d84..1681888e34ea6 100644 --- a/tests/ui/delegation/unsupported.rs +++ b/tests/ui/delegation/unsupported.rs @@ -44,7 +44,6 @@ mod recursive { } reuse to_reuse1::foo; - //~^ ERROR recursive delegation is not supported yet } mod effects { diff --git a/tests/ui/eii/default/multiple-default-impls-same-name.rs b/tests/ui/eii/default/multiple-default-impls-same-name.rs new file mode 100644 index 0000000000000..080e0a46b7557 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls-same-name.rs @@ -0,0 +1,19 @@ +#![crate_type = "lib"] +#![feature(extern_item_impls)] +// `eii` expands to, among other things, `macro eii() {}`. +// If we have two eiis named the same thing, we have a duplicate definition +// for that macro. The compiler happily continues compiling on duplicate +// definitions though, to emit as many diagnostics as possible. +// However, in the case of eiis, this can break the assumption that every +// eii has only one default implementation, since the default for both eiis will +// name resolve to the same eii definiton (since the other definition was duplicate) +// This test tests for the previously-ICE that occurred when this assumption +// (of 1 default) was broken which was reported in #149982. + +#[eii(eii1)] +fn a() {} + +#[eii(eii1)] +//~^ ERROR the name `eii1` is defined multiple times +fn a() {} +//~^ ERROR the name `a` is defined multiple times diff --git a/tests/ui/eii/default/multiple-default-impls-same-name.stderr b/tests/ui/eii/default/multiple-default-impls-same-name.stderr new file mode 100644 index 0000000000000..20544fcfeeba5 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls-same-name.stderr @@ -0,0 +1,25 @@ +error[E0428]: the name `a` is defined multiple times + --> $DIR/multiple-default-impls-same-name.rs:18:1 + | +LL | fn a() {} + | ------ previous definition of the value `a` here +... +LL | fn a() {} + | ^^^^^^ `a` redefined here + | + = note: `a` must be defined only once in the value namespace of this module + +error[E0428]: the name `eii1` is defined multiple times + --> $DIR/multiple-default-impls-same-name.rs:16:1 + | +LL | #[eii(eii1)] + | ------------ previous definition of the macro `eii1` here +... +LL | #[eii(eii1)] + | ^^^^^^^^^^^^ `eii1` redefined here + | + = note: `eii1` must be defined only once in the macro namespace of this module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/eii/default/multiple-default-impls.rs b/tests/ui/eii/default/multiple-default-impls.rs new file mode 100644 index 0000000000000..8d2ad0c1e1378 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls.rs @@ -0,0 +1,18 @@ +#![crate_type = "lib"] +#![feature(extern_item_impls)] +// `eii` expands to, among other things, `macro eii() {}`. +// If we have two eiis named the same thing, we have a duplicate definition +// for that macro. The compiler happily continues compiling on duplicate +// definitions though, to emit as many diagnostics as possible. +// However, in the case of eiis, this can break the assumption that every +// eii has only one default implementation, since the default for both eiis will +// name resolve to the same eii definiton (since the other definition was duplicate) +// This test tests for the previously-ICE that occurred when this assumption +// (of 1 default) was broken which was reported in #149982. + +#[eii(eii1)] +fn a() {} + +#[eii(eii1)] +//~^ ERROR the name `eii1` is defined multiple times +fn b() {} diff --git a/tests/ui/eii/default/multiple-default-impls.stderr b/tests/ui/eii/default/multiple-default-impls.stderr new file mode 100644 index 0000000000000..b270b2346cd50 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `eii1` is defined multiple times + --> $DIR/multiple-default-impls.rs:16:1 + | +LL | #[eii(eii1)] + | ------------ previous definition of the macro `eii1` here +... +LL | #[eii(eii1)] + | ^^^^^^^^^^^^ `eii1` redefined here + | + = note: `eii1` must be defined only once in the macro namespace of this module + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 9fc6803070258..2369158ba82a2 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -47,6 +47,89 @@ fn arm_rhs_expr_3() -> i32 { } } +fn expand_to_statements() -> i32 { + cfg_select! { + true => { + let a = 1; + a + 1 + } + false => { + let b = 2; + b + 1 + } + } +} + +type ExpandToType = cfg_select! { + unix => u32, + _ => i32, +}; + +fn expand_to_pattern(x: Option) -> bool { + match x { + (cfg_select! { + unix => Some(n), + _ => None, + }) => true, + _ => false, + } +} + +cfg_select! { + true => { + fn foo() {} + } + _ => { + fn bar() {} + } +} + +struct S; + +impl S { + cfg_select! { + true => { + fn foo() {} + } + _ => { + fn bar() {} + } + } +} + +trait T { + cfg_select! { + true => { + fn a(); + } + _ => { + fn b(); + } + } +} + +impl T for S { + cfg_select! { + true => { + fn a() {} + } + _ => { + fn b() {} + } + } +} + +extern "C" { + cfg_select! { + true => { + fn puts(s: *const i8) -> i32; + } + _ => { + fn printf(fmt: *const i8, ...) -> i32; + } + } +} + cfg_select! { _ => {} true => {} diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 510fc33d6d113..ffd8540425ab0 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,5 +1,5 @@ warning: unreachable predicate - --> $DIR/cfg_select.rs:52:5 + --> $DIR/cfg_select.rs:135:5 | LL | _ => {} | - always matches @@ -7,7 +7,7 @@ LL | true => {} | ^^^^ this predicate is never reached error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:56:1 + --> $DIR/cfg_select.rs:139:1 | LL | / cfg_select! { LL | | @@ -16,55 +16,55 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:61:1 + --> $DIR/cfg_select.rs:144:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` - --> $DIR/cfg_select.rs:65:5 + --> $DIR/cfg_select.rs:148:5 | LL | => {} | ^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/cfg_select.rs:70:5 + --> $DIR/cfg_select.rs:153:5 | LL | () => {} | ^^ expressions are not allowed here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:75:5 + --> $DIR/cfg_select.rs:158:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:80:5 + --> $DIR/cfg_select.rs:163:5 | LL | a::b => {} | ^^^^ expected a valid identifier here error[E0537]: invalid predicate `a` - --> $DIR/cfg_select.rs:85:5 + --> $DIR/cfg_select.rs:168:5 | LL | a() => {} | ^^^ error: expected one of `(`, `::`, `=>`, or `=`, found `+` - --> $DIR/cfg_select.rs:90:7 + --> $DIR/cfg_select.rs:173:7 | LL | a + 1 => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: expected one of `(`, `::`, `=>`, or `=`, found `!` - --> $DIR/cfg_select.rs:96:8 + --> $DIR/cfg_select.rs:179:8 | LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` warning: unexpected `cfg` condition name: `a` - --> $DIR/cfg_select.rs:90:5 + --> $DIR/cfg_select.rs:173:5 | LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` @@ -75,7 +75,7 @@ LL | a + 1 => {} = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `cfg` - --> $DIR/cfg_select.rs:96:5 + --> $DIR/cfg_select.rs:179:5 | LL | cfg!() => {} | ^^^ diff --git a/tests/ui/macros/cfg_select_parse_error.rs b/tests/ui/macros/cfg_select_parse_error.rs new file mode 100644 index 0000000000000..90fcb2309b348 --- /dev/null +++ b/tests/ui/macros/cfg_select_parse_error.rs @@ -0,0 +1,18 @@ +#![feature(cfg_select)] +#![crate_type = "lib"] + +// Check that parse errors in arms that are not selected are still reported. + +fn print() { + println!(cfg_select! { + false => { 1 ++ 2 } + //~^ ERROR Rust has no postfix increment operator + _ => { "not unix" } + }); +} + +cfg_select! { + false => { fn foo() { 1 +++ 2 } } + //~^ ERROR Rust has no postfix increment operator + _ => {} +} diff --git a/tests/ui/macros/cfg_select_parse_error.stderr b/tests/ui/macros/cfg_select_parse_error.stderr new file mode 100644 index 0000000000000..d4c86c3ceade1 --- /dev/null +++ b/tests/ui/macros/cfg_select_parse_error.stderr @@ -0,0 +1,26 @@ +error: Rust has no postfix increment operator + --> $DIR/cfg_select_parse_error.rs:8:22 + | +LL | false => { 1 ++ 2 } + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL - false => { 1 ++ 2 } +LL + false => { { let tmp = 1 ; 1 += 1; tmp } 2 } + | + +error: Rust has no postfix increment operator + --> $DIR/cfg_select_parse_error.rs:15:29 + | +LL | false => { fn foo() { 1 +++ 2 } } + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL - false => { fn foo() { 1 +++ 2 } } +LL + false => { fn foo() { { let tmp = 1 ; 1 += 1; tmp }+ 2 } } + | + +error: aborting due to 2 previous errors +