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:
Mazdak Farrokhzad 2019-09-23 00:36:40 +02:00 committed by GitHub
commit 78d715fe14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 42 additions and 86 deletions

View File

@ -30,6 +30,7 @@
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 @@ pub fn super_combine_consts<R>(
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) {

View File

@ -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 @@ fn consts(
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>)

View File

@ -66,11 +66,6 @@ fn consts(
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)
}

View File

@ -66,11 +66,6 @@ fn consts(
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)
}

View File

@ -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 @@ fn consts(
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>)

View 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() {}

View 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