From 9220558c246d6d1610e7a9b20bd031559b868236 Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Tue, 22 Oct 2019 14:00:19 +0100 Subject: [PATCH 1/5] Fix an issue with const inference variables sticking around under Chalk + NLL --- src/librustc/infer/combine.rs | 14 ++++------ src/librustc/infer/nll_relate/mod.rs | 41 ++++++++++++++++------------ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index f06dbc72cd9..2e724ac56ee 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -602,19 +602,15 @@ 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) - } + match variable_table.probe_value(vid).val.known() { + Some(u) => self.relate(&u, &u), None => Ok(c), } } - _ => { - relate::super_relate_consts(self, c, c) - } + _ => relate::super_relate_consts(self, c, c), } } } diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 64ef0421808..8d59f455cbb 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -27,7 +27,7 @@ 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::mir::interpret::ConstValue; use rustc_data_structures::fx::FxHashMap; use std::fmt::Debug; @@ -616,15 +616,20 @@ 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) + } + _ => self.infcx.super_combine_consts(self, a, b) } } @@ -991,15 +996,15 @@ 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(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), + None => Ok(a), + } + } + _ => relate::super_relate_consts(self, a, a), } } From 51c687446d65fe271972f6371639334bb10da6db Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Tue, 22 Oct 2019 14:07:20 +0100 Subject: [PATCH 2/5] Add regression test for #65675 --- src/test/ui/const-generics/issues/issue-65675.rs | 10 ++++++++++ src/test/ui/const-generics/issues/issue-65675.stderr | 8 ++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-65675.rs create mode 100644 src/test/ui/const-generics/issues/issue-65675.stderr diff --git a/src/test/ui/const-generics/issues/issue-65675.rs b/src/test/ui/const-generics/issues/issue-65675.rs new file mode 100644 index 00000000000..3ca527313f9 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-65675.rs @@ -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() {} diff --git a/src/test/ui/const-generics/issues/issue-65675.stderr b/src/test/ui/const-generics/issues/issue-65675.stderr new file mode 100644 index 00000000000..60b388e6278 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-65675.stderr @@ -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 + From cc7294c751fd700b77c3556eaae8507661f08f22 Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Wed, 23 Oct 2019 17:09:56 +0100 Subject: [PATCH 3/5] Add regression test for #62579 --- .../const-generics/issues/issue-62579-no-match.rs | 15 +++++++++++++++ .../issues/issue-62579-no-match.stderr | 8 ++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.rs create mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.stderr diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs new file mode 100644 index 00000000000..0ff7ddc41fe --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.rs @@ -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}>(); +} diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr new file mode 100644 index 00000000000..759d5fdeb4c --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr @@ -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 + From 12f68e6987c4669b90a6cdac1643b99b6c677aea Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Wed, 23 Oct 2019 17:40:18 +0100 Subject: [PATCH 4/5] Account for const generalisation in combine --- src/librustc/infer/combine.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 2e724ac56ee..a6c3c2de139 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -605,9 +605,21 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { 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), - None => Ok(c), + 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 }, + }); + let u = self.tcx().mk_const_var(new_var_id, c.ty); + return Ok(u); + } + } } } _ => relate::super_relate_consts(self, c, c), From 624e34a5d02d47b807bad3a81aa7ce0c088d2452 Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Wed, 23 Oct 2019 18:00:35 +0100 Subject: [PATCH 5/5] Account for const generalisation in nll_relate --- src/librustc/infer/combine.rs | 7 +++---- src/librustc/infer/nll_relate/mod.rs | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index a6c3c2de139..51ae4e49493 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -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) } } } @@ -616,8 +616,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { origin: var_value.origin, val: ConstVariableValue::Unknown { universe: self.for_universe }, }); - let u = self.tcx().mk_const_var(new_var_id, c.ty); - return Ok(u); + Ok(self.tcx().mk_const_var(new_var_id, c.ty)) } } } diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 8d59f455cbb..d6f76e9ee34 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -28,6 +28,7 @@ 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, 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). @@ -629,6 +630,7 @@ where // 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) } } @@ -997,11 +999,24 @@ where _: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { 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(); - match variable_table.probe_value(vid).val.known() { + let var_value = variable_table.probe_value(vid); + match var_value.val.known() { Some(u) => self.relate(&u, &u), - None => Ok(a), + 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),