Skip to content

Commit 028b6d1

Browse files
committed
Auto merge of rust-lang#118881 - matthiaskrgr:rollup-0rl3tir, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang#116740 (dont ICE when ConstKind::Expr for is_const_evaluatable) - rust-lang#117914 (On borrow return type, suggest borrowing from arg or owned return type) - rust-lang#117927 (Clarify how to choose a FutureIncompatibilityReason variant.) - rust-lang#118855 (Improve an error involving attribute values.) - rust-lang#118856 (rustdoc-search: clean up parser) - rust-lang#118865 (rustc_codegen_llvm: Enforce `rustc::potential_query_instability` lint) - rust-lang#118866 (llvm-wrapper: adapt for LLVM API change) - rust-lang#118868 (Correctly gate the parsing of match arms without body) - rust-lang#118877 (tests: CGU tests require build-pass, not check-pass (remove FIXME)) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 835ed00 + 010f301 commit 028b6d1

File tree

58 files changed

+939
-168
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+939
-168
lines changed

compiler/rustc_ast/src/ast.rs

+13
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,19 @@ impl Pat {
676676
});
677677
could_be_never_pattern
678678
}
679+
680+
/// Whether this contains a `!` pattern. This in particular means that a feature gate error will
681+
/// be raised if the feature is off. Used to avoid gating the feature twice.
682+
pub fn contains_never_pattern(&self) -> bool {
683+
let mut contains_never_pattern = false;
684+
self.walk(&mut |pat| {
685+
if matches!(pat.kind, PatKind::Never) {
686+
contains_never_pattern = true;
687+
}
688+
true
689+
});
690+
contains_never_pattern
691+
}
679692
}
680693

681694
/// A single field in a struct pattern.

compiler/rustc_ast_lowering/src/expr.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
581581
} else {
582582
// Either `body.is_none()` or `is_never_pattern` here.
583583
if !is_never_pattern {
584-
let suggestion = span.shrink_to_hi();
585-
self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
584+
if self.tcx.features().never_patterns {
585+
// If the feature is off we already emitted the error after parsing.
586+
let suggestion = span.shrink_to_hi();
587+
self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
588+
}
586589
} else if let Some(body) = &arm.body {
587590
self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span });
588591
guard = None;

compiler/rustc_ast_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ ast_passes_item_underscore = `{$kind}` items in this context need a name
174174
ast_passes_keyword_lifetime =
175175
lifetimes cannot use keyword names
176176
177+
ast_passes_match_arm_with_no_body =
178+
`match` arm with no body
179+
.suggestion = add a body after the pattern
180+
177181
ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
178182
.help = consider using the `#[path]` attribute to specify filesystem path
179183

compiler/rustc_ast_passes/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -758,3 +758,12 @@ pub struct AnonStructOrUnionNotAllowed {
758758
pub span: Span,
759759
pub struct_or_union: &'static str,
760760
}
761+
762+
#[derive(Diagnostic)]
763+
#[diag(ast_passes_match_arm_with_no_body)]
764+
pub struct MatchArmWithNoBody {
765+
#[primary_span]
766+
pub span: Span,
767+
#[suggestion(code = " => todo!(),", applicability = "has-placeholders")]
768+
pub suggestion: Span,
769+
}

compiler/rustc_ast_passes/src/feature_gate.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,34 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
554554
gate_all!(explicit_tail_calls, "`become` expression is experimental");
555555
gate_all!(generic_const_items, "generic const items are experimental");
556556
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
557-
gate_all!(never_patterns, "`!` patterns are experimental");
557+
558+
if !visitor.features.never_patterns {
559+
if let Some(spans) = spans.get(&sym::never_patterns) {
560+
for &span in spans {
561+
if span.allows_unstable(sym::never_patterns) {
562+
continue;
563+
}
564+
let sm = sess.source_map();
565+
// We gate two types of spans: the span of a `!` pattern, and the span of a
566+
// match arm without a body. For the latter we want to give the user a normal
567+
// error.
568+
if let Ok(snippet) = sm.span_to_snippet(span)
569+
&& snippet == "!"
570+
{
571+
feature_err(
572+
&sess.parse_sess,
573+
sym::never_patterns,
574+
span,
575+
"`!` patterns are experimental",
576+
)
577+
.emit();
578+
} else {
579+
let suggestion = span.shrink_to_hi();
580+
sess.emit_err(errors::MatchArmWithNoBody { span, suggestion });
581+
}
582+
}
583+
}
584+
}
558585

559586
if !visitor.features.negative_bounds {
560587
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {

compiler/rustc_codegen_llvm/src/back/lto.rs

+3
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,9 @@ impl ThinLTOKeysMap {
816816
use std::io::Write;
817817
let file = File::create(path)?;
818818
let mut writer = io::BufWriter::new(file);
819+
// The entries are loaded back into a hash map in `load_from_file()`, so
820+
// the order in which we write them to file here does not matter.
821+
#[allow(rustc::potential_query_instability)]
819822
for (module, key) in &self.keys {
820823
writeln!(writer, "{module} {key}")?;
821824
}

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
5858
return;
5959
}
6060

61+
// The entries of the map are only used to get a list of all files with
62+
// coverage info. In the end the list of files is passed into
63+
// `GlobalFileTable::new()` which internally do `.sort_unstable_by()`, so
64+
// the iteration order here does not matter.
65+
#[allow(rustc::potential_query_instability)]
6166
let function_coverage_entries = function_coverage_map
6267
.into_iter()
6368
.map(|(instance, function_coverage)| (instance, function_coverage.into_finished()))

compiler/rustc_codegen_llvm/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#![feature(never_type)]
1818
#![feature(impl_trait_in_assoc_type)]
1919
#![recursion_limit = "256"]
20-
#![allow(rustc::potential_query_instability)]
2120
#![deny(rustc::untranslatable_diagnostic)]
2221
#![deny(rustc::diagnostic_outside_of_impl)]
2322

compiler/rustc_lint_defs/src/lib.rs

+67
Original file line numberDiff line numberDiff line change
@@ -345,30 +345,97 @@ pub struct FutureIncompatibleInfo {
345345
}
346346

347347
/// The reason for future incompatibility
348+
///
349+
/// Future-incompatible lints come in roughly two categories:
350+
///
351+
/// 1. There was a mistake in the compiler (such as a soundness issue), and
352+
/// we're trying to fix it, but it may be a breaking change.
353+
/// 2. A change across an Edition boundary, typically used for the
354+
/// introduction of new language features that can't otherwise be
355+
/// introduced in a backwards-compatible way.
356+
///
357+
/// See <https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html> and
358+
/// <https://rustc-dev-guide.rust-lang.org/diagnostics.html#future-incompatible-lints>
359+
/// for more information.
348360
#[derive(Copy, Clone, Debug)]
349361
pub enum FutureIncompatibilityReason {
350362
/// This will be an error in a future release for all editions
351363
///
352364
/// This will *not* show up in cargo's future breakage report.
353365
/// The warning will hence only be seen in local crates, not in dependencies.
366+
///
367+
/// Choose this variant when you are first introducing a "future
368+
/// incompatible" warning that is intended to eventually be fixed in the
369+
/// future. This allows crate developers an opportunity to fix the warning
370+
/// before blasting all dependents with a warning they can't fix
371+
/// (dependents have to wait for a new release of the affected crate to be
372+
/// published).
373+
///
374+
/// After a lint has been in this state for a while, consider graduating
375+
/// it to [`FutureIncompatibilityReason::FutureReleaseErrorReportInDeps`].
354376
FutureReleaseErrorDontReportInDeps,
355377
/// This will be an error in a future release, and
356378
/// Cargo should create a report even for dependencies
357379
///
358380
/// This is the *only* reason that will make future incompatibility warnings show up in cargo's
359381
/// reports. All other future incompatibility warnings are not visible when they occur in a
360382
/// dependency.
383+
///
384+
/// Choose this variant after the lint has been sitting in the
385+
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`]
386+
/// state for a while, and you feel like it is ready to graduate to
387+
/// warning everyone. It is a good signal that it is ready if you can
388+
/// determine that all or most affected crates on crates.io have been
389+
/// updated.
390+
///
391+
/// After some period of time, lints with this variant can be turned into
392+
/// hard errors (and the lint removed). Preferably when there is some
393+
/// confidence that the number of impacted projects is very small (few
394+
/// should have a broken dependency in their dependency tree).
361395
FutureReleaseErrorReportInDeps,
362396
/// Code that changes meaning in some way in a
363397
/// future release.
398+
///
399+
/// Choose this variant when the semantics of existing code is changing,
400+
/// (as opposed to
401+
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`],
402+
/// which is for when code is going to be rejected in the future).
364403
FutureReleaseSemanticsChange,
365404
/// Previously accepted code that will become an
366405
/// error in the provided edition
406+
///
407+
/// Choose this variant for code that you want to start rejecting across
408+
/// an edition boundary. This will automatically include the lint in the
409+
/// `rust-20xx-compatibility` lint group, which is used by `cargo fix
410+
/// --edition` to do migrations. The lint *should* be auto-fixable with
411+
/// [`Applicability::MachineApplicable`].
412+
///
413+
/// The lint can either be `Allow` or `Warn` by default. If it is `Allow`,
414+
/// users usually won't see this warning unless they are doing an edition
415+
/// migration manually or there is a problem during the migration (cargo's
416+
/// automatic migrations will force the level to `Warn`). If it is `Warn`
417+
/// by default, users on all editions will see this warning (only do this
418+
/// if you think it is important for everyone to be aware of the change,
419+
/// and to encourage people to update their code on all editions).
420+
///
421+
/// See also [`FutureIncompatibilityReason::EditionSemanticsChange`] if
422+
/// you have code that is changing semantics across the edition (as
423+
/// opposed to being rejected).
367424
EditionError(Edition),
368425
/// Code that changes meaning in some way in
369426
/// the provided edition
427+
///
428+
/// This is the same as [`FutureIncompatibilityReason::EditionError`],
429+
/// except for situations where the semantics change across an edition. It
430+
/// slightly changes the text of the diagnostic, but is otherwise the
431+
/// same.
370432
EditionSemanticsChange(Edition),
371433
/// A custom reason.
434+
///
435+
/// Choose this variant if the built-in text of the diagnostic of the
436+
/// other variants doesn't match your situation. This is behaviorally
437+
/// equivalent to
438+
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`].
372439
Custom(&'static str),
373440
}
374441

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
3838
#include "llvm/LTO/LTO.h"
3939
#include "llvm/Bitcode/BitcodeWriter.h"
40-
40+
#if LLVM_VERSION_GE(18, 0)
41+
#include "llvm/TargetParser/Host.h"
42+
#endif
4143
#include "llvm/Transforms/Instrumentation.h"
4244
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
4345
#include "llvm/Support/TimeProfiler.h"

compiler/rustc_parse/src/parser/expr.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2918,7 +2918,15 @@ impl<'a> Parser<'a> {
29182918
let mut result = if !is_fat_arrow && !is_almost_fat_arrow {
29192919
// A pattern without a body, allowed for never patterns.
29202920
arm_body = None;
2921-
this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)])
2921+
this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]).map(
2922+
|x| {
2923+
// Don't gate twice
2924+
if !pat.contains_never_pattern() {
2925+
this.sess.gated_spans.gate(sym::never_patterns, pat.span);
2926+
}
2927+
x
2928+
},
2929+
)
29222930
} else {
29232931
if let Err(mut err) = this.expect(&token::FatArrow) {
29242932
// We might have a `=>` -> `=` or `->` typo (issue #89396).

compiler/rustc_parse/src/validate_attr.rs

+38-22
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use rustc_ast::token::Delimiter;
66
use rustc_ast::tokenstream::DelimSpan;
77
use rustc_ast::MetaItemKind;
88
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem};
9-
use rustc_ast_pretty::pprust;
109
use rustc_errors::{Applicability, FatalError, PResult};
1110
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
11+
use rustc_session::errors::report_lit_error;
1212
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
1313
use rustc_session::parse::ParseSess;
1414
use rustc_span::{sym, Span, Symbol};
@@ -51,28 +51,44 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
5151
MetaItemKind::List(nmis)
5252
}
5353
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
54-
if let ast::ExprKind::Lit(token_lit) = expr.kind
55-
&& let Ok(lit) = ast::MetaItemLit::from_token_lit(token_lit, expr.span)
56-
{
57-
if token_lit.suffix.is_some() {
58-
let mut err = sess.span_diagnostic.struct_span_err(
59-
expr.span,
60-
"suffixed literals are not allowed in attributes",
61-
);
62-
err.help(
63-
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
64-
use an unsuffixed version (`1`, `1.0`, etc.)",
65-
);
66-
return Err(err);
67-
} else {
68-
MetaItemKind::NameValue(lit)
69-
}
54+
if let ast::ExprKind::Lit(token_lit) = expr.kind {
55+
let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
56+
let res = match res {
57+
Ok(lit) => {
58+
if token_lit.suffix.is_some() {
59+
let mut err = sess.span_diagnostic.struct_span_err(
60+
expr.span,
61+
"suffixed literals are not allowed in attributes",
62+
);
63+
err.help(
64+
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
65+
use an unsuffixed version (`1`, `1.0`, etc.)",
66+
);
67+
return Err(err);
68+
} else {
69+
MetaItemKind::NameValue(lit)
70+
}
71+
}
72+
Err(err) => {
73+
report_lit_error(sess, err, token_lit, expr.span);
74+
let lit = ast::MetaItemLit {
75+
symbol: token_lit.symbol,
76+
suffix: token_lit.suffix,
77+
kind: ast::LitKind::Err,
78+
span: expr.span,
79+
};
80+
MetaItemKind::NameValue(lit)
81+
}
82+
};
83+
res
7084
} else {
71-
// The non-error case can happen with e.g. `#[foo = 1+1]`. The error case can
72-
// happen with e.g. `#[foo = include_str!("nonexistent-file.rs")]`; in that
73-
// case we delay the error because an earlier error will have already been
74-
// reported.
75-
let msg = format!("unexpected expression: `{}`", pprust::expr_to_string(expr));
85+
// Example cases:
86+
// - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
87+
// - `#[foo = include_str!("nonexistent-file.rs")]`:
88+
// results in `ast::ExprKind::Err`. In that case we delay
89+
// the error because an earlier error will have already
90+
// been reported.
91+
let msg = format!("attribute value must be a literal");
7692
let mut err = sess.span_diagnostic.struct_span_err(expr.span, msg);
7793
if let ast::ExprKind::Err = expr.kind {
7894
err.downgrade_to_delayed_bug();

0 commit comments

Comments
 (0)