Skip to content

Commit

Permalink
Rollup merge of rust-lang#64679 - skinny121:const-infer, r=varkor
Browse files Browse the repository at this point in the history
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 rust-lang#64519

r? @varkor
  • Loading branch information
Centril committed Sep 22, 2019
2 parents ee2012c + 3f2855e commit afd1c60
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 86 deletions.
7 changes: 7 additions & 0 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
40 changes: 3 additions & 37 deletions src/librustc/infer/equate.rs
Original file line number Diff line number Diff line change
@@ -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> {
Expand Down Expand Up @@ -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>)
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
5 changes: 0 additions & 5 deletions src/librustc/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
42 changes: 3 additions & 39 deletions src/librustc/infer/sub.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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>)
Expand Down
21 changes: 21 additions & 0 deletions src/test/ui/const-generics/issue-64519.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions src/test/ui/const-generics/issue-64519.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit afd1c60

Please sign in to comment.