Skip to content

Commit 8c729bd

Browse files
BoxyUwUJulianKnodt
authored andcommitted
handle nested obligations in satisfied_from_param_env
1 parent 5bb1a9f commit 8c729bd

File tree

7 files changed

+126
-45
lines changed

7 files changed

+126
-45
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitor};
1818
use rustc_span::Span;
1919
use std::ops::ControlFlow;
2020

21+
use crate::traits::ObligationCtxt;
22+
2123
/// Check if a given constant can be evaluated.
2224
#[instrument(skip(infcx), level = "debug")]
2325
pub fn is_const_evaluatable<'tcx>(
@@ -71,26 +73,27 @@ pub fn is_const_evaluatable<'tcx>(
7173
// See #74595 for more details about this.
7274
let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
7375
match concrete {
74-
// If we're evaluating a generic foreign constant, under a nightly compiler while
75-
// the current crate does not enable `feature(generic_const_exprs)`, abort
76-
// compilation with a useful error.
77-
Err(_) if tcx.sess.is_nightly_build()
78-
&& let Ok(Some(ac)) = tcx.expand_abstract_consts(ct)
79-
&& let ty::ConstKind::Expr(_) = ac.kind() => {
80-
tcx.sess
81-
.struct_span_fatal(
82-
// Slightly better span than just using `span` alone
83-
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
84-
"failed to evaluate generic const expression",
85-
)
86-
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
87-
.span_suggestion_verbose(
88-
rustc_span::DUMMY_SP,
89-
"consider enabling this feature",
90-
"#![feature(generic_const_exprs)]\n",
91-
rustc_errors::Applicability::MaybeIncorrect,
92-
)
93-
.emit()
76+
// If we're evaluating a generic foreign constant, under a nightly compiler while
77+
// the current crate does not enable `feature(generic_const_exprs)`, abort
78+
// compilation with a useful error.
79+
Err(_) if tcx.sess.is_nightly_build()
80+
&& let Ok(Some(ac)) = tcx.expand_abstract_consts(ct)
81+
&& let ty::ConstKind::Expr(_) = ac.kind() =>
82+
{
83+
tcx.sess
84+
.struct_span_fatal(
85+
// Slightly better span than just using `span` alone
86+
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
87+
"failed to evaluate generic const expression",
88+
)
89+
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
90+
.span_suggestion_verbose(
91+
rustc_span::DUMMY_SP,
92+
"consider enabling this feature",
93+
"#![feature(generic_const_exprs)]\n",
94+
rustc_errors::Applicability::MaybeIncorrect,
95+
)
96+
.emit()
9497
}
9598

9699
Err(ErrorHandled::TooGeneric) => {
@@ -130,12 +133,17 @@ fn satisfied_from_param_env<'tcx>(
130133
impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
131134
type BreakTy = ();
132135
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
133-
if c.ty() == self.ct.ty()
134-
&& let Ok(_nested_obligations) = self
135-
.infcx
136-
.at(&ObligationCause::dummy(), self.param_env)
137-
.eq(c, self.ct)
138-
{
136+
if let Ok(()) = self.infcx.commit_if_ok(|_| {
137+
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
138+
if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty())
139+
&& let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct)
140+
&& ocx.select_all_or_error().is_empty()
141+
{
142+
Ok(())
143+
} else {
144+
Err(())
145+
}
146+
}) {
139147
ControlFlow::BREAK
140148
} else if let ty::ConstKind::Expr(e) = c.kind() {
141149
e.visit_with(self)

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap;
33
use rustc_data_structures::obligation_forest::ProcessResult;
44
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
55
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
6-
use rustc_hir::def::DefKind;
76
use rustc_infer::traits::ProjectionCacheKey;
87
use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation};
98
use rustc_middle::mir::interpret::ErrorHandled;
@@ -465,6 +464,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
465464
// Let's just see where this breaks :shrug:
466465
match (c1.kind(), c2.kind()) {
467466
(ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) => {
467+
// FIXME: remove
468+
use rustc_hir::def::DefKind;
468469
if tcx.def_kind(a.def.did) == DefKind::AssocConst
469470
|| tcx.def_kind(b.def.did) == DefKind::AssocConst
470471
{
@@ -477,16 +478,17 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
477478
),
478479
);
479480
}
480-
if let (Ok(Some(a)), Ok(Some(b))) = (
481-
tcx.expand_abstract_consts(c1),
482-
tcx.expand_abstract_consts(c2),
483-
) && a.ty() == b.ty() &&
484-
let Ok(new_obligations) = infcx
485-
.at(&obligation.cause, obligation.param_env)
486-
.eq(a, b) {
487-
return ProcessResult::Changed(mk_pending(
488-
new_obligations.into_obligations(),
489-
));
481+
482+
if let Ok(Some(a)) = tcx.expand_abstract_consts(c1)
483+
&& let Ok(Some(b)) = tcx.expand_abstract_consts(c2)
484+
&& a.ty() == b.ty()
485+
&& let Ok(new_obligations) = infcx
486+
.at(&obligation.cause, obligation.param_env)
487+
.eq(a, b)
488+
{
489+
return ProcessResult::Changed(mk_pending(
490+
new_obligations.into_obligations(),
491+
));
490492
}
491493
}
492494
_ => {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
3+
4+
trait Trait {
5+
const ASSOC: usize;
6+
}
7+
8+
fn foo<T: Trait, U: Trait>() where [(); U::ASSOC]:, {
9+
bar::<{ T::ASSOC }>();
10+
//~^ ERROR: unconstrained generic constant
11+
}
12+
13+
fn bar<const N: usize>() {}
14+
15+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: unconstrained generic constant
2+
--> $DIR/doesnt_unify_evaluatable.rs:9:11
3+
|
4+
LL | bar::<{ T::ASSOC }>();
5+
| ^^^^^^^^^^^^
6+
|
7+
= help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:`
8+
9+
error: aborting due to previous error
10+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// check-pass
2+
3+
#![feature(generic_const_exprs)]
4+
#![allow(incomplete_features)]
5+
6+
trait Trait {
7+
const ASSOC: usize;
8+
}
9+
10+
fn foo<T: Trait, U: Trait>() where [(); T::ASSOC]:, {
11+
bar::<{ T::ASSOC }>();
12+
}
13+
14+
fn bar<const N: usize>() -> [(); N] {
15+
[(); N]
16+
}
17+
18+
fn main() {}

src/test/ui/const-generics/issues/issue-83765.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@ impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T,
5959
assert!(DIM >= T::DIM);
6060
if !self.inbounds(index) {
6161
//~^ ERROR mismatched types
62+
//~^^ ERROR unconstrained generic constant
6263
return None;
6364
}
6465
let size = self.size();
66+
//~^ ERROR unconstrained generic constant
6567
let newindex: [usize; T::DIM] = Default::default();
6668
//~^ ERROR the trait bound
6769
self.reference.bget(newindex)

src/test/ui/const-generics/issues/issue-83765.stderr

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
1717
found constant `DIM`
1818

1919
error[E0308]: method not compatible with trait
20-
--> $DIR/issue-83765.rs:84:5
20+
--> $DIR/issue-83765.rs:86:5
2121
|
2222
LL | fn size(&self) -> [usize; DIM] {
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
@@ -26,14 +26,27 @@ LL | fn size(&self) -> [usize; DIM] {
2626
found constant `DIM`
2727

2828
error[E0308]: method not compatible with trait
29-
--> $DIR/issue-83765.rs:96:5
29+
--> $DIR/issue-83765.rs:98:5
3030
|
3131
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
3333
|
3434
= note: expected constant `Self::DIM`
3535
found constant `DIM`
3636

37+
error: unconstrained generic constant
38+
--> $DIR/issue-83765.rs:60:18
39+
|
40+
LL | if !self.inbounds(index) {
41+
| ^^^^^^^^
42+
|
43+
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
44+
note: required by a bound in `TensorSize::inbounds`
45+
--> $DIR/issue-83765.rs:16:39
46+
|
47+
LL | fn inbounds(&self, index: [usize; Self::DIM]) -> bool {
48+
| ^^^^^^^^^ required by this bound in `TensorSize::inbounds`
49+
3750
error[E0308]: mismatched types
3851
--> $DIR/issue-83765.rs:60:27
3952
|
@@ -43,8 +56,21 @@ LL | if !self.inbounds(index) {
4356
= note: expected constant `Self::DIM`
4457
found constant `DIM`
4558

59+
error: unconstrained generic constant
60+
--> $DIR/issue-83765.rs:65:25
61+
|
62+
LL | let size = self.size();
63+
| ^^^^
64+
|
65+
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
66+
note: required by a bound in `TensorSize::size`
67+
--> $DIR/issue-83765.rs:15:31
68+
|
69+
LL | fn size(&self) -> [usize; Self::DIM];
70+
| ^^^^^^^^^ required by this bound in `TensorSize::size`
71+
4672
error[E0277]: the trait bound `[usize; _]: Default` is not satisfied
47-
--> $DIR/issue-83765.rs:65:41
73+
--> $DIR/issue-83765.rs:67:41
4874
|
4975
LL | let newindex: [usize; T::DIM] = Default::default();
5076
| ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[usize; _]`
@@ -55,7 +81,7 @@ LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a
5581
| +++++++++++++++++++++++++
5682

5783
error: unconstrained generic constant
58-
--> $DIR/issue-83765.rs:86:24
84+
--> $DIR/issue-83765.rs:88:24
5985
|
6086
LL | self.reference.size()
6187
| ^^^^
@@ -68,7 +94,7 @@ LL | fn size(&self) -> [usize; Self::DIM];
6894
| ^^^^^^^^^ required by this bound in `TensorSize::size`
6995

7096
error[E0308]: mismatched types
71-
--> $DIR/issue-83765.rs:86:9
97+
--> $DIR/issue-83765.rs:88:9
7298
|
7399
LL | self.reference.size()
74100
| ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
@@ -77,7 +103,7 @@ LL | self.reference.size()
77103
found constant `Self::DIM`
78104

79105
error: unconstrained generic constant
80-
--> $DIR/issue-83765.rs:98:24
106+
--> $DIR/issue-83765.rs:100:24
81107
|
82108
LL | self.reference.bget(index).map(&self.closure)
83109
| ^^^^
@@ -90,15 +116,15 @@ LL | fn bget(&self, index: [usize; Self::DIM]) -> Option<Self::Element>;
90116
| ^^^^^^^^^ required by this bound in `Broadcastable::bget`
91117

92118
error[E0308]: mismatched types
93-
--> $DIR/issue-83765.rs:98:29
119+
--> $DIR/issue-83765.rs:100:29
94120
|
95121
LL | self.reference.bget(index).map(&self.closure)
96122
| ^^^^^ expected `Self::DIM`, found `DIM`
97123
|
98124
= note: expected constant `Self::DIM`
99125
found constant `DIM`
100126

101-
error: aborting due to 10 previous errors
127+
error: aborting due to 12 previous errors
102128

103129
Some errors have detailed explanations: E0277, E0308.
104130
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)