Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,13 @@ pub enum PatKind<'tcx> {
pats: Box<[Pat<'tcx>]>,
},

/// A guard pattern, e.g. `x if guard(x)`
Guard {
subpattern: Box<Pat<'tcx>>,
#[type_visitable(ignore)]
condition: ExprId,
},

/// A never pattern `!`.
Never,

Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
visitor: &mut V,
pat: &'thir Pat<'tcx>,
) {
if let PatKind::Guard { subpattern, condition } = &pat.kind {
visitor.visit_pat(subpattern);
visitor.visit_expr(&visitor.thir()[*condition]);
return;
};

for_each_immediate_subpat(pat, |p| visitor.visit_pat(p));
}

Expand Down Expand Up @@ -287,5 +293,9 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
callback(pat);
}
}

PatKind::Guard { subpattern, .. } => {
callback(subpattern);
}
}
}
5 changes: 5 additions & 0 deletions compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,11 @@ impl<'tcx> MatchPairTree<'tcx> {
Some(TestableCase::Deref { temp, mutability })
}

PatKind::Guard { .. } => {
// FIXME(guard_patterns)
None
}

PatKind::Never => Some(TestableCase::Never),
};

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_mir_build/src/builder/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
visit_subpat(self, subpattern, user_tys, f);
}
}
PatKind::Guard { ref subpattern, .. } => {
visit_subpat(self, subpattern, user_tys, f);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
| PatKind::Range { .. }
| PatKind::Slice { .. }
| PatKind::Array { .. }
| PatKind::Guard { .. }
// Never constitutes a witness of uninhabitedness.
| PatKind::Never => {
self.requires_unsafe(pat.span, AccessToUnionField);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/thir/cx/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
}
Some(_) | None => local.span,
};
let initializer = local.init.map(|init| self.mirror_expr(init));
let stmt = Stmt {
kind: StmtKind::Let {
remainder_scope,
Expand All @@ -91,7 +92,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
data: region::ScopeData::Node,
},
pattern,
initializer: local.init.map(|init| self.mirror_expr(init)),
initializer,
else_block,
hir_id: local.hir_id,
span,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
};

let indices = self.typeck_results.offset_of_data().get(expr.hir_id).unwrap();
let mut expr = None::<ExprKind<'tcx>>;
let mut expr = None::<ExprKind<'_>>;

for &(container, variant, field) in indices.iter() {
let next = mk_call(&mut self.thir, container, variant, field);
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_mir_build/src/thir/cx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ use rustc_middle::thir::*;
use rustc_middle::ty::{self, TyCtxt};

/// Query implementation for [`TyCtxt::thir_body`].
pub(crate) fn thir_body(
tcx: TyCtxt<'_>,
pub(crate) fn thir_body<'tcx>(
tcx: TyCtxt<'tcx>,
owner_def: LocalDefId,
) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> {
) -> Result<(&'tcx Steal<Thir<'tcx>>, ExprId), ErrorGuaranteed> {
debug_assert!(!tcx.is_type_const(owner_def.to_def_id()), "thir_body queried for type_const");

let body = tcx.hir_body_owned_by(owner_def);
let mut cx = ThirBuildCx::new(tcx, owner_def);
let mut cx: ThirBuildCx<'tcx> = ThirBuildCx::new(tcx, owner_def);
if let Some(reported) = cx.typeck_results.tainted_by_errors {
return Err(reported);
}
Expand Down Expand Up @@ -50,7 +50,7 @@ pub(crate) fn thir_body(
}

/// Context for lowering HIR to THIR for a single function body (or other kind of body).
struct ThirBuildCx<'tcx> {
pub(crate) struct ThirBuildCx<'tcx> {
tcx: TyCtxt<'tcx>,
/// The THIR data that this context is building.
thir: Thir<'tcx>,
Expand Down Expand Up @@ -118,6 +118,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
let_stmt_type: Option<&hir::Ty<'tcx>>,
) -> Box<Pat<'tcx>> {
crate::thir::pattern::pat_from_hir(
self,
self.tcx,
self.typing_env,
self.typeck_results,
Expand Down Expand Up @@ -201,7 +202,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
fn_sig.inputs()[index]
};

let pat = self.pattern_from_hir(param.pat);
let pat: Box<Pat<'tcx>> = self.pattern_from_hir(param.pat);
Param { pat: Some(pat), ty, ty_span, self_kind, hir_id: Some(param.hir_id) }
})
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::errors::{
PointerPattern, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern,
};

impl<'tcx> PatCtxt<'tcx> {
impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
/// Converts a constant to a pattern (if possible).
/// This means aggregate values (like structs and enums) are converted
/// to a pattern that matches the value (as if you'd compared via structural equality).
Expand Down Expand Up @@ -61,7 +61,7 @@ struct ConstToPat<'tcx> {
}

impl<'tcx> ConstToPat<'tcx> {
fn new(pat_ctxt: &PatCtxt<'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
fn new(pat_ctxt: &PatCtxt<'tcx, '_>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
trace!(?pat_ctxt.typeck_results.hir_owner);
ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c }
}
Expand Down
18 changes: 12 additions & 6 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ use tracing::{debug, instrument};
pub(crate) use self::check_match::check_match;
use self::migration::PatMigration;
use crate::errors::*;
use crate::thir::cx::ThirBuildCx;

/// Context for lowering HIR patterns to THIR patterns.
struct PatCtxt<'tcx> {
struct PatCtxt<'tcx, 'ptcx> {
upper: &'ptcx mut ThirBuildCx<'tcx>,
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
typeck_results: &'tcx ty::TypeckResults<'tcx>,
Expand All @@ -41,8 +43,9 @@ struct PatCtxt<'tcx> {
rust_2024_migration: Option<PatMigration<'tcx>>,
}

#[instrument(level = "debug", skip(tcx, typing_env, typeck_results), ret)]
pub(super) fn pat_from_hir<'tcx>(
#[instrument(level = "debug", skip(upper, tcx, typing_env, typeck_results), ret)]
pub(super) fn pat_from_hir<'tcx, 'ptcx>(
upper: &'ptcx mut ThirBuildCx<'tcx>,
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
typeck_results: &'tcx ty::TypeckResults<'tcx>,
Expand All @@ -51,6 +54,7 @@ pub(super) fn pat_from_hir<'tcx>(
let_stmt_type: Option<&hir::Ty<'tcx>>,
) -> Box<Pat<'tcx>> {
let mut pcx = PatCtxt {
upper,
tcx,
typing_env,
typeck_results,
Expand Down Expand Up @@ -87,7 +91,7 @@ pub(super) fn pat_from_hir<'tcx>(
thir_pat
}

impl<'tcx> PatCtxt<'tcx> {
impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
let adjustments: &[PatAdjustment<'tcx>] =
self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
Expand Down Expand Up @@ -443,8 +447,10 @@ impl<'tcx> PatCtxt<'tcx> {

hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },

// FIXME(guard_patterns): implement guard pattern lowering
hir::PatKind::Guard(pat, _) => self.lower_pattern(pat).kind,
hir::PatKind::Guard(pat, condition) => PatKind::Guard {
subpattern: self.lower_pattern(pat),
condition: self.upper.mirror_expr(condition),
},

hir::PatKind::Err(guar) => PatKind::Error(guar),
};
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_mir_build/src/thir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,14 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
print_indented!(self, "]", depth_lvl + 2);
print_indented!(self, "}", depth_lvl + 1);
}
PatKind::Guard { subpattern, condition } => {
print_indented!(self, "Guard pattern: {", depth_lvl + 1);
print_indented!(self, "subpattern: ", depth_lvl + 2);
self.print_pat(subpattern, depth_lvl + 3);
print_indented!(self, "guard: ", depth_lvl + 2);
self.print_expr(*condition, depth_lvl + 3);
print_indented!(self, "}", depth_lvl + 1);
}
PatKind::Error(_) => {
print_indented!(self, "Error", depth_lvl + 1);
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_pattern_analysis/src/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
let arity;
let fields: Vec<_>;
match &pat.kind {
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
PatKind::Binding { subpattern: Some(subpat), .. }
| PatKind::Guard { subpattern: subpat, .. } => return self.lower_pat(subpat),
PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
ctor = Wildcard;
fields = vec![];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![expect(incomplete_features)]

fn good_fn_item(((x if x) | x): bool) -> bool { x }
//~^ ERROR: used binding `x` is possibly-uninitialized [E0381]

fn bad_fn_item_1(x: bool, ((y if x) | y): bool) {}
//~^ ERROR cannot find value `x` in this scope
Expand Down
Loading
Loading