Change:
<short summary of the bugI tried this code: I expected to see this happen: It should build. Instead, this happened: rustc crashed with: Possible workaround: replace with . playground: rustc version: 1.39.0-nightly 2019-09-15
cc
Also ICEs without explicit feature gate enabled :/

Discussion:
use super::type_variable::TypeVariableValue; use super::unify_key::{ConstVarValue, ConstVariableValue}; use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; <ins> use super::unify_key::replace_if_possible; </ins> use crate::hir::def_id::DefId; use crate::mir::interpret::ConstValue;

where R: TypeRelation<'tcx>, { <ins> 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); </ins> let a_is_expected = relation.a_is_expected(); match (a.val, b.val) {

<del> use super::combine::{CombineFields, RelationDir, const_unification_error}; </del> <ins> use super::combine::{CombineFields, RelationDir}; </ins> use super::Subtype; use crate::hir::def_id::DefId; <del> use crate::ty::{self, Ty, TyCtxt, InferConst}; </del> <ins> use crate::ty::{self, Ty, TyCtxt}; </ins> use crate::ty::TyVar; use crate::ty::subst::SubstsRef; use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; <del> use crate::mir::interpret::ConstValue; use crate::infer::unify_key::replace_if_possible; </del> /// Ensures `a` is made equal to `b`. Returns `a` on success. pub struct Equate<'combine, 'infcx, 'tcx> {

a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { <del> 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) </del> <ins> self.fields.infcx.super_combine_consts(self, a, b) </ins> } fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)

a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { <del> debug!("{}.consts({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } </del> self.fields.infcx.super_combine_consts(self, a, b) }

use super::SubregionOrigin; <del> use super::combine::{CombineFields, RelationDir, const_unification_error}; </del> <ins> use super::combine::{CombineFields, RelationDir}; </ins> use crate::traits::Obligation; <del> use crate::ty::{self, Ty, TyCtxt, InferConst}; </del> <ins> use crate::ty::{self, Ty, TyCtxt}; </ins> use crate::ty::TyVar; use crate::ty::fold::TypeFoldable; use crate::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; <del> use crate::infer::unify_key::replace_if_possible; use crate::mir::interpret::ConstValue; </del> use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success.

a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { <del> 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) </del> <ins> self.fields.infcx.super_combine_consts(self, a, b) </ins> } fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)

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

<ins> 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 </ins>