Rollup merge of #65696 - varkor:nll-chalk-const-generics-issue, r=eddyb
Fix an issue with const inference variables sticking around under Chalk + NLL Fixes https://github.com/rust-lang/rust/issues/65675. Fixes https://github.com/rust-lang/rust/issues/62579. r? @eddyb cc @LukasKalbertodt @skinny121
This commit is contained in:
commit
b2b35797d0
@ -494,7 +494,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
if sub_vid == self.for_vid_sub_root {
|
||||
// If sub-roots are equal, then `for_vid` and
|
||||
// `vid` are related via subtyping.
|
||||
return Err(TypeError::CyclicTy(self.root_ty));
|
||||
Err(TypeError::CyclicTy(self.root_ty))
|
||||
} else {
|
||||
match variables.probe(vid) {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
@ -527,7 +527,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
let u = self.tcx().mk_ty_var(new_var_id);
|
||||
debug!("generalize: replacing original vid={:?} with new={:?}",
|
||||
vid, u);
|
||||
return Ok(u);
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -602,19 +602,26 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
match c {
|
||||
ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
|
||||
match c.val {
|
||||
ConstValue::Infer(InferConst::Var(vid)) => {
|
||||
let mut variable_table = self.infcx.const_unification_table.borrow_mut();
|
||||
match variable_table.probe_value(*vid).val.known() {
|
||||
Some(u) => {
|
||||
self.relate(&u, &u)
|
||||
let var_value = variable_table.probe_value(vid);
|
||||
match var_value.val {
|
||||
ConstVariableValue::Known { value: u } => self.relate(&u, &u),
|
||||
ConstVariableValue::Unknown { universe } => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
Ok(c)
|
||||
} else {
|
||||
let new_var_id = variable_table.new_key(ConstVarValue {
|
||||
origin: var_value.origin,
|
||||
val: ConstVariableValue::Unknown { universe: self.for_universe },
|
||||
});
|
||||
Ok(self.tcx().mk_const_var(new_var_id, c.ty))
|
||||
}
|
||||
}
|
||||
None => Ok(c),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
relate::super_relate_consts(self, c, c)
|
||||
}
|
||||
_ => relate::super_relate_consts(self, c, c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ use crate::ty::error::TypeError;
|
||||
use crate::ty::fold::{TypeFoldable, TypeVisitor};
|
||||
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use crate::ty::subst::GenericArg;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::{self, Ty, TyCtxt, InferConst};
|
||||
use crate::infer::{ConstVariableValue, ConstVarValue};
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use std::fmt::Debug;
|
||||
@ -324,7 +325,7 @@ where
|
||||
let vid = pair.vid();
|
||||
let value_ty = pair.value_ty();
|
||||
|
||||
// FIXME -- this logic assumes invariance, but that is wrong.
|
||||
// FIXME(invariance) -- this logic assumes invariance, but that is wrong.
|
||||
// This only presently applies to chalk integration, as NLL
|
||||
// doesn't permit type variables to appear on both sides (and
|
||||
// doesn't use lazy norm).
|
||||
@ -616,15 +617,21 @@ where
|
||||
fn consts(
|
||||
&mut self,
|
||||
a: &'tcx ty::Const<'tcx>,
|
||||
b: &'tcx ty::Const<'tcx>,
|
||||
mut b: &'tcx ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
if let ty::Const { val: ConstValue::Bound(..), .. } = a {
|
||||
// FIXME(const_generics): I'm unsure how this branch should actually be handled,
|
||||
// so this is probably not correct.
|
||||
self.infcx.super_combine_consts(self, a, b)
|
||||
} else {
|
||||
debug!("consts(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance);
|
||||
relate::super_relate_consts(self, a, b)
|
||||
let a = self.infcx.shallow_resolve(a);
|
||||
|
||||
if !D::forbid_inference_vars() {
|
||||
b = self.infcx.shallow_resolve(b);
|
||||
}
|
||||
|
||||
match b.val {
|
||||
ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
|
||||
// Forbid inference variables in the RHS.
|
||||
bug!("unexpected inference var {:?}", b)
|
||||
}
|
||||
// FIXME(invariance): see the related FIXME above.
|
||||
_ => self.infcx.super_combine_consts(self, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
@ -991,15 +998,28 @@ where
|
||||
a: &'tcx ty::Const<'tcx>,
|
||||
_: &'tcx ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
debug!("TypeGeneralizer::consts(a={:?})", a);
|
||||
|
||||
if let ty::Const { val: ConstValue::Bound(..), .. } = a {
|
||||
bug!(
|
||||
"unexpected inference variable encountered in NLL generalization: {:?}",
|
||||
a
|
||||
);
|
||||
} else {
|
||||
relate::super_relate_consts(self, a, a)
|
||||
match a.val {
|
||||
ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
|
||||
bug!(
|
||||
"unexpected inference variable encountered in NLL generalization: {:?}",
|
||||
a
|
||||
);
|
||||
}
|
||||
ConstValue::Infer(InferConst::Var(vid)) => {
|
||||
let mut variable_table = self.infcx.const_unification_table.borrow_mut();
|
||||
let var_value = variable_table.probe_value(vid);
|
||||
match var_value.val.known() {
|
||||
Some(u) => self.relate(&u, &u),
|
||||
None => {
|
||||
let new_var_id = variable_table.new_key(ConstVarValue {
|
||||
origin: var_value.origin,
|
||||
val: ConstVariableValue::Unknown { universe: self.universe },
|
||||
});
|
||||
Ok(self.tcx().mk_const_var(new_var_id, a.ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => relate::super_relate_consts(self, a, a),
|
||||
}
|
||||
}
|
||||
|
||||
|
15
src/test/ui/const-generics/issues/issue-62579-no-match.rs
Normal file
15
src/test/ui/const-generics/issues/issue-62579-no-match.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct NoMatch;
|
||||
|
||||
fn foo<const T: NoMatch>() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo::<{NoMatch}>();
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/issue-62579-no-match.rs:3:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
10
src/test/ui/const-generics/issues/issue-65675.rs
Normal file
10
src/test/ui/const-generics/issues/issue-65675.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// run-pass
|
||||
// compile-flags: -Z chalk
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
pub struct Foo<T, const N: usize>([T; N]);
|
||||
impl<T, const N: usize> Foo<T, {N}> {}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/const-generics/issues/issue-65675.stderr
Normal file
8
src/test/ui/const-generics/issues/issue-65675.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/issue-65675.rs:4:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
Loading…
x
Reference in New Issue
Block a user