Rollup merge of #91570 - nbdd0121:const_typeck, r=oli-obk
Evaluate inline const pat early and report error if too generic Fix #90150 ````@rustbot```` label: T-compiler F-inline_const
This commit is contained in:
commit
67c58327fc
@ -533,43 +533,64 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts inline const patterns.
|
||||
fn lower_inline_const(
|
||||
&mut self,
|
||||
anon_const: &'tcx hir::AnonConst,
|
||||
id: hir::HirId,
|
||||
span: Span,
|
||||
) -> PatKind<'tcx> {
|
||||
let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
|
||||
let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
|
||||
|
||||
// Evaluate early like we do in `lower_path`.
|
||||
let value = value.eval(self.tcx, self.param_env);
|
||||
|
||||
match value.val {
|
||||
ConstKind::Param(_) => {
|
||||
self.errors.push(PatternError::ConstParamInPattern(span));
|
||||
return PatKind::Wild;
|
||||
}
|
||||
ConstKind::Unevaluated(_) => {
|
||||
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
|
||||
self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
|
||||
return PatKind::Wild;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
*self.const_to_pat(value, id, span, false).kind
|
||||
}
|
||||
|
||||
/// Converts literals, paths and negation of literals to patterns.
|
||||
/// The special case for negation exists to allow things like `-128_i8`
|
||||
/// which would overflow if we tried to evaluate `128_i8` and then negate
|
||||
/// afterwards.
|
||||
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
|
||||
if let hir::ExprKind::Path(ref qpath) = expr.kind {
|
||||
*self.lower_path(qpath, expr.hir_id, expr.span).kind
|
||||
} else {
|
||||
let (lit, neg) = match expr.kind {
|
||||
hir::ExprKind::ConstBlock(ref anon_const) => {
|
||||
let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
|
||||
let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
|
||||
if matches!(value.val, ConstKind::Param(_)) {
|
||||
let span = self.tcx.hir().span(anon_const.hir_id);
|
||||
self.errors.push(PatternError::ConstParamInPattern(span));
|
||||
return PatKind::Wild;
|
||||
}
|
||||
return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind;
|
||||
}
|
||||
hir::ExprKind::Lit(ref lit) => (lit, false),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
|
||||
let lit = match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => lit,
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
(lit, true)
|
||||
}
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
|
||||
let lit_input =
|
||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind,
|
||||
Err(LitToConstError::Reported) => PatKind::Wild,
|
||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
||||
let (lit, neg) = match expr.kind {
|
||||
hir::ExprKind::Path(ref qpath) => {
|
||||
return *self.lower_path(qpath, expr.hir_id, expr.span).kind;
|
||||
}
|
||||
hir::ExprKind::ConstBlock(ref anon_const) => {
|
||||
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
|
||||
}
|
||||
hir::ExprKind::Lit(ref lit) => (lit, false),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
|
||||
let lit = match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => lit,
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
(lit, true)
|
||||
}
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
|
||||
let lit_input =
|
||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind,
|
||||
Err(LitToConstError::Reported) => PatKind::Wild,
|
||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,31 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(inline_const_pat)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
|
||||
|
||||
fn foo<const V: usize>() {
|
||||
match 0 {
|
||||
const { V } => {},
|
||||
//~^ ERROR const parameters cannot be referenced in patterns [E0158]
|
||||
_ => {},
|
||||
}
|
||||
match 0 {
|
||||
const { V } => {},
|
||||
//~^ ERROR const parameters cannot be referenced in patterns [E0158]
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
const fn f(x: usize) -> usize {
|
||||
x + 1
|
||||
}
|
||||
|
||||
fn bar<const V: usize>() where [(); f(V)]: {
|
||||
match 0 {
|
||||
const { f(V) } => {},
|
||||
//~^ ERROR constant pattern depends on a generic parameter
|
||||
//~| ERROR constant pattern depends on a generic parameter
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo::<1>();
|
||||
bar::<1>();
|
||||
}
|
||||
|
@ -1,9 +1,21 @@
|
||||
error[E0158]: const parameters cannot be referenced in patterns
|
||||
--> $DIR/const-match-pat-generic.rs:8:11
|
||||
--> $DIR/const-match-pat-generic.rs:9:9
|
||||
|
|
||||
LL | const { V } => {},
|
||||
| ^^^^^
|
||||
LL | const { V } => {},
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: constant pattern depends on a generic parameter
|
||||
--> $DIR/const-match-pat-generic.rs:21:9
|
||||
|
|
||||
LL | const { f(V) } => {},
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: constant pattern depends on a generic parameter
|
||||
--> $DIR/const-match-pat-generic.rs:21:9
|
||||
|
|
||||
LL | const { f(V) } => {},
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
||||
|
Loading…
Reference in New Issue
Block a user