1
Fork 0

handle nested obligations in satisfied_from_param_env

This commit is contained in:
Boxy 2022-11-14 18:20:53 +00:00 committed by kadmin
parent 5bb1a9febc
commit 8c729bd0f3
7 changed files with 126 additions and 45 deletions

View file

@ -18,6 +18,8 @@ use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitor};
use rustc_span::Span; use rustc_span::Span;
use std::ops::ControlFlow; use std::ops::ControlFlow;
use crate::traits::ObligationCtxt;
/// Check if a given constant can be evaluated. /// Check if a given constant can be evaluated.
#[instrument(skip(infcx), level = "debug")] #[instrument(skip(infcx), level = "debug")]
pub fn is_const_evaluatable<'tcx>( pub fn is_const_evaluatable<'tcx>(
@ -76,7 +78,8 @@ pub fn is_const_evaluatable<'tcx>(
// compilation with a useful error. // compilation with a useful error.
Err(_) if tcx.sess.is_nightly_build() Err(_) if tcx.sess.is_nightly_build()
&& let Ok(Some(ac)) = tcx.expand_abstract_consts(ct) && let Ok(Some(ac)) = tcx.expand_abstract_consts(ct)
&& let ty::ConstKind::Expr(_) = ac.kind() => { && let ty::ConstKind::Expr(_) = ac.kind() =>
{
tcx.sess tcx.sess
.struct_span_fatal( .struct_span_fatal(
// Slightly better span than just using `span` alone // Slightly better span than just using `span` alone
@ -130,12 +133,17 @@ fn satisfied_from_param_env<'tcx>(
impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
type BreakTy = (); type BreakTy = ();
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if c.ty() == self.ct.ty() if let Ok(()) = self.infcx.commit_if_ok(|_| {
&& let Ok(_nested_obligations) = self let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
.infcx if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty())
.at(&ObligationCause::dummy(), self.param_env) && let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct)
.eq(c, self.ct) && ocx.select_all_or_error().is_empty()
{ {
Ok(())
} else {
Err(())
}
}) {
ControlFlow::BREAK ControlFlow::BREAK
} else if let ty::ConstKind::Expr(e) = c.kind() { } else if let ty::ConstKind::Expr(e) = c.kind() {
e.visit_with(self) e.visit_with(self)

View file

@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_hir::def::DefKind;
use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::ProjectionCacheKey;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation}; use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation};
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
@ -465,6 +464,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
// Let's just see where this breaks :shrug: // Let's just see where this breaks :shrug:
match (c1.kind(), c2.kind()) { match (c1.kind(), c2.kind()) {
(ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) => { (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) => {
// FIXME: remove
use rustc_hir::def::DefKind;
if tcx.def_kind(a.def.did) == DefKind::AssocConst if tcx.def_kind(a.def.did) == DefKind::AssocConst
|| tcx.def_kind(b.def.did) == DefKind::AssocConst || tcx.def_kind(b.def.did) == DefKind::AssocConst
{ {
@ -477,13 +478,14 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
), ),
); );
} }
if let (Ok(Some(a)), Ok(Some(b))) = (
tcx.expand_abstract_consts(c1), if let Ok(Some(a)) = tcx.expand_abstract_consts(c1)
tcx.expand_abstract_consts(c2), && let Ok(Some(b)) = tcx.expand_abstract_consts(c2)
) && a.ty() == b.ty() && && a.ty() == b.ty()
let Ok(new_obligations) = infcx && let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.eq(a, b) { .eq(a, b)
{
return ProcessResult::Changed(mk_pending( return ProcessResult::Changed(mk_pending(
new_obligations.into_obligations(), new_obligations.into_obligations(),
)); ));

View file

@ -0,0 +1,15 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
trait Trait {
const ASSOC: usize;
}
fn foo<T: Trait, U: Trait>() where [(); U::ASSOC]:, {
bar::<{ T::ASSOC }>();
//~^ ERROR: unconstrained generic constant
}
fn bar<const N: usize>() {}
fn main() {}

View file

@ -0,0 +1,10 @@
error: unconstrained generic constant
--> $DIR/doesnt_unify_evaluatable.rs:9:11
|
LL | bar::<{ T::ASSOC }>();
| ^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:`
error: aborting due to previous error

View file

@ -0,0 +1,18 @@
// check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
trait Trait {
const ASSOC: usize;
}
fn foo<T: Trait, U: Trait>() where [(); T::ASSOC]:, {
bar::<{ T::ASSOC }>();
}
fn bar<const N: usize>() -> [(); N] {
[(); N]
}
fn main() {}

View file

@ -59,9 +59,11 @@ impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T,
assert!(DIM >= T::DIM); assert!(DIM >= T::DIM);
if !self.inbounds(index) { if !self.inbounds(index) {
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~^^ ERROR unconstrained generic constant
return None; return None;
} }
let size = self.size(); let size = self.size();
//~^ ERROR unconstrained generic constant
let newindex: [usize; T::DIM] = Default::default(); let newindex: [usize; T::DIM] = Default::default();
//~^ ERROR the trait bound //~^ ERROR the trait bound
self.reference.bget(newindex) self.reference.bget(newindex)

View file

@ -17,7 +17,7 @@ LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
found constant `DIM` found constant `DIM`
error[E0308]: method not compatible with trait error[E0308]: method not compatible with trait
--> $DIR/issue-83765.rs:84:5 --> $DIR/issue-83765.rs:86:5
| |
LL | fn size(&self) -> [usize; DIM] { LL | fn size(&self) -> [usize; DIM] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
@ -26,7 +26,7 @@ LL | fn size(&self) -> [usize; DIM] {
found constant `DIM` found constant `DIM`
error[E0308]: method not compatible with trait error[E0308]: method not compatible with trait
--> $DIR/issue-83765.rs:96:5 --> $DIR/issue-83765.rs:98:5
| |
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> { LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
@ -34,6 +34,19 @@ LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
= note: expected constant `Self::DIM` = note: expected constant `Self::DIM`
found constant `DIM` found constant `DIM`
error: unconstrained generic constant
--> $DIR/issue-83765.rs:60:18
|
LL | if !self.inbounds(index) {
| ^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
note: required by a bound in `TensorSize::inbounds`
--> $DIR/issue-83765.rs:16:39
|
LL | fn inbounds(&self, index: [usize; Self::DIM]) -> bool {
| ^^^^^^^^^ required by this bound in `TensorSize::inbounds`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-83765.rs:60:27 --> $DIR/issue-83765.rs:60:27
| |
@ -43,8 +56,21 @@ LL | if !self.inbounds(index) {
= note: expected constant `Self::DIM` = note: expected constant `Self::DIM`
found constant `DIM` found constant `DIM`
error: unconstrained generic constant
--> $DIR/issue-83765.rs:65:25
|
LL | let size = self.size();
| ^^^^
|
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
note: required by a bound in `TensorSize::size`
--> $DIR/issue-83765.rs:15:31
|
LL | fn size(&self) -> [usize; Self::DIM];
| ^^^^^^^^^ required by this bound in `TensorSize::size`
error[E0277]: the trait bound `[usize; _]: Default` is not satisfied error[E0277]: the trait bound `[usize; _]: Default` is not satisfied
--> $DIR/issue-83765.rs:65:41 --> $DIR/issue-83765.rs:67:41
| |
LL | let newindex: [usize; T::DIM] = Default::default(); LL | let newindex: [usize; T::DIM] = Default::default();
| ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[usize; _]` | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[usize; _]`
@ -55,7 +81,7 @@ LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a
| +++++++++++++++++++++++++ | +++++++++++++++++++++++++
error: unconstrained generic constant error: unconstrained generic constant
--> $DIR/issue-83765.rs:86:24 --> $DIR/issue-83765.rs:88:24
| |
LL | self.reference.size() LL | self.reference.size()
| ^^^^ | ^^^^
@ -68,7 +94,7 @@ LL | fn size(&self) -> [usize; Self::DIM];
| ^^^^^^^^^ required by this bound in `TensorSize::size` | ^^^^^^^^^ required by this bound in `TensorSize::size`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-83765.rs:86:9 --> $DIR/issue-83765.rs:88:9
| |
LL | self.reference.size() LL | self.reference.size()
| ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
@ -77,7 +103,7 @@ LL | self.reference.size()
found constant `Self::DIM` found constant `Self::DIM`
error: unconstrained generic constant error: unconstrained generic constant
--> $DIR/issue-83765.rs:98:24 --> $DIR/issue-83765.rs:100:24
| |
LL | self.reference.bget(index).map(&self.closure) LL | self.reference.bget(index).map(&self.closure)
| ^^^^ | ^^^^
@ -90,7 +116,7 @@ LL | fn bget(&self, index: [usize; Self::DIM]) -> Option<Self::Element>;
| ^^^^^^^^^ required by this bound in `Broadcastable::bget` | ^^^^^^^^^ required by this bound in `Broadcastable::bget`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-83765.rs:98:29 --> $DIR/issue-83765.rs:100:29
| |
LL | self.reference.bget(index).map(&self.closure) LL | self.reference.bget(index).map(&self.closure)
| ^^^^^ expected `Self::DIM`, found `DIM` | ^^^^^ expected `Self::DIM`, found `DIM`
@ -98,7 +124,7 @@ LL | self.reference.bget(index).map(&self.closure)
= note: expected constant `Self::DIM` = note: expected constant `Self::DIM`
found constant `DIM` found constant `DIM`
error: aborting due to 10 previous errors error: aborting due to 12 previous errors
Some errors have detailed explanations: E0277, E0308. Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0277`.