Skip to content

Commit

Permalink
Auto merge of rust-lang#134248 - oli-obk:patkind-path-removal, r=<try>
Browse files Browse the repository at this point in the history
Merge `PatKind::Path` into `PatKind::Lit`

Follow-up to rust-lang#134228

We always had a duplication where `Path`s could be represented as `PatKind::Path` or `PatKind::Lit(ExprKind::Path)`. We had to handle both everywhere, and still do after rust-lang#134228, so I'm removing it now.
  • Loading branch information
bors committed Jan 17, 2025
2 parents 73c0ae6 + 9d7525b commit dbdec20
Show file tree
Hide file tree
Showing 29 changed files with 210 additions and 179 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
self.insert(expr.span, expr.hir_id, Node::PatExpr(expr));

self.with_parent(expr.hir_id, |this| {
intravisit::walk_pat_expr(this, expr);
intravisit::walk_pat_expr(this, expr.hir_id, expr.span, &expr.kind);
});
}

Expand Down
26 changes: 12 additions & 14 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
break hir::PatKind::Ref(self.lower_pat(inner), *mutbl);
}
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
let mut lower_end = |e: &Expr| {
&*self.arena.alloc(hir::PatExpr {
hir_id: self.lower_node_id(e.id),
span: e.span,
kind: self.lower_expr_within_pat(e, true),
})
};
break hir::PatKind::Range(
e1.as_deref().map(|e| self.lower_expr_within_pat(e, true)),
e2.as_deref().map(|e| self.lower_expr_within_pat(e, true)),
e1.as_deref().map(|e| lower_end(e)),
e2.as_deref().map(|e| lower_end(e)),
self.lower_range_end(end, e2.is_some()),
);
}
Expand Down Expand Up @@ -370,16 +377,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// }
// m!(S);
// ```
fn lower_expr_within_pat(
&mut self,
expr: &Expr,
allow_paths: bool,
) -> &'hir hir::PatExpr<'hir> {
fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> hir::PatExprKind<'hir> {
let err = |guar| hir::PatExprKind::Lit {
lit: self.arena.alloc(respan(self.lower_span(expr.span), LitKind::Err(guar))),
negated: false,
};
let kind = match &expr.kind {
match &expr.kind {
ExprKind::Lit(lit) => {
hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: false }
}
Expand Down Expand Up @@ -413,11 +416,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
});
err(guar)
}
};
self.arena.alloc(hir::PatExpr {
hir_id: self.lower_node_id(expr.id),
span: expr.span,
kind,
})
}
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,7 @@ impl fmt::Debug for DotDotPos {

#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct PatExpr<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub span: Span,
pub kind: PatExprKind<'hir>,
Expand Down Expand Up @@ -1584,7 +1585,7 @@ pub enum PatKind<'hir> {
Ref(&'hir Pat<'hir>, Mutability),

/// A literal, const block or path.
Expr(&'hir PatExpr<'hir>),
Expr(PatExprKind<'hir>),

/// A guard pattern (e.g., `x if guard(x)`).
Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
Expand Down
19 changes: 13 additions & 6 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ pub trait Visitor<'v>: Sized {
walk_pat_field(self, f)
}
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
walk_pat_expr(self, expr)
walk_pat_expr(self, expr.hir_id, expr.span, &expr.kind)
}
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
walk_anon_const(self, c)
Expand Down Expand Up @@ -688,7 +688,9 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
try_visit!(visitor.visit_ident(ident));
visit_opt!(visitor, visit_pat, optional_subpattern);
}
PatKind::Expr(ref expression) => try_visit!(visitor.visit_pat_expr(expression)),
PatKind::Expr(ref expression) => {
try_visit!(walk_pat_expr(visitor, pattern.hir_id, pattern.span, expression))
}
PatKind::Range(ref lower_bound, ref upper_bound, _) => {
visit_opt!(visitor, visit_pat_expr, lower_bound);
visit_opt!(visitor, visit_pat_expr, upper_bound);
Expand All @@ -713,12 +715,17 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
visitor.visit_pat(field.pat)
}

pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
try_visit!(visitor.visit_id(expr.hir_id));
match &expr.kind {
pub fn walk_pat_expr<'v, V: Visitor<'v>>(
visitor: &mut V,
hir_id: HirId,
span: Span,
kind: &'v PatExprKind<'v>,
) -> V::Result {
try_visit!(visitor.visit_id(hir_id));
match kind {
PatExprKind::Lit { .. } => V::Result::output(),
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, hir_id, span),
}
}

Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl<'a> State<'a> {
Node::OpaqueTy(o) => self.print_opaque_ty(o),
Node::Pat(a) => self.print_pat(a),
Node::PatField(a) => self.print_patfield(a),
Node::PatExpr(a) => self.print_pat_expr(a),
Node::PatExpr(a) => self.print_pat_expr(&a.kind),
Node::Arm(a) => self.print_arm(a),
Node::Infer(_) => self.word("_"),
Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
Expand Down Expand Up @@ -1850,8 +1850,8 @@ impl<'a> State<'a> {
}
}

fn print_pat_expr(&mut self, expr: &hir::PatExpr<'_>) {
match &expr.kind {
fn print_pat_expr(&mut self, kind: &hir::PatExprKind<'_>) {
match kind {
hir::PatExprKind::Lit { lit, negated } => {
if *negated {
self.word("-");
Expand Down Expand Up @@ -1980,17 +1980,17 @@ impl<'a> State<'a> {
self.pclose();
}
}
PatKind::Expr(e) => self.print_pat_expr(e),
PatKind::Expr(ref e) => self.print_pat_expr(e),
PatKind::Range(begin, end, end_kind) => {
if let Some(expr) = begin {
self.print_pat_expr(expr);
self.print_pat_expr(&expr.kind);
}
match end_kind {
RangeEnd::Included => self.word("..."),
RangeEnd::Excluded => self.word(".."),
}
if let Some(expr) = end {
self.print_pat_expr(expr);
self.print_pat_expr(&expr.kind);
}
}
PatKind::Slice(before, slice, after) => {
Expand Down
73 changes: 43 additions & 30 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => None,
};
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
let (adjust_mode, opt_expr_ty) = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
let (expected, binding_mode, max_ref_mutbl) =
self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl);
let pat_info = PatInfo {
Expand All @@ -271,7 +271,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PatKind::Wild | PatKind::Err(_) => expected,
// We allow any type here; we ensure that the type is uninhabited during match checking.
PatKind::Never => expected,
PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
PatKind::Expr(ref lt) => {
self.check_pat_lit(pat.hir_id, pat.span, lt, expected, ti, opt_expr_ty.unwrap())
}
PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
PatKind::Binding(ba, var_id, ident, sub) => {
self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
Expand Down Expand Up @@ -376,13 +378,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// How should the binding mode and expected type be adjusted?
///
/// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
///
/// Returns the unadjusted type for expr patterns.
fn calc_adjust_mode(
&self,
pat: &'tcx Pat<'tcx>,
opt_path_res: Option<Res>,
) -> (AdjustMode, Option<Ty<'tcx>>) {
// When we perform destructuring assignment, we disable default match bindings, which are
// unintuitive in this context.
if !pat.default_binding_modes {
return AdjustMode::Reset;
return (AdjustMode::Reset, None);
}
match &pat.kind {
let adjust = match &pat.kind {
// Type checking these product-like types successfully always require
// that the expected type be of those types and not reference types.
PatKind::Struct(..)
Expand All @@ -399,9 +407,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
//
// Call `resolve_vars_if_possible` here for inline const blocks.
PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
ty::Ref(..) => AdjustMode::Pass,
_ => AdjustMode::Peel,
PatKind::Expr(lt) => {
let ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt, pat.hir_id, pat.span));
let adjust = match ty.kind() {
ty::Ref(..) => AdjustMode::Pass,
_ => AdjustMode::Peel,
};
return (adjust, Some(ty))
},
PatKind::Path(_) => match opt_path_res.unwrap() {
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
Expand Down Expand Up @@ -431,7 +443,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| PatKind::Or(_)
// Like or-patterns, guard patterns just propogate to their subpatterns.
| PatKind::Guard(..) => AdjustMode::Pass,
}
};
(adjust, None)
}

/// Peel off as many immediately nested `& mut?` from the expected type as possible
Expand Down Expand Up @@ -494,8 +507,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(expected, def_br, max_ref_mutbl)
}

fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
let ty = match &lt.kind {
fn check_pat_expr_unadjusted(
&self,
kind: &'tcx hir::PatExprKind<'tcx>,
hir_id: HirId,
span: Span,
) -> Ty<'tcx> {
match kind {
rustc_hir::PatExprKind::Lit { lit, .. } => {
self.check_expr_lit(lit, Expectation::NoExpectation)
}
Expand All @@ -504,42 +522,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
rustc_hir::PatExprKind::Path(qpath) => {
let (res, opt_ty, segments) =
self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);
self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0
self.resolve_ty_and_res_fully_qualified_call(qpath, hir_id, span);
self.instantiate_value_path(segments, opt_ty, res, span, span, hir_id).0
}
};
self.write_ty(lt.hir_id, ty);
ty
}
}

fn check_pat_lit(
&self,
hir_id: HirId,
span: Span,
lt: &hir::PatExpr<'tcx>,
lt: &hir::PatExprKind<'tcx>,
expected: Ty<'tcx>,
ti: &TopInfo<'tcx>,
mut pat_ty: Ty<'tcx>,
) -> Ty<'tcx> {
// We've already computed the type above (when checking for a non-ref pat),
// so avoid computing it again.
let ty = self.node_ty(lt.hir_id);

// Byte string patterns behave the same way as array patterns
// They can denote both statically and dynamically-sized byte arrays.
let mut pat_ty = ty;
if let hir::PatExprKind::Lit {
lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
} = lt.kind
} = lt
{
let expected = self.structurally_resolve_type(span, expected);
if let ty::Ref(_, inner_ty, _) = *expected.kind()
&& self.try_structurally_resolve_type(span, inner_ty).is_slice()
{
let tcx = self.tcx;
trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
self.typeck_results
.borrow_mut()
.treat_byte_string_as_slice
.insert(lt.hir_id.local_id);
trace!(?hir_id.local_id, "polymorphic byte string lit");
self.typeck_results.borrow_mut().lit_pat_type_adjusted.insert(hir_id.local_id);
pat_ty =
Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
}
Expand All @@ -548,10 +558,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.tcx.features().string_deref_patterns()
&& let hir::PatExprKind::Lit {
lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
} = lt.kind
} = lt
{
let tcx = self.tcx;
let expected = self.resolve_vars_if_possible(expected);
self.typeck_results.borrow_mut().lit_pat_type_adjusted.insert(hir_id.local_id);
pat_ty = match expected.kind() {
ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected,
ty::Str => Ty::new_static_str(tcx),
Expand Down Expand Up @@ -597,7 +608,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let calc_side = |opt_expr: Option<&'tcx hir::PatExpr<'tcx>>| match opt_expr {
None => None,
Some(expr) => {
let ty = self.check_pat_expr_unadjusted(expr);
let ty = self.check_pat_expr_unadjusted(&expr.kind, expr.hir_id, expr.span);

self.write_ty(expr.hir_id, ty);
// Check that the end-point is possibly of numeric or char type.
// The early check here is not for correctness, but rather better
// diagnostics (e.g. when `&str` is being matched, `expected` will
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
wbcx.typeck_results.used_trait_imports = used_trait_imports;

wbcx.typeck_results.treat_byte_string_as_slice =
mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
wbcx.typeck_results.lit_pat_type_adjusted =
mem::take(&mut self.typeck_results.borrow_mut().lit_pat_type_adjusted);

debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);

Expand Down Expand Up @@ -328,6 +328,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
self.visit_field_id(field.hir_id);
}
}
hir::PatKind::Expr(hir::PatExprKind::ConstBlock(ref c)) => {
self.visit_const_block(p.span, c);
}
_ => {}
};

Expand All @@ -344,7 +347,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
if let hir::PatExprKind::ConstBlock(c) = &expr.kind {
self.visit_const_block(expr.span, c);
}
intravisit::walk_pat_expr(self, expr);
intravisit::walk_pat_expr(self, expr.hir_id, expr.span, &expr.kind);
}

fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) {
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_middle/src/ty/typeck_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,13 @@ pub struct TypeckResults<'tcx> {
/// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,

/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
/// as `&[u8]`, depending on the pattern in which they are used.
/// We sometimes treat
/// * byte string literals (which are of type `&[u8; N]`)
/// as `&[u8]`, depending on the pattern in which they are used.
/// * string literals (which are of type `&str`) as `String`
/// This hashset records all instances where we behave
/// like this to allow `const_to_pat` to reliably handle this situation.
pub treat_byte_string_as_slice: ItemLocalSet,
pub lit_pat_type_adjusted: ItemLocalSet,

/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
/// on closure size.
Expand Down Expand Up @@ -239,7 +241,7 @@ impl<'tcx> TypeckResults<'tcx> {
closure_fake_reads: Default::default(),
rvalue_scopes: Default::default(),
coroutine_stalled_predicates: Default::default(),
treat_byte_string_as_slice: Default::default(),
lit_pat_type_adjusted: Default::default(),
closure_size_eval: Default::default(),
offset_of_data: Default::default(),
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub(crate) fn lit_to_const<'tcx>(
};

let valtree = match (lit, ty.kind()) {
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
(ast::LitKind::Str(s, _), _) => {
let str_bytes = s.as_str().as_bytes();
ty::ValTree::from_raw_bytes(tcx, str_bytes)
}
Expand Down
Loading

0 comments on commit dbdec20

Please sign in to comment.