Skip to content

Commit 36fc307

Browse files
authored
Rollup merge of rust-lang#91570 - nbdd0121:const_typeck, r=oli-obk
Evaluate inline const pat early and report error if too generic Fix rust-lang#90150 ```@rustbot``` label: T-compiler F-inline_const
2 parents 7752498 + 2a95958 commit 36fc307

File tree

3 files changed

+88
-40
lines changed

3 files changed

+88
-40
lines changed

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+52-31
Original file line numberDiff line numberDiff line change
@@ -533,43 +533,64 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
533533
}
534534
}
535535

536+
/// Converts inline const patterns.
537+
fn lower_inline_const(
538+
&mut self,
539+
anon_const: &'tcx hir::AnonConst,
540+
id: hir::HirId,
541+
span: Span,
542+
) -> PatKind<'tcx> {
543+
let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
544+
let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
545+
546+
// Evaluate early like we do in `lower_path`.
547+
let value = value.eval(self.tcx, self.param_env);
548+
549+
match value.val {
550+
ConstKind::Param(_) => {
551+
self.errors.push(PatternError::ConstParamInPattern(span));
552+
return PatKind::Wild;
553+
}
554+
ConstKind::Unevaluated(_) => {
555+
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
556+
self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
557+
return PatKind::Wild;
558+
}
559+
_ => (),
560+
}
561+
562+
*self.const_to_pat(value, id, span, false).kind
563+
}
564+
536565
/// Converts literals, paths and negation of literals to patterns.
537566
/// The special case for negation exists to allow things like `-128_i8`
538567
/// which would overflow if we tried to evaluate `128_i8` and then negate
539568
/// afterwards.
540569
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
541-
if let hir::ExprKind::Path(ref qpath) = expr.kind {
542-
*self.lower_path(qpath, expr.hir_id, expr.span).kind
543-
} else {
544-
let (lit, neg) = match expr.kind {
545-
hir::ExprKind::ConstBlock(ref anon_const) => {
546-
let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
547-
let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
548-
if matches!(value.val, ConstKind::Param(_)) {
549-
let span = self.tcx.hir().span(anon_const.hir_id);
550-
self.errors.push(PatternError::ConstParamInPattern(span));
551-
return PatKind::Wild;
552-
}
553-
return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind;
554-
}
555-
hir::ExprKind::Lit(ref lit) => (lit, false),
556-
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
557-
let lit = match expr.kind {
558-
hir::ExprKind::Lit(ref lit) => lit,
559-
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
560-
};
561-
(lit, true)
562-
}
563-
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
564-
};
565-
566-
let lit_input =
567-
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
568-
match self.tcx.at(expr.span).lit_to_const(lit_input) {
569-
Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind,
570-
Err(LitToConstError::Reported) => PatKind::Wild,
571-
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
570+
let (lit, neg) = match expr.kind {
571+
hir::ExprKind::Path(ref qpath) => {
572+
return *self.lower_path(qpath, expr.hir_id, expr.span).kind;
573+
}
574+
hir::ExprKind::ConstBlock(ref anon_const) => {
575+
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
576+
}
577+
hir::ExprKind::Lit(ref lit) => (lit, false),
578+
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
579+
let lit = match expr.kind {
580+
hir::ExprKind::Lit(ref lit) => lit,
581+
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
582+
};
583+
(lit, true)
572584
}
585+
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
586+
};
587+
588+
let lit_input =
589+
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
590+
match self.tcx.at(expr.span).lit_to_const(lit_input) {
591+
Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind,
592+
Err(LitToConstError::Reported) => PatKind::Wild,
593+
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
573594
}
574595
}
575596
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
11
#![allow(incomplete_features)]
22
#![feature(inline_const_pat)]
3+
#![feature(generic_const_exprs)]
34

45
// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
56

67
fn foo<const V: usize>() {
7-
match 0 {
8-
const { V } => {},
9-
//~^ ERROR const parameters cannot be referenced in patterns [E0158]
10-
_ => {},
11-
}
8+
match 0 {
9+
const { V } => {},
10+
//~^ ERROR const parameters cannot be referenced in patterns [E0158]
11+
_ => {},
12+
}
13+
}
14+
15+
const fn f(x: usize) -> usize {
16+
x + 1
17+
}
18+
19+
fn bar<const V: usize>() where [(); f(V)]: {
20+
match 0 {
21+
const { f(V) } => {},
22+
//~^ ERROR constant pattern depends on a generic parameter
23+
//~| ERROR constant pattern depends on a generic parameter
24+
_ => {},
25+
}
1226
}
1327

1428
fn main() {
1529
foo::<1>();
30+
bar::<1>();
1631
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
error[E0158]: const parameters cannot be referenced in patterns
2-
--> $DIR/const-match-pat-generic.rs:8:11
2+
--> $DIR/const-match-pat-generic.rs:9:9
33
|
4-
LL | const { V } => {},
5-
| ^^^^^
4+
LL | const { V } => {},
5+
| ^^^^^^^^^^^
66

7-
error: aborting due to previous error
7+
error: constant pattern depends on a generic parameter
8+
--> $DIR/const-match-pat-generic.rs:21:9
9+
|
10+
LL | const { f(V) } => {},
11+
| ^^^^^^^^^^^^^^
12+
13+
error: constant pattern depends on a generic parameter
14+
--> $DIR/const-match-pat-generic.rs:21:9
15+
|
16+
LL | const { f(V) } => {},
17+
| ^^^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
820

921
For more information about this error, try `rustc --explain E0158`.

0 commit comments

Comments
 (0)