Skip to content

Commit

Permalink
Don't store thir::Pat in error structs
Browse files Browse the repository at this point in the history
In several cases this avoids the need to clone the underlying pattern, and then
print the clone later.
  • Loading branch information
Zalathar committed Jul 28, 2024
1 parent 3148b35 commit e1fc4a9
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 40 deletions.
7 changes: 0 additions & 7 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html

use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
Expand Down Expand Up @@ -702,12 +701,6 @@ impl<'tcx> Pat<'tcx> {
}
}

impl<'tcx> IntoDiagArg for Pat<'tcx> {
fn into_diag_arg(self) -> DiagArgValue {
format!("{self}").into_diag_arg()
}
}

#[derive(Clone, Debug, HashStable, TypeVisitable)]
pub struct Ascription<'tcx> {
pub annotation: CanonicalUserTypeAnnotation<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
pub(crate) span: Span,
pub(crate) origin: &'s str,
#[subdiagnostic]
pub(crate) uncovered: Uncovered<'tcx>,
pub(crate) uncovered: Uncovered,
#[subdiagnostic]
pub(crate) inform: Option<Inform>,
#[subdiagnostic]
Expand Down
53 changes: 26 additions & 27 deletions compiler/rustc_pattern_analysis/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,44 @@
use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::thir::Pat;
use rustc_middle::ty::Ty;
use rustc_span::Span;

use crate::rustc::{RustcPatCtxt, WitnessPat};

#[derive(Subdiagnostic)]
#[label(pattern_analysis_uncovered)]
pub struct Uncovered<'tcx> {
pub struct Uncovered {
#[primary_span]
span: Span,
count: usize,
witness_1: Pat<'tcx>,
witness_2: Pat<'tcx>,
witness_3: Pat<'tcx>,
witness_1: String, // a printed pattern
witness_2: String, // a printed pattern
witness_3: String, // a printed pattern
remainder: usize,
}

impl<'tcx> Uncovered<'tcx> {
pub fn new<'p>(
impl Uncovered {
pub fn new<'p, 'tcx>(
span: Span,
cx: &RustcPatCtxt<'p, 'tcx>,
witnesses: Vec<WitnessPat<'p, 'tcx>>,
) -> Self
where
'tcx: 'p,
{
let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap());
let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap()).to_string();
Self {
span,
count: witnesses.len(),
// Substitute dummy values if witnesses is smaller than 3. These will never be read.
witness_2: witnesses
.get(1)
.map(|w| cx.hoist_witness_pat(w))
.unwrap_or_else(|| witness_1.clone()),
.map(|w| cx.hoist_witness_pat(w).to_string())
.unwrap_or_default(),
witness_3: witnesses
.get(2)
.map(|w| cx.hoist_witness_pat(w))
.unwrap_or_else(|| witness_1.clone()),
.map(|w| cx.hoist_witness_pat(w).to_string())
.unwrap_or_default(),
witness_1,
remainder: witnesses.len().saturating_sub(3),
}
Expand All @@ -49,19 +48,19 @@ impl<'tcx> Uncovered<'tcx> {
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_overlapping_range_endpoints)]
#[note]
pub struct OverlappingRangeEndpoints<'tcx> {
pub struct OverlappingRangeEndpoints {
#[label]
pub range: Span,
#[subdiagnostic]
pub overlap: Vec<Overlap<'tcx>>,
pub overlap: Vec<Overlap>,
}

pub struct Overlap<'tcx> {
pub struct Overlap {
pub span: Span,
pub range: Pat<'tcx>,
pub range: String, // a printed pattern
}

impl<'tcx> Subdiagnostic for Overlap<'tcx> {
impl Subdiagnostic for Overlap {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
Expand All @@ -78,38 +77,38 @@ impl<'tcx> Subdiagnostic for Overlap<'tcx> {

#[derive(LintDiagnostic)]
#[diag(pattern_analysis_excluside_range_missing_max)]
pub struct ExclusiveRangeMissingMax<'tcx> {
pub struct ExclusiveRangeMissingMax {
#[label]
#[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
/// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`).
pub first_range: Span,
/// Suggest `lo..=max` instead.
pub suggestion: String,
pub max: Pat<'tcx>,
pub max: String, // a printed pattern
}

#[derive(LintDiagnostic)]
#[diag(pattern_analysis_excluside_range_missing_gap)]
pub struct ExclusiveRangeMissingGap<'tcx> {
pub struct ExclusiveRangeMissingGap {
#[label]
#[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
/// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`).
pub first_range: Span,
pub gap: Pat<'tcx>,
pub gap: String, // a printed pattern
/// Suggest `lo..=gap` instead.
pub suggestion: String,
#[subdiagnostic]
/// All these ranges skipped over `gap` which we think is probably a mistake.
pub gap_with: Vec<GappedRange<'tcx>>,
pub gap_with: Vec<GappedRange>,
}

pub struct GappedRange<'tcx> {
pub struct GappedRange {
pub span: Span,
pub gap: Pat<'tcx>,
pub first_range: Pat<'tcx>,
pub gap: String, // a printed pattern
pub first_range: String, // a printed pattern
}

impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
impl Subdiagnostic for GappedRange {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
Expand All @@ -134,7 +133,7 @@ impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
pub scrut_ty: Ty<'tcx>,
#[subdiagnostic]
pub uncovered: Uncovered<'tcx>,
pub uncovered: Uncovered,
}

#[derive(LintDiagnostic)]
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_pattern_analysis/src/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
let overlaps: Vec<_> = overlaps_with
.iter()
.map(|pat| pat.data().span)
.map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
.map(|span| errors::Overlap { range: overlap_as_pat.to_string(), span })
.collect();
let pat_span = pat.data().span;
self.tcx.emit_node_span_lint(
Expand Down Expand Up @@ -1014,7 +1014,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
// Point at this range.
first_range: thir_pat.span,
// That's the gap that isn't covered.
max: gap_as_pat.clone(),
max: gap_as_pat.to_string(),
// Suggest `lo..=max` instead.
suggestion: suggested_range.to_string(),
},
Expand All @@ -1028,7 +1028,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
// Point at this range.
first_range: thir_pat.span,
// That's the gap that isn't covered.
gap: gap_as_pat.clone(),
gap: gap_as_pat.to_string(),
// Suggest `lo..=gap` instead.
suggestion: suggested_range.to_string(),
// All these ranges skipped over `gap` which we think is probably a
Expand All @@ -1037,8 +1037,8 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
.iter()
.map(|pat| errors::GappedRange {
span: pat.data().span,
gap: gap_as_pat.clone(),
first_range: thir_pat.clone(),
gap: gap_as_pat.to_string(),
first_range: thir_pat.to_string(),
})
.collect(),
},
Expand Down

0 comments on commit e1fc4a9

Please sign in to comment.