Skip to content

Commit 96c11f9

Browse files
authored
Rollup merge of #80551 - lcnr:const-arg-wildcard, r=varkor
support pattern as const parents in type_of nice to know that there's still stuff about rust i didn't know about 😆 fixes #80531 r? `@varkor`
2 parents 33806d2 + 2aef46b commit 96c11f9

File tree

5 files changed

+127
-11
lines changed

5 files changed

+127
-11
lines changed

compiler/rustc_hir/src/hir.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -760,9 +760,9 @@ pub struct Pat<'hir> {
760760
pub default_binding_modes: bool,
761761
}
762762

763-
impl Pat<'_> {
763+
impl<'hir> Pat<'hir> {
764764
// FIXME(#19596) this is a workaround, but there should be a better way
765-
fn walk_short_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) -> bool {
765+
fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool {
766766
if !it(self) {
767767
return false;
768768
}
@@ -785,12 +785,12 @@ impl Pat<'_> {
785785
/// Note that when visiting e.g. `Tuple(ps)`,
786786
/// if visiting `ps[0]` returns `false`,
787787
/// then `ps[1]` will not be visited.
788-
pub fn walk_short(&self, mut it: impl FnMut(&Pat<'_>) -> bool) -> bool {
788+
pub fn walk_short(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) -> bool {
789789
self.walk_short_(&mut it)
790790
}
791791

792792
// FIXME(#19596) this is a workaround, but there should be a better way
793-
fn walk_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) {
793+
fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) {
794794
if !it(self) {
795795
return;
796796
}
@@ -810,7 +810,7 @@ impl Pat<'_> {
810810
/// Walk the pattern in left-to-right order.
811811
///
812812
/// If `it(pat)` returns `false`, the children are not visited.
813-
pub fn walk(&self, mut it: impl FnMut(&Pat<'_>) -> bool) {
813+
pub fn walk(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) {
814814
self.walk_(&mut it)
815815
}
816816

compiler/rustc_typeck/src/collect/type_of.rs

+46-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_hir::def::{DefKind, Res};
66
use rustc_hir::def_id::{DefId, LocalDefId};
77
use rustc_hir::intravisit;
88
use rustc_hir::intravisit::Visitor;
9-
use rustc_hir::Node;
9+
use rustc_hir::{HirId, Node};
1010
use rustc_middle::hir::map::Map;
1111
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
1212
use rustc_middle::ty::util::IntTypeExt;
@@ -22,7 +22,6 @@ use super::{bad_placeholder_type, is_suggestable_infer_ty};
2222
/// This should be called using the query `tcx.opt_const_param_of`.
2323
pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
2424
use hir::*;
25-
2625
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
2726

2827
if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
@@ -62,9 +61,9 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
6261
}
6362

6463
Node::Ty(&Ty { kind: TyKind::Path(_), .. })
65-
| Node::Expr(&Expr { kind: ExprKind::Struct(..), .. })
66-
| Node::Expr(&Expr { kind: ExprKind::Path(_), .. })
67-
| Node::TraitRef(..) => {
64+
| Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
65+
| Node::TraitRef(..)
66+
| Node::Pat(_) => {
6867
let path = match parent_node {
6968
Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
7069
| Node::TraitRef(&TraitRef { path, .. }) => &*path,
@@ -79,6 +78,20 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
7978
let _tables = tcx.typeck(body_owner);
8079
&*path
8180
}
81+
Node::Pat(pat) => {
82+
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
83+
path
84+
} else {
85+
tcx.sess.delay_span_bug(
86+
tcx.def_span(def_id),
87+
&format!(
88+
"unable to find const parent for {} in pat {:?}",
89+
hir_id, pat
90+
),
91+
);
92+
return None;
93+
}
94+
}
8295
_ => {
8396
tcx.sess.delay_span_bug(
8497
tcx.def_span(def_id),
@@ -91,7 +104,6 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
91104
// We've encountered an `AnonConst` in some path, so we need to
92105
// figure out which generic parameter it corresponds to and return
93106
// the relevant type.
94-
95107
let (arg_index, segment) = path
96108
.segments
97109
.iter()
@@ -144,6 +156,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
144156
}
145157
}
146158

159+
fn get_path_containing_arg_in_pat<'hir>(
160+
pat: &'hir hir::Pat<'hir>,
161+
arg_id: HirId,
162+
) -> Option<&'hir hir::Path<'hir>> {
163+
use hir::*;
164+
165+
let is_arg_in_path = |p: &hir::Path<'_>| {
166+
p.segments
167+
.iter()
168+
.filter_map(|seg| seg.args)
169+
.flat_map(|args| args.args)
170+
.any(|arg| arg.id() == arg_id)
171+
};
172+
let mut arg_path = None;
173+
pat.walk(|pat| match pat.kind {
174+
PatKind::Struct(QPath::Resolved(_, path), _, _)
175+
| PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
176+
| PatKind::Path(QPath::Resolved(_, path))
177+
if is_arg_in_path(path) =>
178+
{
179+
arg_path = Some(path);
180+
false
181+
}
182+
_ => true,
183+
});
184+
arg_path
185+
}
186+
147187
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
148188
let def_id = def_id.expect_local();
149189
use rustc_hir::*;
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// check-pass
2+
enum ConstGenericEnum<const N: usize> {
3+
Foo([i32; N]),
4+
Bar,
5+
}
6+
7+
fn foo<const N: usize>(val: &ConstGenericEnum<N>) {
8+
if let ConstGenericEnum::<N>::Foo(field, ..) = val {}
9+
}
10+
11+
fn bar<const N: usize>(val: &ConstGenericEnum<N>) {
12+
match val {
13+
ConstGenericEnum::<N>::Foo(field, ..) => (),
14+
ConstGenericEnum::<N>::Bar => (),
15+
}
16+
}
17+
18+
fn main() {
19+
match ConstGenericEnum::Bar {
20+
ConstGenericEnum::<3>::Foo(field, ..) => (),
21+
ConstGenericEnum::<3>::Bar => (),
22+
}
23+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// check-pass
2+
enum Generic<const N: usize> {
3+
Variant,
4+
}
5+
6+
fn main() {
7+
match todo!() {
8+
Generic::<0usize>::Variant => todo!()
9+
}
10+
}
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// check-pass
2+
struct Foo<const N: usize>;
3+
4+
fn bindingp() {
5+
match Foo {
6+
mut x @ Foo::<3> => {
7+
let ref mut _x @ Foo::<3> = x;
8+
}
9+
}
10+
}
11+
12+
struct Bar<const N: usize> {
13+
field: Foo<N>,
14+
}
15+
16+
fn structp() {
17+
match todo!() {
18+
Bar::<3> {
19+
field: Foo::<3>,
20+
} => (),
21+
}
22+
}
23+
24+
struct Baz<const N: usize>(Foo<N>);
25+
26+
fn tuplestructp() {
27+
match Baz(Foo) {
28+
Baz::<3>(Foo::<3>) => (),
29+
}
30+
}
31+
32+
impl<const N: usize> Baz<N> {
33+
const ASSOC: usize = 3;
34+
}
35+
36+
fn pathp() {
37+
match 3 {
38+
Baz::<3>::ASSOC => (),
39+
_ => (),
40+
}
41+
}
42+
43+
fn main() {}

0 commit comments

Comments
 (0)