Skip to content

Commit 23edfc3

Browse files
skinnyBatmati865
authored andcommitted
Assume unevaluated consts are equal to the other consts and add ConstEquate obligation. This delays
the need to evaluate consts eagerly and therefore gets around const eval query cycles.
1 parent 11f6096 commit 23edfc3

File tree

37 files changed

+369
-108
lines changed

37 files changed

+369
-108
lines changed

src/librustc_infer/infer/canonical/query_response.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_middle::arena::ArenaAllocatable;
2525
use rustc_middle::ty::fold::TypeFoldable;
2626
use rustc_middle::ty::relate::TypeRelation;
2727
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
28-
use rustc_middle::ty::{self, BoundVar, Ty, TyCtxt};
28+
use rustc_middle::ty::{self, BoundVar, Const, Ty, TyCtxt};
2929
use std::fmt::Debug;
3030

3131
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
@@ -675,6 +675,10 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
675675
bug!("should never be invoked with eager normalization")
676676
}
677677

678+
fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {
679+
unimplemented!()
680+
}
681+
678682
fn normalization() -> NormalizationStrategy {
679683
NormalizationStrategy::Eager
680684
}

src/librustc_infer/infer/combine.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
164164
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
165165
return self.unify_const_variable(!a_is_expected, vid, a);
166166
}
167-
168167
_ => {}
169168
}
170169

@@ -375,6 +374,20 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
375374
debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf);
376375
Ok(Generalization { ty, needs_wf })
377376
}
377+
378+
pub fn add_const_equate_obligation(
379+
&mut self,
380+
a_is_expected: bool,
381+
a: &'tcx ty::Const<'tcx>,
382+
b: &'tcx ty::Const<'tcx>,
383+
) {
384+
let predicate = if a_is_expected {
385+
ty::Predicate::ConstEquate(a, b)
386+
} else {
387+
ty::Predicate::ConstEquate(b, a)
388+
};
389+
self.obligations.push(Obligation::new(self.trace.cause.clone(), self.param_env, predicate));
390+
}
378391
}
379392

380393
struct Generalizer<'cx, 'tcx> {
@@ -635,6 +648,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
635648
}
636649
}
637650
}
651+
ty::ConstKind::Unevaluated(..) => Ok(c),
638652
_ => relate::super_relate_consts(self, c, c),
639653
}
640654
}

src/librustc_infer/infer/equate.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::Subtype;
44
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
55
use rustc_middle::ty::subst::SubstsRef;
66
use rustc_middle::ty::TyVar;
7-
use rustc_middle::ty::{self, Ty, TyCtxt};
7+
use rustc_middle::ty::{self, ConstKind, Ty, TyCtxt};
88

99
use rustc_hir::def_id::DefId;
1010

@@ -119,7 +119,17 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
119119
a: &'tcx ty::Const<'tcx>,
120120
b: &'tcx ty::Const<'tcx>,
121121
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
122-
self.fields.infcx.super_combine_consts(self, a, b)
122+
match (a.val, b.val) {
123+
(ConstKind::Unevaluated(..), _) => {
124+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
125+
Ok(b)
126+
}
127+
(_, ConstKind::Unevaluated(..)) => {
128+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
129+
Ok(a)
130+
}
131+
_ => self.fields.infcx.super_combine_consts(self, a, b),
132+
}
123133
}
124134

125135
fn binders<T>(

src/librustc_infer/infer/glb.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,17 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
7979
a: &'tcx ty::Const<'tcx>,
8080
b: &'tcx ty::Const<'tcx>,
8181
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
82-
self.fields.infcx.super_combine_consts(self, a, b)
82+
match (a.val, b.val) {
83+
(ty::ConstKind::Unevaluated(..), _) => {
84+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
85+
Ok(b)
86+
}
87+
(_, ty::ConstKind::Unevaluated(..)) => {
88+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
89+
Ok(a)
90+
}
91+
_ => self.fields.infcx.super_combine_consts(self, a, b),
92+
}
8393
}
8494

8595
fn binders<T>(

src/librustc_infer/infer/lub.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,17 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
7979
a: &'tcx ty::Const<'tcx>,
8080
b: &'tcx ty::Const<'tcx>,
8181
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
82-
self.fields.infcx.super_combine_consts(self, a, b)
82+
match (a.val, b.val) {
83+
(ty::ConstKind::Unevaluated(..), _) => {
84+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
85+
Ok(b)
86+
}
87+
(_, ty::ConstKind::Unevaluated(..)) => {
88+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
89+
Ok(a)
90+
}
91+
_ => self.fields.infcx.super_combine_consts(self, a, b),
92+
}
8393
}
8494

8595
fn binders<T>(

src/librustc_infer/infer/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14521452
self.report_and_explain_type_error(trace, &err)
14531453
}
14541454

1455+
pub fn report_mismatched_consts(
1456+
&self,
1457+
cause: &ObligationCause<'tcx>,
1458+
expected: &'tcx ty::Const<'tcx>,
1459+
actual: &'tcx ty::Const<'tcx>,
1460+
err: TypeError<'tcx>,
1461+
) -> DiagnosticBuilder<'tcx> {
1462+
let trace = TypeTrace::consts(cause, true, expected, actual);
1463+
self.report_and_explain_type_error(trace, &err)
1464+
}
1465+
14551466
pub fn replace_bound_vars_with_fresh_vars<T>(
14561467
&self,
14571468
span: Span,
@@ -1738,6 +1749,15 @@ impl<'tcx> TypeTrace<'tcx> {
17381749
TypeTrace { cause: cause.clone(), values: Types(ExpectedFound::new(a_is_expected, a, b)) }
17391750
}
17401751

1752+
pub fn consts(
1753+
cause: &ObligationCause<'tcx>,
1754+
a_is_expected: bool,
1755+
a: &'tcx ty::Const<'tcx>,
1756+
b: &'tcx ty::Const<'tcx>,
1757+
) -> TypeTrace<'tcx> {
1758+
TypeTrace { cause: cause.clone(), values: Consts(ExpectedFound::new(a_is_expected, a, b)) }
1759+
}
1760+
17411761
pub fn dummy(tcx: TyCtxt<'tcx>) -> TypeTrace<'tcx> {
17421762
TypeTrace {
17431763
cause: ObligationCause::dummy(),

src/librustc_infer/infer/nll_relate/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ pub trait TypeRelatingDelegate<'tcx> {
8282
/// be related. Used for lazy normalization.
8383
fn push_domain_goal(&mut self, domain_goal: DomainGoal<'tcx>);
8484

85+
fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>);
86+
8587
/// Creates a new universe index. Used when instantiating placeholders.
8688
fn create_next_universe(&mut self) -> ty::UniverseIndex;
8789

@@ -603,8 +605,16 @@ where
603605
b = self.infcx.shallow_resolve(b);
604606
}
605607

606-
match b.val {
607-
ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
608+
match (a.val, b.val) {
609+
(ty::ConstKind::Unevaluated(..), _) => {
610+
self.delegate.const_equate(a, b);
611+
Ok(b)
612+
}
613+
(_, ty::ConstKind::Unevaluated(..)) => {
614+
self.delegate.const_equate(a, b);
615+
Ok(a)
616+
}
617+
(_, ty::ConstKind::Infer(InferConst::Var(_))) if D::forbid_inference_vars() => {
608618
// Forbid inference variables in the RHS.
609619
bug!("unexpected inference var {:?}", b)
610620
}
@@ -985,6 +995,7 @@ where
985995
}
986996
}
987997
}
998+
ty::ConstKind::Unevaluated(..) => Ok(a),
988999
_ => relate::super_relate_consts(self, a, a),
9891000
}
9901001
}

src/librustc_infer/infer/outlives/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ pub fn explicit_outlives_bounds<'tcx>(
1919
| ty::Predicate::ObjectSafe(..)
2020
| ty::Predicate::ClosureKind(..)
2121
| ty::Predicate::TypeOutlives(..)
22-
| ty::Predicate::ConstEvaluatable(..) => None,
22+
| ty::Predicate::ConstEvaluatable(..)
23+
| ty::Predicate::ConstEquate(..) => None,
2324
ty::Predicate::RegionOutlives(ref data) => data
2425
.no_bound_vars()
2526
.map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),

src/librustc_infer/infer/sub.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,17 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
155155
a: &'tcx ty::Const<'tcx>,
156156
b: &'tcx ty::Const<'tcx>,
157157
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
158-
self.fields.infcx.super_combine_consts(self, a, b)
158+
match (a.val, b.val) {
159+
(ty::ConstKind::Unevaluated(..), _) => {
160+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
161+
Ok(b)
162+
}
163+
(_, ty::ConstKind::Unevaluated(..)) => {
164+
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
165+
Ok(a)
166+
}
167+
_ => self.fields.infcx.super_combine_consts(self, a, b),
168+
}
159169
}
160170

161171
fn binders<T>(

src/librustc_infer/traits/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub mod util;
1010

1111
use rustc_hir as hir;
1212
use rustc_middle::ty::error::{ExpectedFound, TypeError};
13-
use rustc_middle::ty::{self, Ty};
13+
use rustc_middle::ty::{self, Const, Ty};
1414
use rustc_span::Span;
1515

1616
pub use self::FulfillmentErrorCode::*;
@@ -80,6 +80,7 @@ pub enum FulfillmentErrorCode<'tcx> {
8080
CodeSelectionError(SelectionError<'tcx>),
8181
CodeProjectionError(MismatchedProjectionTypes<'tcx>),
8282
CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
83+
CodeConstEquateError(ExpectedFound<&'tcx Const<'tcx>>, TypeError<'tcx>),
8384
CodeAmbiguity,
8485
}
8586

src/librustc_infer/traits/structural_impls.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
4141
super::CodeSubtypeError(ref a, ref b) => {
4242
write!(f, "CodeSubtypeError({:?}, {:?})", a, b)
4343
}
44+
super::CodeConstEquateError(ref a, ref b) => {
45+
write!(f, "CodeConstEquateError({:?}, {:?})", a, b)
46+
}
4447
super::CodeAmbiguity => write!(f, "Ambiguity"),
4548
}
4649
}

src/librustc_infer/traits/util.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub fn anonymize_predicate<'tcx>(
4040
ty::Predicate::ConstEvaluatable(def_id, substs) => {
4141
ty::Predicate::ConstEvaluatable(def_id, substs)
4242
}
43+
44+
ty::Predicate::ConstEquate(c1, c2) => ty::Predicate::ConstEquate(c1, c2),
4345
}
4446
}
4547

@@ -164,6 +166,10 @@ impl Elaborator<'tcx> {
164166
// Currently, we do not elaborate const-evaluatable
165167
// predicates.
166168
}
169+
ty::Predicate::ConstEquate(..) => {
170+
// Currently, we do not elaborate const-equate
171+
// predicates.
172+
}
167173
ty::Predicate::RegionOutlives(..) => {
168174
// Nothing to elaborate from `'a: 'b`.
169175
}

src/librustc_lint/builtin.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
12201220
ObjectSafe(..) |
12211221
ClosureKind(..) |
12221222
Subtype(..) |
1223-
ConstEvaluatable(..) => continue,
1223+
ConstEvaluatable(..) |
1224+
ConstEquate(..) => continue,
12241225
};
12251226
if predicate.is_global() {
12261227
cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {

src/librustc_middle/ty/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,9 @@ pub enum Predicate<'tcx> {
12031203

12041204
/// Constant initializer must evaluate successfully.
12051205
ConstEvaluatable(DefId, SubstsRef<'tcx>),
1206+
1207+
/// Constants must be equal. The first component is the const that is expected.
1208+
ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
12061209
}
12071210

12081211
/// The crate outlives map is computed during typeck and contains the
@@ -1321,6 +1324,9 @@ impl<'tcx> Predicate<'tcx> {
13211324
Predicate::ConstEvaluatable(def_id, const_substs) => {
13221325
Predicate::ConstEvaluatable(def_id, const_substs.subst(tcx, substs))
13231326
}
1327+
Predicate::ConstEquate(c1, c2) => {
1328+
Predicate::ConstEquate(c1.subst(tcx, substs), c2.subst(tcx, substs))
1329+
}
13241330
}
13251331
}
13261332
}
@@ -1498,7 +1504,8 @@ impl<'tcx> Predicate<'tcx> {
14981504
| Predicate::ObjectSafe(..)
14991505
| Predicate::ClosureKind(..)
15001506
| Predicate::TypeOutlives(..)
1501-
| Predicate::ConstEvaluatable(..) => None,
1507+
| Predicate::ConstEvaluatable(..)
1508+
| Predicate::ConstEquate(..) => None,
15021509
}
15031510
}
15041511

@@ -1512,7 +1519,8 @@ impl<'tcx> Predicate<'tcx> {
15121519
| Predicate::WellFormed(..)
15131520
| Predicate::ObjectSafe(..)
15141521
| Predicate::ClosureKind(..)
1515-
| Predicate::ConstEvaluatable(..) => None,
1522+
| Predicate::ConstEvaluatable(..)
1523+
| Predicate::ConstEquate(..) => None,
15161524
}
15171525
}
15181526
}

src/librustc_middle/ty/outlives.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
6262
// in the `subtys` iterator (e.g., when encountering a
6363
// projection).
6464
match ty.kind {
65+
ty::Array(element, _) => {
66+
// Don't look into the len const as it doesn't affect regions
67+
compute_components(tcx, element, out);
68+
}
69+
6570
ty::Closure(_, ref substs) => {
6671
for upvar_ty in substs.as_closure().upvar_tys() {
6772
compute_components(tcx, upvar_ty, out);
@@ -139,7 +144,6 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
139144
ty::Opaque(..) | // OutlivesNominalType (ish)
140145
ty::Foreign(..) | // OutlivesNominalType
141146
ty::Str | // OutlivesScalar (ish)
142-
ty::Array(..) | // ...
143147
ty::Slice(..) | // ...
144148
ty::RawPtr(..) | // ...
145149
ty::Ref(..) | // OutlivesReference

src/librustc_middle/ty/print/pretty.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,13 @@ define_print_and_forward_display! {
20442044
print_value_path(def_id, substs),
20452045
write("` can be evaluated"))
20462046
}
2047+
ty::Predicate::ConstEquate(c1, c2) => {
2048+
p!(write("the constant `"),
2049+
print(c1),
2050+
write("` equals `"),
2051+
print(c2),
2052+
write("`"))
2053+
}
20472054
}
20482055
}
20492056

0 commit comments

Comments
 (0)