Skip to content

Commit d030ece

Browse files
committed
Only rewrite valtree-constants to patterns and keep other constants opaque
1 parent 7a2f47c commit d030ece

File tree

11 files changed

+236
-175
lines changed

11 files changed

+236
-175
lines changed

compiler/rustc_middle/src/mir/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2487,8 +2487,8 @@ impl<'tcx> ConstantKind<'tcx> {
24872487
if let Some(lit_input) = lit_input {
24882488
// If an error occurred, ignore that it's a literal and leave reporting the error up to
24892489
// mir.
2490-
match tcx.at(expr.span).lit_to_mir_constant(lit_input) {
2491-
Ok(c) => return c,
2490+
match tcx.at(expr.span).lit_to_const(lit_input) {
2491+
Ok(c) => return Self::Ty(c),
24922492
Err(_) => {}
24932493
}
24942494
}

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

+164-124
Large diffs are not rendered by default.

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

+13-14
Original file line numberDiff line numberDiff line change
@@ -141,22 +141,21 @@ impl IntRange {
141141
) -> Option<IntRange> {
142142
let ty = value.ty();
143143
if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, ty) {
144-
let val = if let mir::ConstantKind::Val(ConstValue::Scalar(scalar), _) = value {
145-
// For this specific pattern we can skip a lot of effort and go
146-
// straight to the result, after doing a bit of checking. (We
147-
// could remove this branch and just fall through, which
148-
// is more general but much slower.)
149-
scalar.to_bits_or_ptr_internal(target_size).unwrap().left()?
150-
} else {
151-
if let mir::ConstantKind::Ty(c) = value
152-
&& let ty::ConstKind::Value(_) = c.kind()
153-
{
154-
bug!("encountered ConstValue in mir::ConstantKind::Ty, whereas this is expected to be in ConstantKind::Val");
144+
let val = match value {
145+
mir::ConstantKind::Val(ConstValue::Scalar(scalar), _) => {
146+
// For this specific pattern we can skip a lot of effort and go
147+
// straight to the result, after doing a bit of checking. (We
148+
// could remove this branch and just fall through, which
149+
// is more general but much slower.)
150+
scalar.to_bits_or_ptr_internal(target_size).unwrap().left()
155151
}
156-
152+
mir::ConstantKind::Ty(c) if let ty::ConstKind::Value(valtree) = c.kind() => {
153+
valtree.unwrap_leaf().to_bits(target_size).ok()
154+
},
157155
// This is a more general form of the previous case.
158-
value.try_eval_bits(tcx, param_env, ty)?
159-
};
156+
_ => value.try_eval_bits(tcx, param_env, ty),
157+
}?;
158+
160159
let val = val ^ bias;
161160
Some(IntRange { range: val..=val, bias })
162161
} else {

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

+47-18
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
1818
use rustc_hir::RangeEnd;
1919
use rustc_index::Idx;
2020
use rustc_middle::mir::interpret::{
21-
ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar,
21+
ConstValue, ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar,
2222
};
2323
use rustc_middle::mir::{self, UserTypeProjection};
2424
use rustc_middle::mir::{BorrowKind, Mutability};
@@ -518,16 +518,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
518518
}
519519
};
520520

521-
// `mir_const_qualif` must be called with the `DefId` of the item where the const is
522-
// defined, not where it is declared. The difference is significant for associated
523-
// constants.
524-
let mir_structural_match_violation = self.tcx.mir_const_qualif(instance.def_id()).custom_eq;
525-
debug!("mir_structural_match_violation({:?}) -> {}", qpath, mir_structural_match_violation);
526-
527-
match self.tcx.const_eval_instance(param_env_reveal_all, instance, Some(span)) {
528-
Ok(literal) => {
529-
let const_ = mir::ConstantKind::Val(literal, ty);
530-
let pattern = self.const_to_pat(const_, id, span, mir_structural_match_violation);
521+
let cid = GlobalId { instance, promoted: None };
522+
// Prefer
523+
let const_value = self
524+
.tcx
525+
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span))
526+
.and_then(|val| match val {
527+
Some(valtree) => Ok(mir::ConstantKind::Ty(self.tcx.mk_const(valtree, ty))),
528+
None => self
529+
.tcx
530+
.const_eval_global_id(param_env_reveal_all, cid, Some(span))
531+
.map(|lit| mir::ConstantKind::Val(lit, ty)),
532+
});
533+
534+
match const_value {
535+
Ok(const_) => {
536+
let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id()));
531537

532538
if !is_associated_const {
533539
return pattern;
@@ -578,9 +584,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
578584
span: Span,
579585
) -> PatKind<'tcx> {
580586
let value = mir::ConstantKind::from_inline_const(self.tcx, anon_const.def_id);
581-
582-
// Evaluate early like we do in `lower_path`.
583-
let value = value.eval(self.tcx, self.param_env);
587+
let value = match value {
588+
mir::ConstantKind::Ty(_) => value,
589+
// Evaluate early like we do in `lower_path`.
590+
mir::ConstantKind::Unevaluated(ct, ty) => {
591+
let ct = ty::UnevaluatedConst { def: ct.def, substs: ct.substs };
592+
if let Ok(Some(valtree)) =
593+
self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
594+
{
595+
mir::ConstantKind::Ty(self.tcx.mk_const(valtree, ty))
596+
} else {
597+
value.eval(self.tcx, self.param_env)
598+
}
599+
}
600+
mir::ConstantKind::Val(_, _) => unreachable!(),
601+
};
584602

585603
match value {
586604
mir::ConstantKind::Ty(c) => match c.kind() {
@@ -591,15 +609,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
591609
ConstKind::Error(_) => {
592610
return PatKind::Wild;
593611
}
594-
_ => bug!("Expected ConstKind::Param"),
612+
_ => {}
595613
},
596-
mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
614+
mir::ConstantKind::Val(_, _) => {}
597615
mir::ConstantKind::Unevaluated(..) => {
598616
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
599617
self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
600618
return PatKind::Wild;
601619
}
602620
}
621+
622+
self.const_to_pat(value, id, span, None).kind
603623
}
604624

605625
/// Converts literals, paths and negation of literals to patterns.
@@ -626,8 +646,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
626646

627647
let lit_input =
628648
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
629-
match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) {
630-
Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
649+
match self
650+
.tcx
651+
.at(expr.span)
652+
.lit_to_const(lit_input)
653+
.map(mir::ConstantKind::Ty)
654+
.or_else(|_| self.tcx.at(expr.span).lit_to_mir_constant(lit_input))
655+
{
656+
Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, None).kind,
631657
Err(LitToConstError::Reported(_)) => PatKind::Wild,
632658
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
633659
}
@@ -806,6 +832,9 @@ pub(crate) fn compare_const_vals<'tcx>(
806832
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(a)), _a_ty),
807833
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(b)), _b_ty),
808834
) => return Some(a.cmp(&b)),
835+
(mir::ConstantKind::Ty(a), mir::ConstantKind::Ty(b)) => {
836+
return Some(a.kind().cmp(&b.kind()));
837+
}
809838
_ => {}
810839
},
811840
}

compiler/rustc_mir_transform/src/required_consts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
1717
let literal = constant.literal;
1818
match literal {
1919
ConstantKind::Ty(c) => match c.kind() {
20-
ConstKind::Param(_) | ConstKind::Error(_) => {}
21-
_ => bug!("only ConstKind::Param should be encountered here, got {:#?}", c),
20+
ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {}
21+
_ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c),
2222
},
2323
ConstantKind::Unevaluated(..) => self.required_consts.push(*constant),
2424
ConstantKind::Val(..) => {}

tests/incremental/issue-101518.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,20 @@
1-
// revisions: cfail1
2-
// should-ice
3-
// error-pattern: forcing query
4-
// known-bug: #101518
1+
// revisions: cpass
52

63
#[derive(PartialEq, Eq)]
74
struct Id<'a> {
85
ns: &'a str,
96
}
107
fn visit_struct() {
118
let id = Id { ns: "random1" };
12-
const FLAG: Id<'static> = Id {
13-
ns: "needs_to_be_the_same",
14-
};
9+
const FLAG: Id<'static> = Id { ns: "needs_to_be_the_same" };
1510
match id {
1611
FLAG => {}
1712
_ => {}
1813
}
1914
}
2015
fn visit_struct2() {
2116
let id = Id { ns: "random2" };
22-
const FLAG: Id<'static> = Id {
23-
ns: "needs_to_be_the_same",
24-
};
17+
const FLAG: Id<'static> = Id { ns: "needs_to_be_the_same" };
2518
match id {
2619
FLAG => {}
2720
_ => {}

tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn foo(_1: Option<String>) -> i32 {
3535
// + literal: Const { ty: for<'a, 'b> fn(&'a str, &'b str) -> bool {<str as PartialEq>::eq}, val: Value(<ZST>) }
3636
// mir::Constant
3737
// + span: $DIR/string.rs:9:14: 9:17
38-
// + literal: Const { ty: &str, val: Value(Slice(..)) }
38+
// + literal: Const { ty: &str, val: Value(ValTree::Branch(..)) }
3939
}
4040

4141
bb3: {

tests/ui/match/issue-70972-dyn-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ fn main() {
44
let a: &dyn Send = &7u32;
55
match a {
66
F => panic!(),
7-
//~^ ERROR `&dyn Send` cannot be used in patterns
7+
//~^ ERROR `dyn Send` cannot be used in patterns
88
_ => {}
99
}
1010
}

tests/ui/match/issue-70972-dyn-trait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `&dyn Send` cannot be used in patterns
1+
error: `dyn Send` cannot be used in patterns
22
--> $DIR/issue-70972-dyn-trait.rs:6:9
33
|
44
LL | F => panic!(),

tests/ui/pattern/issue-72565.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ const F: &'static dyn PartialEq<u32> = &7u32;
33
fn main() {
44
let a: &dyn PartialEq<u32> = &7u32;
55
match a {
6-
F => panic!(), //~ ERROR: `&dyn PartialEq<u32>` cannot be used in patterns
6+
F => panic!(), //~ ERROR: `dyn PartialEq<u32>` cannot be used in patterns
77
}
88
}

tests/ui/pattern/issue-72565.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `&dyn PartialEq<u32>` cannot be used in patterns
1+
error: `dyn PartialEq<u32>` cannot be used in patterns
22
--> $DIR/issue-72565.rs:6:9
33
|
44
LL | F => panic!(),

0 commit comments

Comments
 (0)