From 5a887942a5e50f20569be6569ba62d48a0cc6b53 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Apr 2024 00:06:04 +0200 Subject: [PATCH 1/9] x.py test: remove no-op --skip flag --- src/bootstrap/src/core/builder/tests.rs | 2 -- src/bootstrap/src/core/config/flags.rs | 3 --- src/etc/completions/x.py.fish | 2 +- src/etc/completions/x.py.ps1 | 2 +- src/etc/completions/x.py.sh | 10 +++++----- src/etc/completions/x.py.zsh | 2 +- 6 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 0f97764055966..178df633cec68 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -599,7 +599,6 @@ mod dist { pass: None, run: None, only_modified: false, - skip: vec![], extra_checks: None, }; @@ -664,7 +663,6 @@ mod dist { no_fail_fast: false, doc: true, no_doc: false, - skip: vec![], bless: false, force_rerun: false, compare_mode: None, diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 7262b785ee00a..a66f743a1c516 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -339,9 +339,6 @@ pub enum Subcommand { #[arg(long)] /// run all tests regardless of failure no_fail_fast: bool, - #[arg(long, value_name = "SUBSTRING")] - /// skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times - skip: Vec, #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] /// extra arguments to be passed for the test tool being used /// (e.g. libtest, compiletest or rustdoc) diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 9fc95fd09ba9f..c95516494ae73 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -261,7 +261,6 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate - complete -c x.py -n "__fish_seen_subcommand_from doc" -l enable-bolt-settings -d 'Enable BOLT link flags' complete -c x.py -n "__fish_seen_subcommand_from doc" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times' -r -F complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running tests' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r @@ -274,6 +273,7 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l build -d 'build target complete -c x.py -n "__fish_seen_subcommand_from test" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_seen_subcommand_from test" -l target -d 'target targets to build' -r -f complete -c x.py -n "__fish_seen_subcommand_from test" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'build paths to skip' -r -F complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-error-format -r -f complete -c x.py -n "__fish_seen_subcommand_from test" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" complete -c x.py -n "__fish_seen_subcommand_from test" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 6359b7ff086a9..8e505afaf759b 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -333,7 +333,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { break } 'x.py;test' { - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times') [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests') [CompletionResult]::new('--extra-checks', 'extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') @@ -346,6 +345,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index e1436dcde6704..742f61f162212 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -1625,16 +1625,12 @@ _x.py() { return 0 ;; x.py__test) - opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in - --skip) - COMPREPLY=($(compgen -f "${cur}")) - return 0 - ;; --test-args) COMPREPLY=($(compgen -f "${cur}")) return 0 @@ -1683,6 +1679,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index ea7e4ba6758f5..eec610629a140 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -335,7 +335,6 @@ _arguments "${_arguments_options[@]}" \ ;; (test) _arguments "${_arguments_options[@]}" \ -'*--skip=[skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times]:SUBSTRING:_files' \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \ '*--rustc-args=[extra options to pass the compiler when running tests]:ARGS: ' \ '--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS: ' \ @@ -348,6 +347,7 @@ _arguments "${_arguments_options[@]}" \ '--host=[host targets to build]:HOST:( )' \ '--target=[target targets to build]:TARGET:( )' \ '*--exclude=[build paths to exclude]:PATH:_files' \ +'*--skip=[build paths to skip]:PATH:_files' \ '--rustc-error-format=[]:RUSTC_ERROR_FORMAT:( )' \ '--on-fail=[command to run on failure]:CMD:_cmdstring' \ '--stage=[stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)]:N:( )' \ From b4e2d75d3598a4f9e89d918255e84053c68a4583 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 14:12:40 -0400 Subject: [PATCH 2/9] Assert FnDef only constructed with functions (or fn-like ctors) --- compiler/rustc_middle/src/ty/sty.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b5e619f1e2a3c..ba0898e07c295 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -11,7 +11,7 @@ use crate::ty::{ }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use crate::ty::{List, ParamEnv}; -use hir::def::DefKind; +use hir::def::{CtorKind, DefKind}; use rustc_data_structures::captures::Captures; use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg, MultiSpan}; use rustc_hir as hir; @@ -1677,6 +1677,10 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, args: impl IntoIterator>>, ) -> Ty<'tcx> { + debug_assert_matches!( + tcx.def_kind(def_id), + DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) + ); let args = tcx.check_and_mk_args(def_id, args); Ty::new(tcx, FnDef(def_id, args)) } From cc5105d246c77d54cabb4f595d4e87c14358073d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 14:13:25 -0400 Subject: [PATCH 3/9] Don't create an FnDef of a DefKind::Variant, use the ctor def id --- compiler/rustc_hir_analysis/src/collect/type_of.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 722def2563cbd..9d7deebac48e4 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -474,9 +474,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder { tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity() } - VariantData::Tuple(..) => { + VariantData::Tuple(_, _, ctor) => { let args = ty::GenericArgs::identity_for_item(tcx, def_id); - Ty::new_fn_def(tcx, def_id.to_def_id(), args) + Ty::new_fn_def(tcx, ctor.to_def_id(), args) } }, From 9d116e8e188a84d97e1b64f54410fda7ec6f2dc6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 18:31:42 -0400 Subject: [PATCH 4/9] Don't ICE for postfix match after as --- compiler/rustc_parse/src/parser/expr.rs | 1 + .../ui/match/postfix-match/match-after-as.rs | 7 +++++ .../match/postfix-match/match-after-as.stderr | 28 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tests/ui/match/postfix-match/match-after-as.rs create mode 100644 tests/ui/match/postfix-match/match-after-as.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 18fb858c84cf6..012285e4644d6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -860,6 +860,7 @@ impl<'a> Parser<'a> { ExprKind::MethodCall(_) => "a method call", ExprKind::Call(_, _) => "a function call", ExprKind::Await(_, _) => "`.await`", + ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match", ExprKind::Err(_) => return Ok(with_postfix), _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"), } diff --git a/tests/ui/match/postfix-match/match-after-as.rs b/tests/ui/match/postfix-match/match-after-as.rs new file mode 100644 index 0000000000000..7c648bfcf0353 --- /dev/null +++ b/tests/ui/match/postfix-match/match-after-as.rs @@ -0,0 +1,7 @@ +#![feature(postfix_match)] + +fn main() { + 1 as i32.match {}; + //~^ ERROR cast cannot be followed by a postfix match + //~| ERROR non-exhaustive patterns +} diff --git a/tests/ui/match/postfix-match/match-after-as.stderr b/tests/ui/match/postfix-match/match-after-as.stderr new file mode 100644 index 0000000000000..99e42991c52ba --- /dev/null +++ b/tests/ui/match/postfix-match/match-after-as.stderr @@ -0,0 +1,28 @@ +error: cast cannot be followed by a postfix match + --> $DIR/match-after-as.rs:4:5 + | +LL | 1 as i32.match {}; + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (1 as i32).match {}; + | + + + +error[E0004]: non-exhaustive patterns: type `i32` is non-empty + --> $DIR/match-after-as.rs:4:5 + | +LL | 1 as i32.match {}; + | ^^^^^^^^ + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ 1 as i32 { +LL + _ => todo!(), +LL ~ }; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. From bed8b70d674de72e0e66ab022a64c33f0b1df15e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 19:06:28 -0400 Subject: [PATCH 5/9] Fix suggestions for match non-exhaustiveness --- compiler/rustc_middle/src/thir.rs | 3 +- compiler/rustc_mir_build/src/errors.rs | 23 +++----- compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 +- .../src/thir/pattern/check_match.rs | 57 +++++++++++++------ .../match/postfix-match/match-after-as.stderr | 2 +- 5 files changed, 54 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 05f6fbbbfa33b..95e8509c2d3d4 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -12,7 +12,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::{BindingAnnotation, ByRef, RangeEnd}; +use rustc_hir::{BindingAnnotation, ByRef, MatchSource, RangeEnd}; use rustc_index::newtype_index; use rustc_index::IndexVec; use rustc_middle::middle::region; @@ -358,6 +358,7 @@ pub enum ExprKind<'tcx> { scrutinee: ExprId, scrutinee_hir_id: hir::HirId, arms: Box<[ArmId]>, + match_source: MatchSource, }, /// A block. Block { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 848da56f98168..26f10fdd333cb 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -456,8 +456,8 @@ pub enum UnusedUnsafeEnclosing { pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { pub cx: &'m RustcPatCtxt<'p, 'tcx>, - pub expr_span: Span, - pub span: Span, + pub scrut_span: Span, + pub braces_span: Option, pub ty: Ty<'tcx>, } @@ -465,7 +465,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'_, G> { let mut diag = Diag::new(dcx, level, fluent::mir_build_non_exhaustive_patterns_type_not_empty); - diag.span(self.span); + diag.span(self.scrut_span); diag.code(E0004); let peeled_ty = self.ty.peel_refs(); diag.arg("ty", self.ty); @@ -502,26 +502,19 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo } } - let mut suggestion = None; let sm = self.cx.tcx.sess.source_map(); - if self.span.eq_ctxt(self.expr_span) { + if let Some(braces_span) = self.braces_span { // Get the span for the empty match body `{}`. - let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) { + let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.scrut_span) + { (format!("\n{snippet}"), " ") } else { (" ".to_string(), "") }; - suggestion = Some(( - self.span.shrink_to_hi().with_hi(self.expr_span.hi()), - format!(" {{{indentation}{more}_ => todo!(),{indentation}}}",), - )); - } - - if let Some((span, sugg)) = suggestion { diag.span_suggestion_verbose( - span, + braces_span, fluent::mir_build_suggestion, - sugg, + format!(" {{{indentation}{more}_ => todo!(),{indentation}}}"), Applicability::HasPlaceholders, ); } else { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 1e508ffc1e75b..c697e16217bd4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -716,10 +716,11 @@ impl<'tcx> Cx<'tcx> { then: self.mirror_expr(then), else_opt: else_opt.map(|el| self.mirror_expr(el)), }, - hir::ExprKind::Match(discr, arms, _) => ExprKind::Match { + hir::ExprKind::Match(discr, arms, match_source) => ExprKind::Match { scrutinee: self.mirror_expr(discr), scrutinee_hir_id: discr.hir_id, arms: arms.iter().map(|a| self.convert_arm(a)).collect(), + match_source, }, hir::ExprKind::Loop(body, ..) => { let block_ty = self.typeck_results().node_type(body.hir_id); diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 3a688a14dd50e..a3e6c2abc51fa 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -144,16 +144,8 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { }); return; } - ExprKind::Match { scrutinee, scrutinee_hir_id, box ref arms } => { - let source = match ex.span.desugaring_kind() { - Some(DesugaringKind::ForLoop) => hir::MatchSource::ForLoopDesugar, - Some(DesugaringKind::QuestionMark) => { - hir::MatchSource::TryDesugar(scrutinee_hir_id) - } - Some(DesugaringKind::Await) => hir::MatchSource::AwaitDesugar, - _ => hir::MatchSource::Normal, - }; - self.check_match(scrutinee, arms, source, ex.span); + ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => { + self.check_match(scrutinee, arms, match_source, ex.span); } ExprKind::Let { box ref pat, expr } => { self.check_let(pat, Some(expr), ex.span); @@ -505,8 +497,41 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { None, ); } else { + // span after scrutinee, or after `.match`. That is, the braces, arms, + // and any whitespace preceding the braces. + let braces_span = match source { + hir::MatchSource::Normal => scrut + .span + .find_ancestor_in_same_ctxt(expr_span) + .map(|scrut_span| scrut_span.shrink_to_hi().with_hi(expr_span.hi())), + hir::MatchSource::Postfix => { + // This is horrendous, and we should deal with it by just + // stashing the span of the braces somewhere (like in the match source). + scrut.span.find_ancestor_in_same_ctxt(expr_span).and_then(|scrut_span| { + let sm = self.tcx.sess.source_map(); + let brace_span = sm.span_extend_to_next_char(scrut_span, '{', true); + if sm.span_to_snippet(sm.next_point(brace_span)).as_deref() == Ok("{") { + let sp = brace_span.shrink_to_hi().with_hi(expr_span.hi()); + // We also need to extend backwards for whitespace + sm.span_extend_prev_while(sp, |c| c.is_whitespace()).ok() + } else { + None + } + }) + } + hir::MatchSource::ForLoopDesugar + | hir::MatchSource::TryDesugar(_) + | hir::MatchSource::AwaitDesugar + | hir::MatchSource::FormatArgs => None, + }; self.error = Err(report_non_exhaustive_match( - &cx, self.thir, scrut.ty, scrut.span, witnesses, arms, expr_span, + &cx, + self.thir, + scrut.ty, + scrut.span, + witnesses, + arms, + braces_span, )); } } @@ -929,7 +954,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( sp: Span, witnesses: Vec>, arms: &[ArmId], - expr_span: Span, + braces_span: Option, ) -> ErrorGuaranteed { let is_empty_match = arms.is_empty(); let non_empty_enum = match scrut_ty.kind() { @@ -941,8 +966,8 @@ fn report_non_exhaustive_match<'p, 'tcx>( if is_empty_match && !non_empty_enum { return cx.tcx.dcx().emit_err(NonExhaustivePatternsTypeNotEmpty { cx, - expr_span, - span: sp, + scrut_span: sp, + braces_span, ty: scrut_ty, }); } @@ -1028,7 +1053,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( let mut suggestion = None; let sm = cx.tcx.sess.source_map(); match arms { - [] if sp.eq_ctxt(expr_span) => { + [] if let Some(braces_span) = braces_span => { // Get the span for the empty match body `{}`. let (indentation, more) = if let Some(snippet) = sm.indentation_before(sp) { (format!("\n{snippet}"), " ") @@ -1036,7 +1061,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( (" ".to_string(), "") }; suggestion = Some(( - sp.shrink_to_hi().with_hi(expr_span.hi()), + braces_span, format!(" {{{indentation}{more}{suggested_arm},{indentation}}}",), )); } diff --git a/tests/ui/match/postfix-match/match-after-as.stderr b/tests/ui/match/postfix-match/match-after-as.stderr index 99e42991c52ba..68e4762b8d91d 100644 --- a/tests/ui/match/postfix-match/match-after-as.stderr +++ b/tests/ui/match/postfix-match/match-after-as.stderr @@ -18,7 +18,7 @@ LL | 1 as i32.match {}; = note: the matched value is of type `i32` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | -LL ~ 1 as i32 { +LL ~ 1 as i32.match { LL + _ => todo!(), LL ~ }; | From 382459e0478bfefacd0c1c5a0240bd4bab518d53 Mon Sep 17 00:00:00 2001 From: Aaron Loyd Date: Fri, 29 Mar 2024 17:07:38 -0500 Subject: [PATCH 6/9] Add section to sanitizer doc for `-Zexternal-clangrt` After spending a week looking for answers to how to do the very thing this flag lets me do, it felt appropriate to document it where I would've expected it to be. --- .../src/compiler-flags/external-clangrt.md | 6 ++++++ .../unstable-book/src/compiler-flags/sanitizer.md | 15 +++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/external-clangrt.md diff --git a/src/doc/unstable-book/src/compiler-flags/external-clangrt.md b/src/doc/unstable-book/src/compiler-flags/external-clangrt.md new file mode 100644 index 0000000000000..76b78d733e515 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/external-clangrt.md @@ -0,0 +1,6 @@ +# `external-clangrt` + +This option controls whether the compiler links in its own runtime library for +[sanitizers](./sanitizer.md). Passing this flag makes the compiler *not* link +its own library. For more information, see the section in the sanitizers doc on +[working with other languages.](./sanitizer.md#working-with-other-languages) diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index c8fd154a00ec9..72b44e002b4d4 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -45,6 +45,9 @@ To enable a sanitizer compile with `-Zsanitizer=address`, `-Zsanitizer=cfi`, `-Zsanitizer=dataflow`,`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`, `-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or `-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags. +If you're working with other languages that are also instrumented with sanitizers, +you might need the `external-clangrt` flag. See the section on +[working with other languages](#working-with-other-languages). Example: ```shell @@ -853,6 +856,18 @@ functionality][build-std]. [build-std]: ../../cargo/reference/unstable.html#build-std +# Working with other languages + +Sanitizers rely on compiler runtime libraries to function properly. Rust links +in its own compiler runtime which might conflict with runtimes required by +languages such as C++. Since Rust's runtime doesn't always contain the symbols +required by C++ instrumented code, you might need to skip linking it so another +runtime can be linked instead. + +A separate unstable option `-Zexternal-clangrt` can be used to make rustc skip +linking the compiler runtime for the sanitizer. This will require you to link +in an external runtime, such as from clang instead. + # Build scripts and procedural macros Use of sanitizers together with build scripts and procedural macros is From 5075931290ac4939b1645d2a9cde06cce240ba59 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Tue, 2 Apr 2024 22:46:00 +0000 Subject: [PATCH 7/9] rustc_ast: Update `P` docs to reflect mutable status. `P` has implemented `DerefMut` since #54277. While this was lamented at the time [1], rustc now relies on it extensively via the many implementors of MutVisitor [2]. Updates the docs to reflect that `P` is fundamentally mutable, and a few other cleanups to make them nicer to browse. [1]: https://github.com/rust-lang/rust/pull/54277#discussion_r257181754 [2]: https://doc.rust-lang.org/1.77.1/nightly-rustc/rustc_ast/mut_visit/trait.MutVisitor.html#implementors --- compiler/rustc_ast/src/ptr.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs index 0140fb752bf92..e22a523dbc3ef 100644 --- a/compiler/rustc_ast/src/ptr.rs +++ b/compiler/rustc_ast/src/ptr.rs @@ -1,6 +1,6 @@ //! The AST pointer. //! -//! Provides `P`, a frozen owned smart pointer. +//! Provides [`P`][struct@P], an owned smart pointer. //! //! # Motivations and benefits //! @@ -8,18 +8,14 @@ //! passes (e.g., one may be able to bypass the borrow checker with a shared //! `ExprKind::AddrOf` node taking a mutable borrow). //! -//! * **Immutability**: `P` disallows mutating its inner `T`, unlike `Box` -//! (unless it contains an `Unsafe` interior, but that may be denied later). -//! This mainly prevents mistakes, but also enforces a kind of "purity". -//! //! * **Efficiency**: folding can reuse allocation space for `P` and `Vec`, //! the latter even when the input and output types differ (as it would be the //! case with arenas or a GADT AST using type parameters to toggle features). //! -//! * **Maintainability**: `P` provides a fixed interface - `Deref`, -//! `and_then` and `map` - which can remain fully functional even if the -//! implementation changes (using a special thread-local heap, for example). -//! Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated. +//! * **Maintainability**: `P` provides an interface, which can remain fully +//! functional even if the implementation changes (using a special thread-local +//! heap, for example). Moreover, a switch to, e.g., `P<'a, T>` would be easy +//! and mostly automated. use std::fmt::{self, Debug, Display}; use std::ops::{Deref, DerefMut}; @@ -29,6 +25,8 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// An owned smart pointer. +/// +/// See the [module level documentation][crate::ptr] for details. pub struct P { ptr: Box, } From 66dee4a9aa759748319f4e9c81dbb87d7e759ee0 Mon Sep 17 00:00:00 2001 From: Rajveer Date: Wed, 3 Apr 2024 00:49:43 +0530 Subject: [PATCH 8/9] Set `CARGO` instead of `PATH` for Rust Clippy Resolves #123227 --- src/bootstrap/src/core/builder.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index c051b8183287e..0cce5130f6486 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1194,20 +1194,11 @@ impl<'a> Builder<'a> { } pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> Command { - let initial_sysroot_bin = self.initial_rustc.parent().unwrap(); - // Set PATH to include the sysroot bin dir so clippy can find cargo. - // FIXME: once rust-clippy#11944 lands on beta, set `CARGO` directly instead. - let path = t!(env::join_paths( - // The sysroot comes first in PATH to avoid using rustup's cargo. - std::iter::once(PathBuf::from(initial_sysroot_bin)) - .chain(env::split_paths(&t!(env::var("PATH")))) - )); - if run_compiler.stage == 0 { // `ensure(Clippy { stage: 0 })` *builds* clippy with stage0, it doesn't use the beta clippy. let cargo_clippy = self.build.config.download_clippy(); let mut cmd = Command::new(cargo_clippy); - cmd.env("PATH", &path); + cmd.env("CARGO", &self.initial_cargo); return cmd; } @@ -1227,7 +1218,7 @@ impl<'a> Builder<'a> { let mut cmd = Command::new(cargo_clippy); cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - cmd.env("PATH", path); + cmd.env("CARGO", &self.initial_cargo); cmd } From 508530dbc5b6a1234b1616a077efbfd048c3a3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 3 Apr 2024 15:28:47 +0200 Subject: [PATCH 9/9] Output URLs of CI artifacts to GitHub summary --- src/ci/scripts/upload-artifacts.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh index 9755edb6dce58..c9c85ec20b45a 100755 --- a/src/ci/scripts/upload-artifacts.sh +++ b/src/ci/scripts/upload-artifacts.sh @@ -45,3 +45,17 @@ deploy_url="s3://${DEPLOY_BUCKET}/${deploy_dir}/$(ciCommit)" retry aws s3 cp --storage-class INTELLIGENT_TIERING \ --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}" + +access_url="https://ci-artifacts.rust-lang.org/${deploy_dir}/$(ciCommit)" + +# Output URLs to the uploaded artifacts to GitHub summary (if it is available) +# to make them easily accessible. +if [ -n "${GITHUB_STEP_SUMMARY}" ] +then + echo "# CI artifacts" >> "${GITHUB_STEP_SUMMARY}" + + for filename in "${upload_dir}"/*.xz; do + filename=`basename "${filename}"` + echo "- [${filename}](${access_url}/${filename})" >> "${GITHUB_STEP_SUMMARY}" + done +fi