Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 9 pull requests #120522

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4c01025
std: thread_local::register_dtor fix proposal for FreeBSD.
devnexen Jan 27, 2024
ad1e629
Make duplicate lang items fatal
Nilstrieb Jan 29, 2024
a360ecd
Delete now-useless test
Nilstrieb Jan 29, 2024
1f89e90
Add test for duplicate lang items
Nilstrieb Jan 29, 2024
f6b21e9
Remove the `abi_amdgpu_kernel` feature
clubby789 Jan 30, 2024
0b2579a
Make `PatternColumn` generic in `Cx`
Nadrieril Jan 24, 2024
cb0e8c5
Limit the use of `PlaceCtxt`
Nadrieril Jan 24, 2024
83e88c6
Repurpose `MatchCtxt` for usefulness only
Nadrieril Jan 24, 2024
6ef8362
Make `PatternColumn` part of the public API
Nadrieril Jan 24, 2024
5903142
Separate `PlaceCtxt` from `UsefulnessCtxt`
Nadrieril Jan 24, 2024
dfbbdda
check `RUST_BOOTSTRAP_CONFIG` in `profile_user_dist` test
onur-ozkan Jan 21, 2024
75f670d
rustdoc: Correctly handle attribute merge if this is a glob reexport
GuillaumeGomez Jan 30, 2024
024364a
Add regression test for #120487
GuillaumeGomez Jan 30, 2024
8ebd47e
Mark "unused binding" suggestion as maybe incorrect
estebank Jan 29, 2024
6efddac
Provide more context on derived obligation error primary label
estebank Jan 29, 2024
c780fe6
document `FromIterator for Vec` allocation behaviors
the8472 Jan 25, 2024
39dc315
Apply suggestions from code review
the8472 Jan 26, 2024
f810a80
Rollup merge of #120207 - onur-ozkan:120202-fix, r=clubby789
Nadrieril Jan 31, 2024
79a6a01
Rollup merge of #120321 - Nadrieril:cleanup-cx, r=compiler-errors
Nadrieril Jan 31, 2024
2932425
Rollup merge of #120355 - the8472:doc-vec-fromiter, r=cuviper
Nadrieril Jan 31, 2024
48ca8f4
Rollup merge of #120430 - devnexen:fix_tls_dtor_fbsd, r=cuviper
Nadrieril Jan 31, 2024
ef9dd13
Rollup merge of #120469 - estebank:issue-40120, r=TaKO8Ki
Nadrieril Jan 31, 2024
df61874
Rollup merge of #120470 - estebank:issue-54196, r=compiler-errors
Nadrieril Jan 31, 2024
82ee16f
Rollup merge of #120472 - Nilstrieb:die, r=compiler-errors
Nadrieril Jan 31, 2024
6414100
Rollup merge of #120495 - clubby789:remove-amdgpu-kernel, r=oli-obk
Nadrieril Jan 31, 2024
26b411e
Rollup merge of #120501 - GuillaumeGomez:glob-reexport-attr-merge-bug…
Nadrieril Jan 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call
sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented");
}

Conv::Msp430Intr
| Conv::PtxKernel
| Conv::AmdGpuKernel
| Conv::AvrInterrupt
| Conv::AvrNonBlockingInterrupt => {
Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => {
unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");
}
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,6 @@ impl From<Conv> for llvm::CallConv {
Conv::Cold => llvm::ColdCallConv,
Conv::PreserveMost => llvm::PreserveMost,
Conv::PreserveAll => llvm::PreserveAll,
Conv::AmdGpuKernel => llvm::AmdGpuKernel,
Conv::AvrInterrupt => llvm::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
Conv::ArmAapcs => llvm::ArmAapcsCallConv,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ pub enum CallConv {
X86_Intr = 83,
AvrNonBlockingInterrupt = 84,
AvrInterrupt = 85,
AmdGpuKernel = 91,
}

/// LLVMRustLinkage
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ declare_features! (
// feature-group-start: removed features
// -------------------------------------------------------------------------

/// Allows using the `amdgpu-kernel` ABI.
(removed, abi_amdgpu_kernel, "CURRENT_RUSTC_VERSION", Some(51575), None),
(removed, advanced_slice_patterns, "1.0.0", Some(62254),
Some("merged into `#![feature(slice_patterns)]`")),
(removed, allocator, "1.0.0", None, None),
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,6 @@ declare_features! (
// feature-group-start: actual feature gates
// -------------------------------------------------------------------------

/// Allows using the `amdgpu-kernel` ABI.
(unstable, abi_amdgpu_kernel, "1.29.0", Some(51575)),
/// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
(unstable, abi_avr_interrupt, "1.45.0", Some(69664)),
/// Allows `extern "C-cmse-nonsecure-call" fn()`.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,6 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
PtxKernel
| Msp430Interrupt
| X86Interrupt
| AmdGpuKernel
| EfiApi
| AvrInterrupt
| AvrNonBlockingInterrupt
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ fn abi_can_unwind(abi: Abi) -> bool {
PtxKernel
| Msp430Interrupt
| X86Interrupt
| AmdGpuKernel
| EfiApi
| AvrInterrupt
| AvrNonBlockingInterrupt
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1739,7 +1739,7 @@ pub struct UnusedVariableTryPrefix {

#[derive(Subdiagnostic)]
pub enum UnusedVariableSugg {
#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
#[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")]
TryPrefixSugg {
#[suggestion_part(code = "_{name}")]
spans: Vec<Span>,
Expand Down Expand Up @@ -1778,7 +1778,7 @@ pub struct UnusedVarTryIgnore {
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
#[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")]
pub struct UnusedVarTryIgnoreSugg {
#[suggestion_part(code = "{name}: _")]
pub shorthands: Vec<Span>,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_passes/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,9 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
}
};

self.tcx.dcx().emit_err(DuplicateLangItem {
// When there's a duplicate lang item, something went very wrong and there's no value in recovering or doing anything.
// Give the user the one message to let them debug the mess they created and then wish them farewell.
self.tcx.dcx().emit_fatal(DuplicateLangItem {
local_span: item_span,
lang_item_name,
crate_name,
Expand Down
26 changes: 12 additions & 14 deletions compiler/rustc_pattern_analysis/src/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ use self::MaybeInfiniteInt::*;
use self::SliceKind::*;

use crate::index;
use crate::usefulness::PlaceCtxt;
use crate::TypeCx;

/// Whether we have seen a constructor in the column or not.
Expand Down Expand Up @@ -818,21 +817,20 @@ impl<Cx: TypeCx> Constructor<Cx> {

/// The number of fields for this constructor. This must be kept in sync with
/// `Fields::wildcards`.
pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize {
pcx.ctor_arity(self)
pub(crate) fn arity(&self, cx: &Cx, ty: &Cx::Ty) -> usize {
cx.ctor_arity(self, ty)
}

/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
/// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
/// this checks for inclusion.
// We inline because this has a single call site in `Matrix::specialize_constructor`.
#[inline]
pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool {
pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool {
match (self, other) {
(Wildcard, _) => pcx
.mcx
.tycx
.bug(format_args!("Constructor splitting should not have returned `Wildcard`")),
(Wildcard, _) => {
cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`"))
}
// Wildcards cover anything
(_, Wildcard) => true,
// Only a wildcard pattern can match these special constructors.
Expand Down Expand Up @@ -873,7 +871,7 @@ impl<Cx: TypeCx> Constructor<Cx> {
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
(Opaque(..), _) | (_, Opaque(..)) => false,

_ => pcx.mcx.tycx.bug(format_args!(
_ => cx.bug(format_args!(
"trying to compare incompatible constructors {self:?} and {other:?}"
)),
}
Expand Down Expand Up @@ -950,10 +948,10 @@ pub enum ConstructorSet<Cx: TypeCx> {
/// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be
/// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4.
#[derive(Debug)]
pub(crate) struct SplitConstructorSet<Cx: TypeCx> {
pub(crate) present: SmallVec<[Constructor<Cx>; 1]>,
pub(crate) missing: Vec<Constructor<Cx>>,
pub(crate) missing_empty: Vec<Constructor<Cx>>,
pub struct SplitConstructorSet<Cx: TypeCx> {
pub present: SmallVec<[Constructor<Cx>; 1]>,
pub missing: Vec<Constructor<Cx>>,
pub missing_empty: Vec<Constructor<Cx>>,
}

impl<Cx: TypeCx> ConstructorSet<Cx> {
Expand All @@ -962,7 +960,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
/// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation
/// and its invariants.
#[instrument(level = "debug", skip(self, ctors), ret)]
pub(crate) fn split<'a>(
pub fn split<'a>(
&self,
ctors: impl Iterator<Item = &'a Constructor<Cx>> + Clone,
) -> SplitConstructorSet<Cx>
Expand Down
24 changes: 5 additions & 19 deletions compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod errors;
#[cfg(feature = "rustc")]
pub(crate) mod lints;
pub mod pat;
pub mod pat_column;
#[cfg(feature = "rustc")]
pub mod rustc;
pub mod usefulness;
Expand Down Expand Up @@ -67,8 +68,9 @@ use rustc_span::ErrorGuaranteed;

use crate::constructor::{Constructor, ConstructorSet, IntRange};
#[cfg(feature = "rustc")]
use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn};
use crate::lints::lint_nonexhaustive_missing_variants;
use crate::pat::DeconstructedPat;
use crate::pat_column::PatternColumn;
#[cfg(feature = "rustc")]
use crate::rustc::RustcMatchCheckCtxt;
#[cfg(feature = "rustc")]
Expand Down Expand Up @@ -135,20 +137,6 @@ pub trait TypeCx: Sized + fmt::Debug {
}
}

/// Context that provides information global to a match.
pub struct MatchCtxt<'a, Cx: TypeCx> {
/// The context for type information.
pub tycx: &'a Cx,
}

impl<'a, Cx: TypeCx> Clone for MatchCtxt<'a, Cx> {
fn clone(&self) -> Self {
Self { tycx: self.tycx }
}
}

impl<'a, Cx: TypeCx> Copy for MatchCtxt<'a, Cx> {}

/// The arm of a match expression.
#[derive(Debug)]
pub struct MatchArm<'p, Cx: TypeCx> {
Expand All @@ -175,15 +163,13 @@ pub fn analyze_match<'p, 'tcx>(
) -> Result<rustc::UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee);
let cx = MatchCtxt { tycx };

let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?;
let report = compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity)?;

// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
let pat_column = PatternColumn::new(arms);
lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?;
lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?;
}

Ok(report)
Expand Down
120 changes: 17 additions & 103 deletions compiler/rustc_pattern_analysis/src/lints.rs
Original file line number Diff line number Diff line change
@@ -1,109 +1,24 @@
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::ErrorGuaranteed;

use crate::constructor::Constructor;
use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
use crate::pat::PatOrWild;
use crate::rustc::{
Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt,
SplitConstructorSet, WitnessPat,
};

/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
/// inspect the same subvalue/place".
/// This is used to traverse patterns column-by-column for lints. Despite similarities with the
/// algorithm in [`crate::usefulness`], this does a different traversal. Notably this is linear in
/// the depth of patterns, whereas `compute_exhaustiveness_and_usefulness` is worst-case exponential
/// (exhaustiveness is NP-complete). The core difference is that we treat sub-columns separately.
///
/// This must not contain an or-pattern. `expand_and_push` takes care to expand them.
///
/// This is not used in the usefulness algorithm; only in lints.
#[derive(Debug)]
pub(crate) struct PatternColumn<'p, 'tcx> {
patterns: Vec<&'p DeconstructedPat<'p, 'tcx>>,
}

impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
pub(crate) fn new(arms: &[MatchArm<'p, 'tcx>]) -> Self {
let patterns = Vec::with_capacity(arms.len());
let mut column = PatternColumn { patterns };
for arm in arms {
column.expand_and_push(PatOrWild::Pat(arm.pat));
}
column
}
/// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns.
/// Internal method, prefer [`PatternColumn::new`].
fn expand_and_push(&mut self, pat: PatOrWild<'p, RustcMatchCheckCtxt<'p, 'tcx>>) {
// We flatten or-patterns and skip algorithm-generated wildcards.
if pat.is_or_pat() {
self.patterns.extend(
pat.flatten_or_pat().into_iter().filter_map(|pat_or_wild| pat_or_wild.as_pat()),
)
} else if let Some(pat) = pat.as_pat() {
self.patterns.push(pat)
}
}

fn head_ty(&self) -> Option<RevealedTy<'tcx>> {
self.patterns.first().map(|pat| *pat.ty())
}

/// Do constructor splitting on the constructors of the column.
fn analyze_ctors(
&self,
pcx: &PlaceCtxt<'_, 'p, 'tcx>,
) -> Result<SplitConstructorSet<'p, 'tcx>, ErrorGuaranteed> {
let column_ctors = self.patterns.iter().map(|p| p.ctor());
let ctors_for_ty = &pcx.ctors_for_ty()?;
Ok(ctors_for_ty.split(column_ctors))
}

/// Does specialization: given a constructor, this takes the patterns from the column that match
/// the constructor, and outputs their fields.
/// This returns one column per field of the constructor. They usually all have the same length
/// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns
/// which may change the lengths.
fn specialize(
&self,
pcx: &PlaceCtxt<'_, 'p, 'tcx>,
ctor: &Constructor<'p, 'tcx>,
) -> Vec<PatternColumn<'p, 'tcx>> {
let arity = ctor.arity(pcx);
if arity == 0 {
return Vec::new();
}

// We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These
// columns may have different lengths in the presence of or-patterns (this is why we can't
// reuse `Matrix`).
let mut specialized_columns: Vec<_> =
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
let relevant_patterns =
self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor()));
for pat in relevant_patterns {
let specialized = pat.specialize(ctor, arity);
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
column.expand_and_push(subpat);
}
}
specialized_columns
}
}
use crate::pat_column::PatternColumn;
use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat};
use crate::MatchArm;

/// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned
/// in a given column.
#[instrument(level = "debug", skip(cx), ret)]
fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
cx: MatchCtxt<'a, 'p, 'tcx>,
column: &PatternColumn<'p, 'tcx>,
cx: &RustcMatchCheckCtxt<'p, 'tcx>,
column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
) -> Result<Vec<WitnessPat<'p, 'tcx>>, ErrorGuaranteed> {
let Some(ty) = column.head_ty() else {
let Some(&ty) = column.head_ty() else {
return Ok(Vec::new());
};
let pcx = &PlaceCtxt::new_dummy(cx, &ty);

let set = column.analyze_ctors(pcx)?;
let set = column.analyze_ctors(cx, &ty)?;
if set.present.is_empty() {
// We can't consistently handle the case where no constructors are present (since this would
// require digging deep through any type in case there's a non_exhaustive enum somewhere),
Expand All @@ -112,20 +27,20 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
}

let mut witnesses = Vec::new();
if cx.tycx.is_foreign_non_exhaustive_enum(ty) {
if cx.is_foreign_non_exhaustive_enum(ty) {
witnesses.extend(
set.missing
.into_iter()
// This will list missing visible variants.
.filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive))
.map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor)),
.map(|missing_ctor| WitnessPat::wild_from_ctor(cx, missing_ctor, ty)),
)
}

// Recurse into the fields.
for ctor in set.present {
let specialized_columns = column.specialize(pcx, &ctor);
let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor);
let specialized_columns = column.specialize(cx, &ty, &ctor);
let wild_pat = WitnessPat::wild_from_ctor(cx, ctor, ty);
for (i, col_i) in specialized_columns.iter().enumerate() {
// Compute witnesses for each column.
let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i)?;
Expand All @@ -141,18 +56,17 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
Ok(witnesses)
}

pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
cx: MatchCtxt<'a, 'p, 'tcx>,
arms: &[MatchArm<'p, 'tcx>],
pat_column: &PatternColumn<'p, 'tcx>,
pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
rcx: &RustcMatchCheckCtxt<'p, 'tcx>,
arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>],
pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
scrut_ty: RevealedTy<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;
if !matches!(
rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0,
rustc_session::lint::Level::Allow
) {
let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column)?;
let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?;
if !witnesses.is_empty() {
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
// is not exhaustive enough.
Expand Down
Loading
Loading