Rollup merge of #64679 - skinny121:const-infer, r=varkor
Infer consts more consistently Moved some duplicated logic in `TypeRelation` methods into `super_combined_consts`. Before some `TypeRelation`s like `Lub` wasn't using `replace_if_possible`, meaning some inference types were staying around longer than they should be. Fixes https://github.com/rust-lang/rust/issues/64519 r? @varkor
This commit is contained in:
commit
78d715fe14
@ -30,6 +30,7 @@ use super::sub::Sub;
|
||||
use super::type_variable::TypeVariableValue;
|
||||
use super::unify_key::{ConstVarValue, ConstVariableValue};
|
||||
use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use super::unify_key::replace_if_possible;
|
||||
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::mir::interpret::ConstValue;
|
||||
@ -127,6 +128,12 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
||||
where
|
||||
R: TypeRelation<'tcx>,
|
||||
{
|
||||
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
|
||||
if a == b { return Ok(a); }
|
||||
|
||||
let a = replace_if_possible(self.const_unification_table.borrow_mut(), a);
|
||||
let b = replace_if_possible(self.const_unification_table.borrow_mut(), b);
|
||||
|
||||
let a_is_expected = relation.a_is_expected();
|
||||
|
||||
match (a.val, b.val) {
|
||||
|
@ -1,14 +1,12 @@
|
||||
use super::combine::{CombineFields, RelationDir, const_unification_error};
|
||||
use super::combine::{CombineFields, RelationDir};
|
||||
use super::Subtype;
|
||||
|
||||
use crate::hir::def_id::DefId;
|
||||
|
||||
use crate::ty::{self, Ty, TyCtxt, InferConst};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::TyVar;
|
||||
use crate::ty::subst::SubstsRef;
|
||||
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use crate::infer::unify_key::replace_if_possible;
|
||||
|
||||
/// Ensures `a` is made equal to `b`. Returns `a` on success.
|
||||
pub struct Equate<'combine, 'infcx, 'tcx> {
|
||||
@ -108,39 +106,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
|
||||
a: &'tcx ty::Const<'tcx>,
|
||||
b: &'tcx ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
|
||||
if a == b { return Ok(a); }
|
||||
|
||||
let infcx = self.fields.infcx;
|
||||
let a = replace_if_possible(infcx.const_unification_table.borrow_mut(), a);
|
||||
let b = replace_if_possible(infcx.const_unification_table.borrow_mut(), b);
|
||||
let a_is_expected = self.a_is_expected();
|
||||
|
||||
match (a.val, b.val) {
|
||||
(ConstValue::Infer(InferConst::Var(a_vid)),
|
||||
ConstValue::Infer(InferConst::Var(b_vid))) => {
|
||||
infcx.const_unification_table
|
||||
.borrow_mut()
|
||||
.unify_var_var(a_vid, b_vid)
|
||||
.map_err(|e| const_unification_error(a_is_expected, e))?;
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
(ConstValue::Infer(InferConst::Var(a_id)), _) => {
|
||||
self.fields.infcx.unify_const_variable(a_is_expected, a_id, b)?;
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
(_, ConstValue::Infer(InferConst::Var(b_id))) => {
|
||||
self.fields.infcx.unify_const_variable(!a_is_expected, b_id, a)?;
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.fields.infcx.super_combine_consts(self, a, b)?;
|
||||
Ok(a)
|
||||
self.fields.infcx.super_combine_consts(self, a, b)
|
||||
}
|
||||
|
||||
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
|
||||
|
@ -66,11 +66,6 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
|
||||
a: &'tcx ty::Const<'tcx>,
|
||||
b: &'tcx ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
|
||||
if a == b {
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
self.fields.infcx.super_combine_consts(self, a, b)
|
||||
}
|
||||
|
||||
|
@ -66,11 +66,6 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
|
||||
a: &'tcx ty::Const<'tcx>,
|
||||
b: &'tcx ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
|
||||
if a == b {
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
self.fields.infcx.super_combine_consts(self, a, b)
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,11 @@
|
||||
use super::SubregionOrigin;
|
||||
use super::combine::{CombineFields, RelationDir, const_unification_error};
|
||||
use super::combine::{CombineFields, RelationDir};
|
||||
|
||||
use crate::traits::Obligation;
|
||||
use crate::ty::{self, Ty, TyCtxt, InferConst};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::TyVar;
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
use crate::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
|
||||
use crate::infer::unify_key::replace_if_possible;
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use std::mem;
|
||||
|
||||
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
|
||||
@ -142,41 +140,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
|
||||
a: &'tcx ty::Const<'tcx>,
|
||||
b: &'tcx ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
|
||||
if a == b { return Ok(a); }
|
||||
|
||||
let infcx = self.fields.infcx;
|
||||
let a = replace_if_possible(infcx.const_unification_table.borrow_mut(), a);
|
||||
let b = replace_if_possible(infcx.const_unification_table.borrow_mut(), b);
|
||||
|
||||
// Consts can only be equal or unequal to each other: there's no subtyping
|
||||
// relation, so we're just going to perform equating here instead.
|
||||
let a_is_expected = self.a_is_expected();
|
||||
match (a.val, b.val) {
|
||||
(ConstValue::Infer(InferConst::Var(a_vid)),
|
||||
ConstValue::Infer(InferConst::Var(b_vid))) => {
|
||||
infcx.const_unification_table
|
||||
.borrow_mut()
|
||||
.unify_var_var(a_vid, b_vid)
|
||||
.map_err(|e| const_unification_error(a_is_expected, e))?;
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
(ConstValue::Infer(InferConst::Var(a_id)), _) => {
|
||||
self.fields.infcx.unify_const_variable(a_is_expected, a_id, b)?;
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
(_, ConstValue::Infer(InferConst::Var(b_id))) => {
|
||||
self.fields.infcx.unify_const_variable(!a_is_expected, b_id, a)?;
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.fields.infcx.super_combine_consts(self, a, b)?;
|
||||
Ok(a)
|
||||
self.fields.infcx.super_combine_consts(self, a, b)
|
||||
}
|
||||
|
||||
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
|
||||
|
21
src/test/ui/const-generics/issue-64519.rs
Normal file
21
src/test/ui/const-generics/issue-64519.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
struct Foo<const D: usize> {
|
||||
state: Option<[u8; D]>,
|
||||
}
|
||||
|
||||
impl<const D: usize> Iterator for Foo<{D}> {
|
||||
type Item = [u8; D];
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if true {
|
||||
return Some(self.state.unwrap().clone());
|
||||
} else {
|
||||
return Some(self.state.unwrap().clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/const-generics/issue-64519.stderr
Normal file
8
src/test/ui/const-generics/issue-64519.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/issue-64519.rs:3:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
Loading…
Reference in New Issue
Block a user