From 8b14b84933467d7037feef9c37cb968a5cc9b607 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 29 Feb 2020 10:03:04 +1300 Subject: [PATCH 01/16] Assume unevaluated consts are equal to the other consts and add ConstEquate obligation. This delays the need to evaluate consts eagerly and therefore gets around const eval query cycles. --- .../infer/canonical/query_response.rs | 9 +- src/librustc_infer/infer/combine.rs | 16 ++- src/librustc_infer/infer/equate.rs | 14 ++- src/librustc_infer/infer/glb.rs | 12 ++- src/librustc_infer/infer/lub.rs | 12 ++- src/librustc_infer/infer/mod.rs | 20 ++++ src/librustc_infer/infer/nll_relate/mod.rs | 15 ++- src/librustc_infer/infer/outlives/mod.rs | 3 +- src/librustc_infer/infer/sub.rs | 12 ++- src/librustc_infer/traits/mod.rs | 3 +- src/librustc_infer/traits/structural_impls.rs | 3 + src/librustc_infer/traits/util.rs | 6 ++ src/librustc_lint/builtin.rs | 3 +- src/librustc_middle/ty/mod.rs | 12 ++- src/librustc_middle/ty/outlives.rs | 6 +- src/librustc_middle/ty/print/pretty.rs | 7 ++ src/librustc_middle/ty/relate.rs | 37 +++---- src/librustc_middle/ty/structural_impls.rs | 4 + .../borrow_check/type_check/relate_tys.rs | 4 +- .../transform/qualify_min_const_fn.rs | 3 +- src/librustc_trait_selection/opaque_types.rs | 3 +- .../traits/error_reporting/mod.rs | 21 ++++ .../traits/fulfill.rs | 62 +++++++++++- .../traits/object_safety.rs | 98 +++++++++++-------- .../traits/project.rs | 5 - .../traits/query/normalize.rs | 5 - src/librustc_trait_selection/traits/select.rs | 35 +++++++ src/librustc_trait_selection/traits/wf.rs | 4 + .../implied_outlives_bounds.rs | 3 +- .../normalize_erasing_regions.rs | 3 +- src/librustc_typeck/check/method/probe.rs | 3 +- src/librustc_typeck/check/mod.rs | 11 +++ src/librustc_typeck/collect.rs | 30 +----- .../impl_wf_check/min_specialization.rs | 3 +- src/librustc_typeck/outlives/explicit.rs | 3 +- src/librustdoc/clean/mod.rs | 3 +- 36 files changed, 371 insertions(+), 122 deletions(-) diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index de93baff79beb..c7a7cf89b4f1b 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -25,7 +25,7 @@ use rustc_middle::arena::ArenaAllocatable; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, BoundVar, Ty, TyCtxt}; +use rustc_middle::ty::{self, BoundVar, Const, Ty, TyCtxt}; use std::fmt::Debug; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -671,6 +671,13 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { }); } + fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) { + span_bug!( + self.cause.span(self.infcx.tcx), + "lazy_normalization_consts: unreachable `const_equate`" + ); + } + fn normalization() -> NormalizationStrategy { NormalizationStrategy::Eager } diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index d4af470499670..b995ff989e975 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -164,7 +164,6 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { return self.unify_const_variable(!a_is_expected, vid, a); } - _ => {} } @@ -375,6 +374,20 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf); Ok(Generalization { ty, needs_wf }) } + + pub fn add_const_equate_obligation( + &mut self, + a_is_expected: bool, + a: &'tcx ty::Const<'tcx>, + b: &'tcx ty::Const<'tcx>, + ) { + let predicate = if a_is_expected { + ty::Predicate::ConstEquate(a, b) + } else { + ty::Predicate::ConstEquate(b, a) + }; + self.obligations.push(Obligation::new(self.trace.cause.clone(), self.param_env, predicate)); + } } struct Generalizer<'cx, 'tcx> { @@ -637,6 +650,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } + ty::ConstKind::Unevaluated(..) => Ok(c), _ => relate::super_relate_consts(self, c, c), } } diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index d054070e292fa..eebcc0ff12a6a 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -4,7 +4,7 @@ use super::Subtype; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::TyVar; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, ConstKind, Ty, TyCtxt}; use rustc_hir::def_id::DefId; @@ -119,7 +119,17 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - self.fields.infcx.super_combine_consts(self, a, b) + match (a.val, b.val) { + (ConstKind::Unevaluated(..), _) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(b) + } + (_, ConstKind::Unevaluated(..)) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(a) + } + _ => self.fields.infcx.super_combine_consts(self, a, b), + } } fn binders( diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs index f95d74a9340c9..583e80efc7c55 100644 --- a/src/librustc_infer/infer/glb.rs +++ b/src/librustc_infer/infer/glb.rs @@ -79,7 +79,17 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - self.fields.infcx.super_combine_consts(self, a, b) + match (a.val, b.val) { + (ty::ConstKind::Unevaluated(..), _) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(b) + } + (_, ty::ConstKind::Unevaluated(..)) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(a) + } + _ => self.fields.infcx.super_combine_consts(self, a, b), + } } fn binders( diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs index 492f2b229d36d..e613bd5dc7a89 100644 --- a/src/librustc_infer/infer/lub.rs +++ b/src/librustc_infer/infer/lub.rs @@ -79,7 +79,17 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - self.fields.infcx.super_combine_consts(self, a, b) + match (a.val, b.val) { + (ty::ConstKind::Unevaluated(..), _) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(b) + } + (_, ty::ConstKind::Unevaluated(..)) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(a) + } + _ => self.fields.infcx.super_combine_consts(self, a, b), + } } fn binders( diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 67632a97df792..9c81a1153958b 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -1490,6 +1490,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.report_and_explain_type_error(trace, &err) } + pub fn report_mismatched_consts( + &self, + cause: &ObligationCause<'tcx>, + expected: &'tcx ty::Const<'tcx>, + actual: &'tcx ty::Const<'tcx>, + err: TypeError<'tcx>, + ) -> DiagnosticBuilder<'tcx> { + let trace = TypeTrace::consts(cause, true, expected, actual); + self.report_and_explain_type_error(trace, &err) + } + pub fn replace_bound_vars_with_fresh_vars( &self, span: Span, @@ -1777,6 +1788,15 @@ impl<'tcx> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), values: Types(ExpectedFound::new(a_is_expected, a, b)) } } + pub fn consts( + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: &'tcx ty::Const<'tcx>, + b: &'tcx ty::Const<'tcx>, + ) -> TypeTrace<'tcx> { + TypeTrace { cause: cause.clone(), values: Consts(ExpectedFound::new(a_is_expected, a, b)) } + } + pub fn dummy(tcx: TyCtxt<'tcx>) -> TypeTrace<'tcx> { TypeTrace { cause: ObligationCause::dummy(), diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 7aea26987a29f..32f11abdc9797 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -77,6 +77,8 @@ pub trait TypeRelatingDelegate<'tcx> { /// delegate. fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>); + fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); + /// Creates a new universe index. Used when instantiating placeholders. fn create_next_universe(&mut self) -> ty::UniverseIndex; @@ -592,8 +594,16 @@ where b = self.infcx.shallow_resolve(b); } - match b.val { - ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { + match (a.val, b.val) { + (ty::ConstKind::Unevaluated(..), _) => { + self.delegate.const_equate(a, b); + Ok(b) + } + (_, ty::ConstKind::Unevaluated(..)) => { + self.delegate.const_equate(a, b); + Ok(a) + } + (_, ty::ConstKind::Infer(InferConst::Var(_))) if D::forbid_inference_vars() => { // Forbid inference variables in the RHS. bug!("unexpected inference var {:?}", b) } @@ -976,6 +986,7 @@ where } } } + ty::ConstKind::Unevaluated(..) => Ok(a), _ => relate::super_relate_consts(self, a, a), } } diff --git a/src/librustc_infer/infer/outlives/mod.rs b/src/librustc_infer/infer/outlives/mod.rs index ed3d860586968..289457e2bd0c2 100644 --- a/src/librustc_infer/infer/outlives/mod.rs +++ b/src/librustc_infer/infer/outlives/mod.rs @@ -19,7 +19,8 @@ pub fn explicit_outlives_bounds<'tcx>( | ty::Predicate::ObjectSafe(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::TypeOutlives(..) - | ty::Predicate::ConstEvaluatable(..) => None, + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => None, ty::Predicate::RegionOutlives(ref data) => data .no_bound_vars() .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)), diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index 0abcc15d6fcd8..91b43dd082f14 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -155,7 +155,17 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - self.fields.infcx.super_combine_consts(self, a, b) + match (a.val, b.val) { + (ty::ConstKind::Unevaluated(..), _) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(b) + } + (_, ty::ConstKind::Unevaluated(..)) => { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + Ok(a) + } + _ => self.fields.infcx.super_combine_consts(self, a, b), + } } fn binders( diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index a8585fd293518..8d95904b355da 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -10,7 +10,7 @@ pub mod util; use rustc_hir as hir; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Const, Ty}; use rustc_span::Span; pub use self::FulfillmentErrorCode::*; @@ -81,6 +81,7 @@ pub enum FulfillmentErrorCode<'tcx> { CodeSelectionError(SelectionError<'tcx>), CodeProjectionError(MismatchedProjectionTypes<'tcx>), CodeSubtypeError(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate + CodeConstEquateError(ExpectedFound<&'tcx Const<'tcx>>, TypeError<'tcx>), CodeAmbiguity, } diff --git a/src/librustc_infer/traits/structural_impls.rs b/src/librustc_infer/traits/structural_impls.rs index 595a8cd768390..c48e58c04824e 100644 --- a/src/librustc_infer/traits/structural_impls.rs +++ b/src/librustc_infer/traits/structural_impls.rs @@ -41,6 +41,9 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> { super::CodeSubtypeError(ref a, ref b) => { write!(f, "CodeSubtypeError({:?}, {:?})", a, b) } + super::CodeConstEquateError(ref a, ref b) => { + write!(f, "CodeConstEquateError({:?}, {:?})", a, b) + } super::CodeAmbiguity => write!(f, "Ambiguity"), } } diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index b34685006e223..ee903b676bae9 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -42,6 +42,8 @@ pub fn anonymize_predicate<'tcx>( ty::Predicate::ConstEvaluatable(def_id, substs) => { ty::Predicate::ConstEvaluatable(def_id, substs) } + + ty::Predicate::ConstEquate(c1, c2) => ty::Predicate::ConstEquate(c1, c2), } } @@ -187,6 +189,10 @@ impl Elaborator<'tcx> { // Currently, we do not elaborate const-evaluatable // predicates. } + ty::Predicate::ConstEquate(..) => { + // Currently, we do not elaborate const-equate + // predicates. + } ty::Predicate::RegionOutlives(..) => { // Nothing to elaborate from `'a: 'b`. } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 327dbecba26ce..bca91fb7b5d16 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1221,7 +1221,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints { ObjectSafe(..) | ClosureKind(..) | Subtype(..) | - ConstEvaluatable(..) => continue, + ConstEvaluatable(..) | + ConstEquate(..) => continue, }; if predicate.is_global() { cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| { diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 6d6e1699feb22..36bc44f5e5032 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1054,6 +1054,9 @@ pub enum Predicate<'tcx> { /// Constant initializer must evaluate successfully. ConstEvaluatable(DefId, SubstsRef<'tcx>), + + /// Constants must be equal. The first component is the const that is expected. + ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>), } /// The crate outlives map is computed during typeck and contains the @@ -1172,6 +1175,9 @@ impl<'tcx> Predicate<'tcx> { Predicate::ConstEvaluatable(def_id, const_substs) => { Predicate::ConstEvaluatable(def_id, const_substs.subst(tcx, substs)) } + Predicate::ConstEquate(c1, c2) => { + Predicate::ConstEquate(c1.subst(tcx, substs), c2.subst(tcx, substs)) + } } } } @@ -1349,7 +1355,8 @@ impl<'tcx> Predicate<'tcx> { | Predicate::ObjectSafe(..) | Predicate::ClosureKind(..) | Predicate::TypeOutlives(..) - | Predicate::ConstEvaluatable(..) => None, + | Predicate::ConstEvaluatable(..) + | Predicate::ConstEquate(..) => None, } } @@ -1363,7 +1370,8 @@ impl<'tcx> Predicate<'tcx> { | Predicate::WellFormed(..) | Predicate::ObjectSafe(..) | Predicate::ClosureKind(..) - | Predicate::ConstEvaluatable(..) => None, + | Predicate::ConstEvaluatable(..) + | Predicate::ConstEquate(..) => None, } } } diff --git a/src/librustc_middle/ty/outlives.rs b/src/librustc_middle/ty/outlives.rs index afd670b85775b..3e6a12df6887d 100644 --- a/src/librustc_middle/ty/outlives.rs +++ b/src/librustc_middle/ty/outlives.rs @@ -83,6 +83,11 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo } } + ty::Array(element, _) => { + // Don't look into the len const as it doesn't affect regions + compute_components(tcx, element, out); + } + ty::Closure(_, ref substs) => { for upvar_ty in substs.as_closure().upvar_tys() { compute_components(tcx, upvar_ty, out); @@ -158,7 +163,6 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo ty::Opaque(..) | // OutlivesNominalType (ish) ty::Foreign(..) | // OutlivesNominalType ty::Str | // OutlivesScalar (ish) - ty::Array(..) | // ... ty::Slice(..) | // ... ty::RawPtr(..) | // ... ty::Ref(..) | // OutlivesReference diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 64909cd0c467a..2502a4a13a8f0 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -2058,6 +2058,13 @@ define_print_and_forward_display! { print_value_path(def_id, substs), write("` can be evaluated")) } + ty::Predicate::ConstEquate(c1, c2) => { + p!(write("the constant `"), + print(c1), + write("` equals `"), + print(c2), + write("`")) + } } } diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index d68bc7221f92d..0795990649f43 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -432,16 +432,17 @@ pub fn super_relate_tys>( match relation.relate(&sz_a, &sz_b) { Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), Err(err) => { - // Check whether the lengths are both concrete/known values, - // but are unequal, for better diagnostics. - let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); - let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); - match (sz_a, sz_b) { - (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( - expected_found(relation, &sz_a_val, &sz_b_val), - )), - _ => Err(err), - } + // // Check whether the lengths are both concrete/known values, + // // but are unequal, for better diagnostics. + // let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); + // let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); + // match (sz_a, sz_b) { + // (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( + // expected_found(relation, &sz_a_val, &sz_b_val), + // )), + // _ => Err(err), + // } + Err(err) } } } @@ -604,14 +605,14 @@ pub fn super_relate_consts>( } // FIXME(const_generics): this is wrong, as it is a projection - ( - ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted), - ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted), - ) if a_def_id == b_def_id && a_promoted == b_promoted => { - let substs = - relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted)) - } + // ( + // ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted), + // ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted), + // ) if a_def_id == b_def_id && a_promoted == b_promoted => { + // let substs = + // relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; + // Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted)) + // } _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), }; new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty })) diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index 680b718792199..cdb7e34546af8 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -240,6 +240,7 @@ impl fmt::Debug for ty::Predicate<'tcx> { ty::Predicate::ConstEvaluatable(def_id, substs) => { write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs) } + ty::Predicate::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2), } } } @@ -492,6 +493,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> { ty::Predicate::ConstEvaluatable(def_id, substs) => { tcx.lift(&substs).map(|substs| ty::Predicate::ConstEvaluatable(def_id, substs)) } + ty::Predicate::ConstEquate(c1, c2) => { + tcx.lift(&(c1, c2)).map(|(c1, c2)| ty::Predicate::ConstEquate(c1, c2)) + } } } } diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index 96ae534c3963f..c3b0bd82398cb 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -2,7 +2,7 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRe use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::relate::TypeRelation; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Const, Ty}; use rustc_trait_selection::traits::query::Fallible; use crate::borrow_check::constraints::OutlivesConstraint; @@ -99,6 +99,8 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { } } + fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {} + fn normalization() -> NormalizationStrategy { NormalizationStrategy::Eager } diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index c9982aeaa0839..a2e2c1bf9eda3 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -28,7 +28,8 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - | Predicate::TypeOutlives(_) | Predicate::WellFormed(_) | Predicate::Projection(_) - | Predicate::ConstEvaluatable(..) => continue, + | Predicate::ConstEvaluatable(..) + | Predicate::ConstEquate(..) => continue, Predicate::ObjectSafe(_) => { bug!("object safe predicate on function: {:#?}", predicate) } diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 4f8075b0171d3..396965fcfb8b7 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -1277,7 +1277,8 @@ crate fn required_region_bounds( | ty::Predicate::ObjectSafe(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::RegionOutlives(..) - | ty::Predicate::ConstEvaluatable(..) => None, + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => None, ty::Predicate::TypeOutlives(predicate) => { // Search for a bound of the form `erased_self_ty // : 'a`, but be wary of something like `for<'a> diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 0d53df3bf4b46..1b8f2e1ae9fd4 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -615,6 +615,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation ) } + + + ty::Predicate::ConstEquate(..) => { + // Errors for `ConstEquate` predicates show up as + // `SelectionError::ConstEvalFailure`, + // not `Unimplemented`. + span_bug!( + span, + "const-equate requirement gave wrong error: `{:?}`", + obligation + ) + } } } @@ -1092,6 +1104,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ) .emit(); } + FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => { + self.report_mismatched_consts( + &error.obligation.cause, + expected_found.expected, + expected_found.found, + err.clone(), + ) + .emit(); + } } } diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index 1e056c96acd38..18ba46dce23d3 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -3,8 +3,9 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_infer::traits::{TraitEngine, TraitEngineExt as _}; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; -use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Const, ToPolyTraitRef, Ty, TypeFoldable}; use std::marker::PhantomData; use super::project; @@ -520,6 +521,65 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))), } } + + ty::Predicate::ConstEquate(c1, c2) => { + debug!("equating consts: c1={:?} c2={:?}", c1, c2); + + let stalled_on = &mut pending_obligation.stalled_on; + + let mut evaluate = |c: &'tcx Const<'tcx>| { + if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val { + match self.selcx.infcx().const_eval_resolve( + obligation.param_env, + def_id, + substs, + promoted, + Some(obligation.cause.span), + ) { + Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty)), + Err(ErrorHandled::TooGeneric) => { + stalled_on.append( + &mut substs.types().filter_map(|ty| TyOrConstInferVar::maybe_from_ty(ty)).collect(), + ); + Err(ProcessResult::Unchanged) + } + Err(err) => { + Err(ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err)))) + } + } + } else { + Ok(c) + } + }; + + match (evaluate(c1), evaluate(c2)) { + (Ok(c1), Ok(c2)) => { + match self + .selcx + .infcx() + .at(&obligation.cause, obligation.param_env) + .eq(c1, c2) + { + Ok(_) => ProcessResult::Changed(vec![]), + Err(err) => { + ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError( + ExpectedFound::new(true, c1, c2), + err, + )) + } + } + } + // FIXME(skinny121) How to report both errors if both produces errors? + (Err(result @ ProcessResult::Error(_)), _) + | (_, Err(result @ ProcessResult::Error(_))) => result, + (Err(ProcessResult::Unchanged), _) | (_, Err(ProcessResult::Unchanged)) => { + ProcessResult::Unchanged + } + _ => { + unreachable!("evaluate shouldn't itself return ProcessResult::Changed(..)") + } + } + } } } diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index 96b2b904e6543..3b4533b04ba4c 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -16,8 +16,8 @@ use crate::traits::{self, Obligation, ObligationCause}; use rustc_errors::{Applicability, FatalError}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst}; -use rustc_middle::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst}; +use rustc_middle::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstness}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -281,7 +281,8 @@ fn predicates_reference_self( | ty::Predicate::RegionOutlives(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::Subtype(..) - | ty::Predicate::ConstEvaluatable(..) => None, + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => None, } }) .collect() @@ -313,7 +314,8 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::Predicate::ObjectSafe(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::TypeOutlives(..) - | ty::Predicate::ConstEvaluatable(..) => false, + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => false, }) } @@ -724,51 +726,65 @@ fn contains_illegal_self_type_reference<'tcx>( // object type, and we cannot resolve `Self as SomeOtherTrait` // without knowing what `Self` is. - let mut supertraits: Option>> = None; - let self_ty = tcx.types.self_param; - - let mut walker = ty.walk(); - while let Some(arg) = walker.next() { - if arg == self_ty.into() { - return true; - } - - // Special-case projections (everything else is walked normally). - if let GenericArgKind::Type(ty) = arg.unpack() { - if let ty::Projection(ref data) = ty.kind { - // This is a projected type `::X`. + struct IllegalSelfTypeVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + self_ty: Ty<'tcx>, + trait_def_id: DefId, + supertraits: Option>>, + } - // Compute supertraits of current trait lazily. - if supertraits.is_none() { - let trait_ref = ty::Binder::bind(ty::TraitRef::identity(tcx, trait_def_id)); - supertraits = Some(traits::supertraits(tcx, trait_ref).collect()); - } + impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + match t.kind { + ty::Param(_) => t == self.self_ty, + ty::Projection(ref data) => { + // This is a projected type `::X`. + + // Compute supertraits of current trait lazily. + if self.supertraits.is_none() { + let trait_ref = + ty::Binder::bind(ty::TraitRef::identity(self.tcx, self.trait_def_id)); + self.supertraits = Some(traits::supertraits(self.tcx, trait_ref).collect()); + } - // Determine whether the trait reference `Foo as - // SomeTrait` is in fact a supertrait of the - // current trait. In that case, this type is - // legal, because the type `X` will be specified - // in the object type. Note that we can just use - // direct equality here because all of these types - // are part of the formal parameter listing, and - // hence there should be no inference variables. - let projection_trait_ref = ty::Binder::bind(data.trait_ref(tcx)); - let is_supertrait_of_current_trait = - supertraits.as_ref().unwrap().contains(&projection_trait_ref); - - if is_supertrait_of_current_trait { - // Do not walk contained types, do not report error, do collect $200. - walker.skip_current_subtree(); + // Determine whether the trait reference `Foo as + // SomeTrait` is in fact a supertrait of the + // current trait. In that case, this type is + // legal, because the type `X` will be specified + // in the object type. Note that we can just use + // direct equality here because all of these types + // are part of the formal parameter listing, and + // hence there should be no inference variables. + let projection_trait_ref = ty::Binder::bind(data.trait_ref(self.tcx)); + let is_supertrait_of_current_trait = + self.supertraits.as_ref().unwrap().contains(&projection_trait_ref); + + if is_supertrait_of_current_trait { + false // do not walk contained types, do not report error, do collect $200 + } else { + t.super_visit_with(self) // DO walk contained types, POSSIBLY reporting an error + } } - - // DO walk contained types, POSSIBLY reporting an error. + _ => t.super_visit_with(self), // walk contained types, if any } } - // Walk contained types, if any. + fn visit_const(&mut self, _c: &ty::Const<'tcx>) -> bool { + // FIXME Look into the unevaluated constants for object safety violations. + // Do not walk substitutions of unevaluated consts, as they contain `Self`, even + // though the const expression doesn't necessary use it. Currently type variables + // inside array length expressions are forbidden, so they can't break the above + // rules. + false + } } - false + ty.visit_with(&mut IllegalSelfTypeVisitor { + tcx, + self_ty: tcx.types.self_param, + trait_def_id, + supertraits: None, + }) } pub fn provide(providers: &mut ty::query::Providers<'_>) { diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 0779882b6dd58..d7402fc5376d6 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -386,11 +386,6 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { _ => ty, } } - - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let constant = constant.super_fold_with(self); - constant.eval(self.selcx.tcx(), self.param_env) - } } /// The guts of `normalize`: normalize a specific projection like ` TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { _ => ty, } } - - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let constant = constant.super_fold_with(self); - constant.eval(self.infcx.tcx, self.param_env) - } } diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index f0ff30232b96d..4f4942ff596fc 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -43,6 +43,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items; use rustc_index::bit_set::GrowableBitSet; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fast_reject; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; @@ -503,9 +504,43 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None, ) { Ok(_) => Ok(EvaluatedToOk), + Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig), Err(_) => Ok(EvaluatedToErr), } } + + ty::Predicate::ConstEquate(c1, c2) => { + debug!("evaluate_predicate_recursively: equating consts c1={:?} c2={:?}", c1, c2); + + let evaluate = |c: &'tcx ty::Const<'tcx>| { + if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val { + match self.infcx.const_eval_resolve( + obligation.param_env, + def_id, + substs, + promoted, + Some(obligation.cause.span), + ) { + Ok(val) => Ok(ty::Const::from_value(self.tcx(), val, c.ty)), + Err(ErrorHandled::TooGeneric) => Err(EvaluatedToAmbig), + Err(_) => Err(EvaluatedToErr), + } + } else { + Ok(c) + } + }; + + match (evaluate(c1), evaluate(c2)) { + (Ok(c1), Ok(c2)) => { + match self.infcx().at(&obligation.cause, obligation.param_env).eq(c1, c2) { + Ok(_) => Ok(EvaluatedToOk), + Err(_) => Ok(EvaluatedToErr), + } + } + (Err(EvaluatedToErr), _) | (_, Err(EvaluatedToErr)) => Ok(EvaluatedToErr), + _ => Ok(EvaluatedToAmbig), + } + } } } diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index ba7ec96775c04..4d3bbfa77c37d 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -102,6 +102,10 @@ pub fn predicate_obligations<'a, 'tcx>( wf.compute(ty); } } + ty::Predicate::ConstEquate(c1, c2) => { + wf.compute(c1.ty); + wf.compute(c2.ty); + } } wf.normalize() diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 6db2e557fea69..eaaab87ab7474 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -100,7 +100,8 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::Predicate::Projection(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::ObjectSafe(..) - | ty::Predicate::ConstEvaluatable(..) => vec![], + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => vec![], ty::Predicate::WellFormed(subty) => { wf_types.push(subty); diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs index ad6c753edff00..ed30ed5313e5c 100644 --- a/src/librustc_traits/normalize_erasing_regions.rs +++ b/src/librustc_traits/normalize_erasing_regions.rs @@ -48,6 +48,7 @@ fn not_outlives_predicate(p: &ty::Predicate<'_>) -> bool { | ty::Predicate::ObjectSafe(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::Subtype(..) - | ty::Predicate::ConstEvaluatable(..) => true, + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => true, } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 7f1d77e5b97d8..e21db9035e25d 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -810,7 +810,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::Predicate::ObjectSafe(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::TypeOutlives(..) - | ty::Predicate::ConstEvaluatable(..) => None, + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => None, }); self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6bf836015d226..02b42284e6dea 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1648,6 +1648,16 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId, r.super_visit_with(self) } + + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { + if let ty::ConstKind::Unevaluated(..) = c.val { + // FIXME(lazy_normalization_consts) We currenctly don't detect lifetimes within substs + // which would violate this check. Even though the particular substitution is not used + // within the const, this should still be fixed. + return false; + } + c.super_visit_with(self) + } } let prohibit_opaque = match item.kind { @@ -3858,6 +3868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Predicate::WellFormed(..) => None, ty::Predicate::ObjectSafe(..) => None, ty::Predicate::ConstEvaluatable(..) => None, + ty::Predicate::ConstEquate(..) => None, // N.B., this predicate is created by breaking down a // `ClosureType: FnFoo()` predicate, where // `ClosureType` represents some `Closure`. It can't diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 854bd03b26486..efee33fa5b930 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1156,7 +1156,8 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let node = tcx.hir().get(hir_id); let parent_def_id = match node { - Node::ImplItem(_) + Node::AnonConst(_) + | Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) | Node::Ctor(..) @@ -1164,34 +1165,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id(parent_id).to_def_id()) } - // FIXME(#43408) enable this always when we get lazy normalization. - Node::AnonConst(_) => { - let parent_id = tcx.hir().get_parent_item(hir_id); - let parent_def_id = tcx.hir().local_def_id(parent_id); - - // HACK(eddyb) this provides the correct generics when - // `feature(const_generics)` is enabled, so that const expressions - // used with const generics, e.g. `Foo<{N+1}>`, can work at all. - if tcx.features().const_generics { - Some(parent_def_id.to_def_id()) - } else { - let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); - match parent_node { - // HACK(eddyb) this provides the correct generics for repeat - // expressions' count (i.e. `N` in `[x; N]`), and explicit - // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), - // as they shouldn't be able to cause query cycle errors. - Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - | Node::Variant(Variant { disr_expr: Some(ref constant), .. }) - if constant.hir_id == hir_id => - { - Some(parent_def_id.to_def_id()) - } - _ => None, - } - } - } Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { Some(tcx.closure_base_def_id(def_id)) } diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs index 8b12535b3a2cf..919bcc9943d48 100644 --- a/src/librustc_typeck/impl_wf_check/min_specialization.rs +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -413,6 +413,7 @@ fn trait_predicate_kind<'tcx>( | ty::Predicate::Subtype(_) | ty::Predicate::ObjectSafe(_) | ty::Predicate::ClosureKind(..) - | ty::Predicate::ConstEvaluatable(..) => None, + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => None, } } diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 168f20771476c..66daf0e7f7d9d 100644 --- a/src/librustc_typeck/outlives/explicit.rs +++ b/src/librustc_typeck/outlives/explicit.rs @@ -58,7 +58,8 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::Predicate::ObjectSafe(..) | ty::Predicate::ClosureKind(..) | ty::Predicate::Subtype(..) - | ty::Predicate::ConstEvaluatable(..) => (), + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => (), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6c001bc548410..c130ed3f46dbb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -493,7 +493,8 @@ impl<'a> Clean> for ty::Predicate<'a> { Predicate::WellFormed(..) | Predicate::ObjectSafe(..) | Predicate::ClosureKind(..) - | Predicate::ConstEvaluatable(..) => panic!("not user writable"), + | Predicate::ConstEvaluatable(..) + | Predicate::ConstEquate(..) => panic!("not user writable"), } } } From 4cfdd2178e999960358e15b8c36e89c13b4f21c0 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Thu, 2 Jan 2020 15:41:34 +1300 Subject: [PATCH 02/16] Emit `ConstEquate` obligation after checking/unifying for inference variables. This means a inference variable can be unified with an unevaluated const. --- src/librustc_infer/infer/combine.rs | 17 ++++++++++++++++- src/librustc_infer/infer/equate.rs | 22 +++++++++------------- src/librustc_infer/infer/glb.rs | 19 ++++++++----------- src/librustc_infer/infer/lub.rs | 19 ++++++++----------- src/librustc_infer/infer/nll_relate/mod.rs | 18 ++++++++++-------- src/librustc_infer/infer/sub.rs | 19 ++++++++----------- 6 files changed, 59 insertions(+), 55 deletions(-) diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index b995ff989e975..4d7461aa94e84 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -126,7 +126,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> where - R: TypeRelation<'tcx>, + R: ConstEquateRelation<'tcx>, { debug!("{}.consts({:?}, {:?})", relation.tag(), a, b); if a == b { @@ -164,6 +164,14 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { return self.unify_const_variable(!a_is_expected, vid, a); } + (ty::ConstKind::Unevaluated(..), _) => { + relation.const_equate_obligation(a, b); + return Ok(b); + } + (_, ty::ConstKind::Unevaluated(..)) => { + relation.const_equate_obligation(a, b); + return Ok(a); + } _ => {} } @@ -656,6 +664,13 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } +pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> { + /// Register am obligation that both constants must be equal to each other. + /// + /// If they aren't equal then the relation doesn't hold. + fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); +} + pub trait RelateResultCompare<'tcx, T> { fn compare(&self, t: T, f: F) -> RelateResult<'tcx, T> where diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index eebcc0ff12a6a..627580b0474d9 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -1,10 +1,10 @@ -use super::combine::{CombineFields, RelationDir}; +use super::combine::{CombineFields, RelationDir, ConstEquateRelation}; use super::Subtype; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::TyVar; -use rustc_middle::ty::{self, ConstKind, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::DefId; @@ -119,17 +119,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>> { - match (a.val, b.val) { - (ConstKind::Unevaluated(..), _) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(b) - } - (_, ConstKind::Unevaluated(..)) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(a) - } - _ => self.fields.infcx.super_combine_consts(self, a, b), - } + self.fields.infcx.super_combine_consts(self, a, b) } fn binders( @@ -150,3 +140,9 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { } } } + +impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> { + fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + } +} diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs index 583e80efc7c55..ec219a95b9441 100644 --- a/src/librustc_infer/infer/glb.rs +++ b/src/librustc_infer/infer/glb.rs @@ -3,6 +3,7 @@ use super::lattice::{self, LatticeDir}; use super::InferCtxt; use super::Subtype; +use crate::infer::combine::ConstEquateRelation; use crate::traits::ObligationCause; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -79,17 +80,7 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - match (a.val, b.val) { - (ty::ConstKind::Unevaluated(..), _) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(b) - } - (_, ty::ConstKind::Unevaluated(..)) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(a) - } - _ => self.fields.infcx.super_combine_consts(self, a, b), - } + self.fields.infcx.super_combine_consts(self, a, b) } fn binders( @@ -126,3 +117,9 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, Ok(()) } } + +impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> { + fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + } +} diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs index e613bd5dc7a89..a0453db2cb499 100644 --- a/src/librustc_infer/infer/lub.rs +++ b/src/librustc_infer/infer/lub.rs @@ -3,6 +3,7 @@ use super::lattice::{self, LatticeDir}; use super::InferCtxt; use super::Subtype; +use crate::infer::combine::ConstEquateRelation; use crate::traits::ObligationCause; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -79,17 +80,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - match (a.val, b.val) { - (ty::ConstKind::Unevaluated(..), _) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(b) - } - (_, ty::ConstKind::Unevaluated(..)) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(a) - } - _ => self.fields.infcx.super_combine_consts(self, a, b), - } + self.fields.infcx.super_combine_consts(self, a, b) } fn binders( @@ -110,6 +101,12 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { } } +impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> { + fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + } +} + impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> { fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'tcx> { self.fields.infcx diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 32f11abdc9797..709aa6b1bb7ae 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -21,6 +21,7 @@ //! thing we relate in chalk are basically domain goals and their //! constituents) +use crate::infer::combine::ConstEquateRelation; use crate::infer::InferCtxt; use crate::infer::{ConstVarValue, ConstVariableValue}; use rustc_data_structures::fx::FxHashMap; @@ -595,14 +596,6 @@ where } match (a.val, b.val) { - (ty::ConstKind::Unevaluated(..), _) => { - self.delegate.const_equate(a, b); - Ok(b) - } - (_, ty::ConstKind::Unevaluated(..)) => { - self.delegate.const_equate(a, b); - Ok(a) - } (_, ty::ConstKind::Infer(InferConst::Var(_))) if D::forbid_inference_vars() => { // Forbid inference variables in the RHS. bug!("unexpected inference var {:?}", b) @@ -725,6 +718,15 @@ where } } +impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D> +where + D: TypeRelatingDelegate<'tcx>, +{ + fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) { + self.delegate.const_equate(a, b); + } +} + /// When we encounter a binder like `for<..> fn(..)`, we actually have /// to walk the `fn` value to find all the values bound by the `for` /// (these are not explicitly present in the ty representation right diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index 91b43dd082f14..1ec67ef2efa9d 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -1,6 +1,7 @@ use super::combine::{CombineFields, RelationDir}; use super::SubregionOrigin; +use crate::infer::combine::ConstEquateRelation; use crate::traits::Obligation; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; @@ -155,17 +156,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>> { - match (a.val, b.val) { - (ty::ConstKind::Unevaluated(..), _) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(b) - } - (_, ty::ConstKind::Unevaluated(..)) => { - self.fields.add_const_equate_obligation(self.a_is_expected, a, b); - Ok(a) - } - _ => self.fields.infcx.super_combine_consts(self, a, b), - } + self.fields.infcx.super_combine_consts(self, a, b) } fn binders( @@ -179,3 +170,9 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { self.fields.higher_ranked_sub(a, b, self.a_is_expected) } } + +impl<'tcx> ConstEquateRelation<'tcx> for Sub<'_, '_, 'tcx> { + fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) { + self.fields.add_const_equate_obligation(self.a_is_expected, a, b); + } +} From 3ef831069a7bb249f2ce5bfb8abeaac21a0e9183 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 4 Jan 2020 13:42:02 +1300 Subject: [PATCH 03/16] Add lazy normalization tests --- .../ui/const-generics/issues/issue-61935.rs | 24 ++++++++ ...ssue-61336-1.stderr => issue-61935.stderr} | 3 - .../ui/const-generics/issues/issue-67185-1.rs | 32 ++++++++++ .../issues/issue-67185-1.stderr | 8 +++ .../ui/const-generics/issues/issue-67185-2.rs | 34 +++++++++++ .../issues/issue-67185-2.stderr | 61 +++++++++++++++++++ .../lazy-normalization/issue-71986.rs | 8 +++ 7 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/const-generics/issues/issue-61935.rs rename src/test/ui/const-generics/issues/{issue-61336-1.stderr => issue-61935.stderr} (84%) create mode 100644 src/test/ui/const-generics/issues/issue-67185-1.rs create mode 100644 src/test/ui/const-generics/issues/issue-67185-1.stderr create mode 100644 src/test/ui/const-generics/issues/issue-67185-2.rs create mode 100644 src/test/ui/const-generics/issues/issue-67185-2.stderr create mode 100644 src/test/ui/const-generics/lazy-normalization/issue-71986.rs diff --git a/src/test/ui/const-generics/issues/issue-61935.rs b/src/test/ui/const-generics/issues/issue-61935.rs new file mode 100644 index 0000000000000..35fb435b812a4 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61935.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait Foo {} + +impl Foo for [(); N] + where + Self:FooImpl<{N==0}> +{} + +trait FooImpl{} + +impl FooImpl for [(); 0] {} + +impl FooImpl for [();N] {} + +fn foo(_: impl Foo) {} + +fn main() { + foo([]); + foo([()]); +} diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61935.stderr similarity index 84% rename from src/test/ui/const-generics/issues/issue-61336-1.stderr rename to src/test/ui/const-generics/issues/issue-61935.stderr index b2c69d57c40b7..5ada50c344924 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.stderr @@ -1,5 +1,4 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-61336-1.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ @@ -7,5 +6,3 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: 1 warning emitted - diff --git a/src/test/ui/const-generics/issues/issue-67185-1.rs b/src/test/ui/const-generics/issues/issue-67185-1.rs new file mode 100644 index 0000000000000..89e0b7f62da5d --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-67185-1.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait Baz { + type Quaks; +} +impl Baz for u8 { + type Quaks = [u16; 3]; +} + +trait Bar {} +impl Bar for [u16; 3] {} +impl Bar for [[u16; 3]; 2] {} + +trait Foo + where + [::Quaks; 2]: Bar, + ::Quaks: Bar, +{ +} + +struct FooImpl; + +impl Foo for FooImpl {} + +fn f(_: impl Foo) {} + +fn main() { + f(FooImpl) +} diff --git a/src/test/ui/const-generics/issues/issue-67185-1.stderr b/src/test/ui/const-generics/issues/issue-67185-1.stderr new file mode 100644 index 0000000000000..01c09763314a9 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-67185-1.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-67185-1.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs new file mode 100644 index 0000000000000..af797721324e3 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -0,0 +1,34 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait Baz { + type Quaks; +} +impl Baz for u8 { + type Quaks = [u16; 3]; +} + +trait Bar {} +impl Bar for [u16; 4] {} +impl Bar for [[u16; 3]; 3] {} + +trait Foo //~ ERROR mismatched types + where + [::Quaks; 2]: Bar, + ::Quaks: Bar, +{ +} + +struct FooImpl; + +impl Foo for FooImpl {} +//~^ ERROR mismatched types +//~^^ ERROR mismatched types + +fn f(_: impl Foo) {} +//~^ ERROR mismatched types +//~^^ ERROR mismatched types + +fn main() { + f(FooImpl) +} diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr new file mode 100644 index 0000000000000..3a46d8fece88f --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -0,0 +1,61 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-67185-2.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/issue-67185-2.rs:15:1 + | +LL | / trait Foo +LL | | where +LL | | [::Quaks; 2]: Bar, +LL | | ::Quaks: Bar, +LL | | { +LL | | } + | |_^ expected `3usize`, found `4usize` + | + = note: expected type `3usize` + found type `4usize` + +error[E0308]: mismatched types + --> $DIR/issue-67185-2.rs:24:6 + | +LL | impl Foo for FooImpl {} + | ^^^ expected `3usize`, found `4usize` + | + = note: expected type `3usize` + found type `4usize` + +error[E0308]: mismatched types + --> $DIR/issue-67185-2.rs:24:6 + | +LL | impl Foo for FooImpl {} + | ^^^ expected `2usize`, found `3usize` + | + = note: expected type `2usize` + found type `3usize` + +error[E0308]: mismatched types + --> $DIR/issue-67185-2.rs:28:1 + | +LL | fn f(_: impl Foo) {} + | ^^^^^^^^^^^^^^^^^^^^ expected `2usize`, found `3usize` + | + = note: expected type `2usize` + found type `3usize` + +error[E0308]: mismatched types + --> $DIR/issue-67185-2.rs:28:1 + | +LL | fn f(_: impl Foo) {} + | ^^^^^^^^^^^^^^^^^^^^ expected `3usize`, found `4usize` + | + = note: expected type `3usize` + found type `4usize` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71986.rs b/src/test/ui/const-generics/lazy-normalization/issue-71986.rs new file mode 100644 index 0000000000000..a07bf2a1a5498 --- /dev/null +++ b/src/test/ui/const-generics/lazy-normalization/issue-71986.rs @@ -0,0 +1,8 @@ +// check-pass +#![allow(incomplete_features)] +#![feature(const_generics, lazy_normalization_consts)] + +pub trait Foo {} +pub fn bar>() {} + +fn main() {} From 93d15b94804d262be22f043c3dd9f66e3ce5a2fa Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 4 Jan 2020 18:54:19 +1300 Subject: [PATCH 04/16] Put lazy normalization behind a feature gate --- src/librustc_feature/active.rs | 4 + src/librustc_infer/infer/combine.rs | 14 ++- src/librustc_infer/infer/equate.rs | 2 +- src/librustc_infer/infer/nll_relate/mod.rs | 4 +- src/librustc_middle/ty/relate.rs | 40 ++++--- src/librustc_session/options.rs | 2 +- src/librustc_span/symbol.rs | 1 + .../traits/project.rs | 9 ++ .../traits/query/normalize.rs | 5 + src/librustc_typeck/collect.rs | 12 +- .../array-size-in-generic-struct-param.rs | 3 +- .../array-size-in-generic-struct-param.stderr | 10 +- .../ui/const-generics/issues/issue-61336-1.rs | 3 +- .../ui/const-generics/issues/issue-61336-2.rs | 3 +- .../issues/issue-61336-2.stderr | 6 + .../ui/const-generics/issues/issue-61336.rs | 2 + .../const-generics/issues/issue-61336.stderr | 6 + .../ui/const-generics/issues/issue-61747.rs | 2 + .../const-generics/issues/issue-61747.stderr | 8 ++ .../ui/const-generics/issues/issue-61935.rs | 2 + .../const-generics/issues/issue-61935.stderr | 6 + .../ui/const-generics/issues/issue-66205.rs | 1 + .../ui/const-generics/issues/issue-67185-1.rs | 2 + .../issues/issue-67185-1.stderr | 6 + .../ui/const-generics/issues/issue-67185-2.rs | 13 ++- .../issues/issue-67185-2.stderr | 108 +++++++++++++----- 26 files changed, 207 insertions(+), 67 deletions(-) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index a1dd7a5ca5225..f075988099b9e 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -558,6 +558,9 @@ declare_features! ( /// Allow negative trait implementations. (active, negative_impls, "1.44.0", Some(68318), None), + + /// Lazily evaluate constants. Which allows constants to depend on type parameters. + (active, lazy_normalization_consts, "1.44.0", Some(60471), None), /// Allows the use of `#[target_feature]` on safe functions. (active, target_feature_11, "1.45.0", Some(69098), None), @@ -581,4 +584,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::raw_dylib, sym::const_trait_impl, sym::const_trait_bound_opt_out, + sym::lazy_normalization_consts, ]; diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 4d7461aa94e84..415e3262c5093 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -164,11 +164,15 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { return self.unify_const_variable(!a_is_expected, vid, a); } - (ty::ConstKind::Unevaluated(..), _) => { + (ty::ConstKind::Unevaluated(..), _) + if self.tcx.features().lazy_normalization_consts => + { relation.const_equate_obligation(a, b); return Ok(b); } - (_, ty::ConstKind::Unevaluated(..)) => { + (_, ty::ConstKind::Unevaluated(..)) + if self.tcx.features().lazy_normalization_consts => + { relation.const_equate_obligation(a, b); return Ok(a); } @@ -658,14 +662,16 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } - ty::ConstKind::Unevaluated(..) => Ok(c), + ty::ConstKind::Unevaluated(..) if self.tcx().features().lazy_normalization_consts => { + Ok(c) + } _ => relate::super_relate_consts(self, c, c), } } } pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> { - /// Register am obligation that both constants must be equal to each other. + /// Register an obligation that both constants must be equal to each other. /// /// If they aren't equal then the relation doesn't hold. fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index 627580b0474d9..e3cafb82719dd 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -1,4 +1,4 @@ -use super::combine::{CombineFields, RelationDir, ConstEquateRelation}; +use super::combine::{CombineFields, ConstEquateRelation, RelationDir}; use super::Subtype; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 709aa6b1bb7ae..58acca7004154 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -988,7 +988,9 @@ where } } } - ty::ConstKind::Unevaluated(..) => Ok(a), + ty::ConstKind::Unevaluated(..) if self.tcx().features().lazy_normalization_consts => { + Ok(a) + } _ => relate::super_relate_consts(self, a, a), } } diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 0795990649f43..914b6d1d29e9c 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -431,18 +431,20 @@ pub fn super_relate_tys>( let t = relation.relate(&a_t, &b_t)?; match relation.relate(&sz_a, &sz_b) { Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), + // FIXME(lazy_normalization_consts) Implement improved diagnostics for mismatched array + // length? + Err(err) if relation.tcx().features().lazy_normalization_consts => Err(err), Err(err) => { - // // Check whether the lengths are both concrete/known values, - // // but are unequal, for better diagnostics. - // let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); - // let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); - // match (sz_a, sz_b) { - // (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( - // expected_found(relation, &sz_a_val, &sz_b_val), - // )), - // _ => Err(err), - // } - Err(err) + // Check whether the lengths are both concrete/known values, + // but are unequal, for better diagnostics. + let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); + let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); + match (sz_a, sz_b) { + (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( + expected_found(relation, &sz_a_val, &sz_b_val), + )), + _ => Err(err), + } } } } @@ -605,14 +607,14 @@ pub fn super_relate_consts>( } // FIXME(const_generics): this is wrong, as it is a projection - // ( - // ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted), - // ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted), - // ) if a_def_id == b_def_id && a_promoted == b_promoted => { - // let substs = - // relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - // Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted)) - // } + ( + ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted), + ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted), + ) if a_def_id == b_def_id && a_promoted == b_promoted => { + let substs = + relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; + Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted)) + } _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), }; new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty })) diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index e2c82a397c738..f02659cdb994b 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -870,7 +870,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], - "keep hygiene data after analysis (default: no)"), + "lazily evaluate constants (experimental)"), link_native_libraries: bool = (true, parse_bool, [UNTRACKED], "link native libraries in the linker invocation (default: yes)"), link_only: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index a61647bfd655f..e4318c65050a1 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -411,6 +411,7 @@ symbols! { label_break_value, lang, lang_items, + lazy_normalization_consts, let_chains, lhs, lib, diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index d7402fc5376d6..676cb68f60e2d 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -386,6 +386,15 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { _ => ty, } } + + fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + if self.selcx.tcx().features().lazy_normalization_consts { + constant + } else { + let constant = constant.super_fold_with(self); + constant.eval(self.selcx.tcx(), self.param_env) + } + } } /// The guts of `normalize`: normalize a specific projection like ` TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { _ => ty, } } + + fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + let constant = constant.super_fold_with(self); + constant.eval(self.infcx.tcx, self.param_env) + } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index efee33fa5b930..55ba008e35961 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1156,8 +1156,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let node = tcx.hir().get(hir_id); let parent_def_id = match node { - Node::AnonConst(_) - | Node::ImplItem(_) + Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) | Node::Ctor(..) @@ -1166,6 +1165,15 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.hir().local_def_id(parent_id).to_def_id()) } + Node::AnonConst(_) => { + if tcx.features().lazy_normalization_consts { + let parent_id = tcx.hir().get_parent_item(hir_id); + Some(tcx.hir().local_def_id(parent_id)) + } else { + None + } + } + Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { Some(tcx.closure_base_def_id(def_id)) } diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs index 5c02e585dc8ba..9e32687787ba6 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs @@ -1,5 +1,6 @@ -#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete #[allow(dead_code)] struct ArithArrayLen([u32; 0 + N]); diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr index 14cf64eeb7ac6..8a1ffe1806237 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr @@ -7,8 +7,14 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information +warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash + --> $DIR/array-size-in-generic-struct-param.rs:3:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error: constant expression depends on a generic parameter - --> $DIR/array-size-in-generic-struct-param.rs:5:38 + --> $DIR/array-size-in-generic-struct-param.rs:7:38 | LL | struct ArithArrayLen([u32; 0 + N]); | ^^^^^^^^^^^^ @@ -16,7 +22,7 @@ LL | struct ArithArrayLen([u32; 0 + N]); = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/array-size-in-generic-struct-param.rs:14:5 + --> $DIR/array-size-in-generic-struct-param.rs:16:5 | LL | arr: [u8; CFG.arr_size], | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs index 2135c868bbc70..915781bc0fc40 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.rs +++ b/src/test/ui/const-generics/issues/issue-61336-1.rs @@ -1,5 +1,6 @@ -#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete // build-pass diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs index 52969056f00a5..934831f91ad9b 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.rs +++ b/src/test/ui/const-generics/issues/issue-61336-2.rs @@ -1,5 +1,6 @@ -#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete fn f(x: T) -> [T; N] { [x; { N }] diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr index 5f3395223f95d..3e169f6592f16 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr @@ -7,6 +7,12 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information +warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash + --> $DIR/issue-61336-2.rs:3:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-61336-2.rs:9:5 | diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs index eb0f309762764..6baee0c0a7f18 100644 --- a/src/test/ui/const-generics/issues/issue-61336.rs +++ b/src/test/ui/const-generics/issues/issue-61336.rs @@ -1,5 +1,7 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete fn f(x: T) -> [T; N] { [x; N] diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr index 0eee37df3dd52..d619226a854d5 100644 --- a/src/test/ui/const-generics/issues/issue-61336.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.stderr @@ -7,6 +7,12 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information +warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash + --> $DIR/issue-61336.rs:3:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-61336.rs:9:5 | diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs index 9e0572d3568cb..0e185b53c1947 100644 --- a/src/test/ui/const-generics/issues/issue-61747.rs +++ b/src/test/ui/const-generics/issues/issue-61747.rs @@ -2,6 +2,8 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete struct Const; diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.stderr index 2e405370dc0df..8f4c389bb04e4 100644 --- a/src/test/ui/const-generics/issues/issue-61747.stderr +++ b/src/test/ui/const-generics/issues/issue-61747.stderr @@ -7,5 +7,13 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information +<<<<<<< HEAD warning: 1 warning emitted +======= +warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash + --> $DIR/issue-61747.rs:5:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +>>>>>>> Added `lazy_normalization_consts` feature, and removed the -Z flag. diff --git a/src/test/ui/const-generics/issues/issue-61935.rs b/src/test/ui/const-generics/issues/issue-61935.rs index 35fb435b812a4..445862cccdd89 100644 --- a/src/test/ui/const-generics/issues/issue-61935.rs +++ b/src/test/ui/const-generics/issues/issue-61935.rs @@ -2,6 +2,8 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash trait Foo {} diff --git a/src/test/ui/const-generics/issues/issue-61935.stderr b/src/test/ui/const-generics/issues/issue-61935.stderr index 5ada50c344924..0cc620738c714 100644 --- a/src/test/ui/const-generics/issues/issue-61935.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.stderr @@ -6,3 +6,9 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information +warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash + --> $DIR/issue-61935.rs:5:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/const-generics/issues/issue-66205.rs b/src/test/ui/const-generics/issues/issue-66205.rs index 73ba4fa6aae88..76bde1815be18 100644 --- a/src/test/ui/const-generics/issues/issue-66205.rs +++ b/src/test/ui/const-generics/issues/issue-66205.rs @@ -1,5 +1,6 @@ #![allow(incomplete_features, dead_code, unconditional_recursion)] #![feature(const_generics)] +#![feature(lazy_normalization_consts)] fn fact() { fact::<{ N - 1 }>(); diff --git a/src/test/ui/const-generics/issues/issue-67185-1.rs b/src/test/ui/const-generics/issues/issue-67185-1.rs index 89e0b7f62da5d..664dbaeb06791 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.rs +++ b/src/test/ui/const-generics/issues/issue-67185-1.rs @@ -2,6 +2,8 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67185-1.stderr b/src/test/ui/const-generics/issues/issue-67185-1.stderr index 01c09763314a9..257949340d0f0 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-1.stderr @@ -6,3 +6,9 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default +warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash + --> $DIR/issue-67185-1.rs:5:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index af797721324e3..52c8a5c9de809 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -1,5 +1,7 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash trait Baz { type Quaks; @@ -12,7 +14,8 @@ trait Bar {} impl Bar for [u16; 4] {} impl Bar for [[u16; 3]; 3] {} -trait Foo //~ ERROR mismatched types +trait Foo //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] + //~^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] where [::Quaks; 2]: Bar, ::Quaks: Bar, @@ -22,12 +25,12 @@ trait Foo //~ ERROR mismatched types struct FooImpl; impl Foo for FooImpl {} -//~^ ERROR mismatched types -//~^^ ERROR mismatched types +//~^ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +//~^^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] fn f(_: impl Foo) {} -//~^ ERROR mismatched types -//~^^ ERROR mismatched types +//~^ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +//~^^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] fn main() { f(FooImpl) diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 3a46d8fece88f..c8620fc268ffb 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -6,56 +6,106 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0308]: mismatched types - --> $DIR/issue-67185-2.rs:15:1 +warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash + --> $DIR/issue-67185-2.rs:3:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:17:1 + | +LL | / trait Foo +LL | | +LL | | where +LL | | [::Quaks; 2]: Bar, +LL | | ::Quaks: Bar, +LL | | { +LL | | } + | |_^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:17:1 | LL | / trait Foo +LL | | LL | | where LL | | [::Quaks; 2]: Bar, LL | | ::Quaks: Bar, LL | | { LL | | } - | |_^ expected `3usize`, found `4usize` + | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = note: expected type `3usize` - found type `4usize` + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable -error[E0308]: mismatched types - --> $DIR/issue-67185-2.rs:24:6 +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:27:6 | LL | impl Foo for FooImpl {} - | ^^^ expected `3usize`, found `4usize` + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = note: expected type `3usize` - found type `4usize` + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> -error[E0308]: mismatched types - --> $DIR/issue-67185-2.rs:24:6 +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:27:6 | LL | impl Foo for FooImpl {} - | ^^^ expected `2usize`, found `3usize` + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = note: expected type `2usize` - found type `3usize` + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> -error[E0308]: mismatched types - --> $DIR/issue-67185-2.rs:28:1 +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:31:14 | -LL | fn f(_: impl Foo) {} - | ^^^^^^^^^^^^^^^^^^^^ expected `2usize`, found `3usize` +LL | / trait Foo +LL | | +LL | | where +LL | | [::Quaks; 2]: Bar, +LL | | ::Quaks: Bar, +LL | | { +LL | | } + | |_- required by `Foo` +... +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = note: expected type `2usize` - found type `3usize` + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> -error[E0308]: mismatched types - --> $DIR/issue-67185-2.rs:28:1 +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:31:14 | -LL | fn f(_: impl Foo) {} - | ^^^^^^^^^^^^^^^^^^^^ expected `3usize`, found `4usize` +LL | / trait Foo +LL | | +LL | | where +LL | | [::Quaks; 2]: Bar, +LL | | ::Quaks: Bar, +LL | | { +LL | | } + | |_- required by `Foo` +... +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = note: expected type `3usize` - found type `4usize` + = help: the following implementations were found: + <[[u16; 3]; 3] as Bar> + <[u16; 4] as Bar> -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. From c3a0cba1c1612c64bf5f8e485cff086e0a4b5ab3 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 5 May 2020 17:57:23 +0200 Subject: [PATCH 05/16] initial cleanup --- src/librustc_feature/active.rs | 2 +- src/librustc_infer/infer/nll_relate/mod.rs | 4 ++-- src/librustc_session/options.rs | 2 +- src/librustc_trait_selection/traits/error_reporting/mod.rs | 1 - src/librustc_trait_selection/traits/fulfill.rs | 5 ++++- src/librustc_trait_selection/traits/object_safety.rs | 3 ++- src/librustc_typeck/collect.rs | 2 +- 7 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index f075988099b9e..894b392f1c036 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -558,7 +558,7 @@ declare_features! ( /// Allow negative trait implementations. (active, negative_impls, "1.44.0", Some(68318), None), - + /// Lazily evaluate constants. Which allows constants to depend on type parameters. (active, lazy_normalization_consts, "1.44.0", Some(60471), None), diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 58acca7004154..e67ea56cf8911 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -595,8 +595,8 @@ where b = self.infcx.shallow_resolve(b); } - match (a.val, b.val) { - (_, ty::ConstKind::Infer(InferConst::Var(_))) if D::forbid_inference_vars() => { + match b.val { + ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { // Forbid inference variables in the RHS. bug!("unexpected inference var {:?}", b) } diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index f02659cdb994b..e2c82a397c738 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -870,7 +870,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], - "lazily evaluate constants (experimental)"), + "keep hygiene data after analysis (default: no)"), link_native_libraries: bool = (true, parse_bool, [UNTRACKED], "link native libraries in the linker invocation (default: yes)"), link_only: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 1b8f2e1ae9fd4..139b860072224 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -616,7 +616,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) } - ty::Predicate::ConstEquate(..) => { // Errors for `ConstEquate` predicates show up as // `SelectionError::ConstEvalFailure`, diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index 18ba46dce23d3..cf107a6c5b5ab 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -539,7 +539,10 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty)), Err(ErrorHandled::TooGeneric) => { stalled_on.append( - &mut substs.types().filter_map(|ty| TyOrConstInferVar::maybe_from_ty(ty)).collect(), + &mut substs + .types() + .filter_map(|ty| TyOrConstInferVar::maybe_from_ty(ty)) + .collect(), ); Err(ProcessResult::Unchanged) } diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index 3b4533b04ba4c..a34006dd4fc06 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -17,7 +17,8 @@ use rustc_errors::{Applicability, FatalError}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst}; -use rustc_middle::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstness}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstness}; +use rustc_middle::ty::{Predicate, ToPredicate}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; use rustc_span::Span; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 55ba008e35961..a29a9a6a99750 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1168,7 +1168,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Node::AnonConst(_) => { if tcx.features().lazy_normalization_consts { let parent_id = tcx.hir().get_parent_item(hir_id); - Some(tcx.hir().local_def_id(parent_id)) + Some(tcx.hir().local_def_id(parent_id).to_def_id()) } else { None } From e1a8d322d0cb1ecce799a3ae5bfc991892ab09e2 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 5 May 2020 22:47:47 +0200 Subject: [PATCH 06/16] keep the good old lazy_normalization hack alive --- src/librustc_typeck/collect.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a29a9a6a99750..6ab7f66186333 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1164,13 +1164,33 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id(parent_id).to_def_id()) } - + // FIXME(#43408) always enable this once we use `lazy_normalization` is + // stable enough and does not need a feature gate anymore. Node::AnonConst(_) => { - if tcx.features().lazy_normalization_consts { - let parent_id = tcx.hir().get_parent_item(hir_id); - Some(tcx.hir().local_def_id(parent_id).to_def_id()) + let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_def_id = tcx.hir().local_def_id(parent_id); + + // HACK(eddyb) this provides the correct generics when + // `feature(const_generics)` is enabled, so that const expressions + // used with const generics, e.g. `Foo<{N+1}>`, can work at all. + if tcx.features().const_generics || tcx.features().lazy_normalization_consts { + Some(parent_def_id.to_def_id()) } else { - None + let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); + match parent_node { + // HACK(eddyb) this provides the correct generics for repeat + // expressions' count (i.e. `N` in `[x; N]`), and explicit + // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), + // as they shouldn't be able to cause query cycle errors. + Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) + | Node::Variant(Variant { disr_expr: Some(ref constant), .. }) + if constant.hir_id == hir_id => + { + Some(parent_def_id.to_def_id()) + } + + _ => None, + } } } From afd7ea88fb887627dd551309b951a5b69ea90d98 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 5 May 2020 22:47:54 +0200 Subject: [PATCH 07/16] update tests and add relevant feature gate test --- src/librustc_typeck/collect.rs | 3 +- .../array-size-in-generic-struct-param.stderr | 2 +- .../issues/issue-61336-2.stderr | 4 +- .../const-generics/issues/issue-61336.stderr | 4 +- .../const-generics/issues/issue-61747.stderr | 6 +-- .../const-generics/issues/issue-61935.stderr | 2 + .../const-generics/issues/issue-66205.stderr | 2 +- .../issues/issue-67185-1.stderr | 2 + .../issues/issue-67185-2.stderr | 48 +++++++++++-------- .../lazy-normalization/issue-71922.rs | 20 ++++++++ .../lazy-normalization-feature-gate.rs | 20 ++++++++ .../lazy-normalization-feature-gate.stderr | 44 +++++++++++++++++ 12 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 src/test/ui/const-generics/lazy-normalization/issue-71922.rs create mode 100644 src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs create mode 100644 src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6ab7f66186333..d16990cb44c49 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1164,7 +1164,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id(parent_id).to_def_id()) } - // FIXME(#43408) always enable this once we use `lazy_normalization` is + // FIXME(#43408) always enable this once `lazy_normalization` is // stable enough and does not need a feature gate anymore. Node::AnonConst(_) => { let parent_id = tcx.hir().get_parent_item(hir_id); @@ -1193,7 +1193,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } } } - Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { Some(tcx.closure_base_def_id(def_id)) } diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr index 8a1ffe1806237..2ebd063af18ac 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr @@ -29,5 +29,5 @@ LL | arr: [u8; CFG.arr_size], | = note: this may fail depending on what value the parameter takes -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr index 3e169f6592f16..c779ac10671a6 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr @@ -14,7 +14,7 @@ LL | #![feature(lazy_normalization_consts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/issue-61336-2.rs:9:5 + --> $DIR/issue-61336-2.rs:11:5 | LL | [x; { N }] | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` @@ -25,6 +25,6 @@ help: consider restricting type parameter `T` LL | fn g(x: T) -> [T; N] { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error; 2 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr index d619226a854d5..7d7cec2c17911 100644 --- a/src/test/ui/const-generics/issues/issue-61336.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.stderr @@ -14,7 +14,7 @@ LL | #![feature(lazy_normalization_consts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/issue-61336.rs:9:5 + --> $DIR/issue-61336.rs:11:5 | LL | [x; N] | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` @@ -25,6 +25,6 @@ help: consider restricting type parameter `T` LL | fn g(x: T) -> [T; N] { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error; 2 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.stderr index 8f4c389bb04e4..5eb468cc27263 100644 --- a/src/test/ui/const-generics/issues/issue-61747.stderr +++ b/src/test/ui/const-generics/issues/issue-61747.stderr @@ -7,13 +7,11 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -<<<<<<< HEAD -warning: 1 warning emitted -======= warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash --> $DIR/issue-61747.rs:5:12 | LL | #![feature(lazy_normalization_consts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ ->>>>>>> Added `lazy_normalization_consts` feature, and removed the -Z flag. + +warning: 2 warnings emitted diff --git a/src/test/ui/const-generics/issues/issue-61935.stderr b/src/test/ui/const-generics/issues/issue-61935.stderr index 0cc620738c714..ec0db0401b41c 100644 --- a/src/test/ui/const-generics/issues/issue-61935.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.stderr @@ -12,3 +12,5 @@ warning: the feature `lazy_normalization_consts` is incomplete and may cause the LL | #![feature(lazy_normalization_consts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: 2 warnings emitted + diff --git a/src/test/ui/const-generics/issues/issue-66205.stderr b/src/test/ui/const-generics/issues/issue-66205.stderr index 2bd013e8b41f2..416b675b56d28 100644 --- a/src/test/ui/const-generics/issues/issue-66205.stderr +++ b/src/test/ui/const-generics/issues/issue-66205.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-66205.rs:5:12 + --> $DIR/issue-66205.rs:6:12 | LL | fact::<{ N - 1 }>(); | ^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-67185-1.stderr b/src/test/ui/const-generics/issues/issue-67185-1.stderr index 257949340d0f0..2472693afcbaf 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-1.stderr @@ -12,3 +12,5 @@ warning: the feature `lazy_normalization_consts` is incomplete and may cause the LL | #![feature(lazy_normalization_consts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: 2 warnings emitted + diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index c8620fc268ffb..76d2622e9af0f 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -51,6 +51,12 @@ LL | | } error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:27:6 | +LL | trait Foo + | --- required by a bound in this +... +LL | ::Quaks: Bar, + | --- required by this bound in `Foo` +... LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | @@ -61,6 +67,12 @@ LL | impl Foo for FooImpl {} error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:27:6 | +LL | trait Foo + | --- required by a bound in this +... +LL | [::Quaks; 2]: Bar, + | --- required by this bound in `Foo` +... LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | @@ -71,17 +83,14 @@ LL | impl Foo for FooImpl {} error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:31:14 | -LL | / trait Foo -LL | | -LL | | where -LL | | [::Quaks; 2]: Bar, -LL | | ::Quaks: Bar, -LL | | { -LL | | } - | |_- required by `Foo` +LL | trait Foo + | --- required by a bound in this +... +LL | [::Quaks; 2]: Bar, + | --- required by this bound in `Foo` ... -LL | fn f(_: impl Foo) {} - | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> @@ -90,22 +99,19 @@ LL | fn f(_: impl Foo) {} error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:31:14 | -LL | / trait Foo -LL | | -LL | | where -LL | | [::Quaks; 2]: Bar, -LL | | ::Quaks: Bar, -LL | | { -LL | | } - | |_- required by `Foo` +LL | trait Foo + | --- required by a bound in this +... +LL | ::Quaks: Bar, + | --- required by this bound in `Foo` ... -LL | fn f(_: impl Foo) {} - | ^^^ the trait `Bar` is not implemented for `[u16; 3]` +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> -error: aborting due to 6 previous errors +error: aborting due to 6 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71922.rs b/src/test/ui/const-generics/lazy-normalization/issue-71922.rs new file mode 100644 index 0000000000000..60597b8be620d --- /dev/null +++ b/src/test/ui/const-generics/lazy-normalization/issue-71922.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(const_generics)] +#![feature(lazy_normalization_consts)] +#![allow(incomplete_features)] +trait Foo {} + +impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + +trait FooImpl {} + +impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {} + +impl FooImpl<{ 0u8 != 0u8 }> for [(); N] {} + +fn foo(_: T) {} + +fn main() { + foo([]); + foo([()]); +} diff --git a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs new file mode 100644 index 0000000000000..2c6fbfe65d6e1 --- /dev/null +++ b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs @@ -0,0 +1,20 @@ +// gate-test-lazy_normalization_consts +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +trait Foo {} + +impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} +//~^ ERROR cycle detected + +trait FooImpl {} + +impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {} + +impl FooImpl<{ 0u8 != 0u8 }> for [(); N] {} + +fn foo(_: T) {} + +fn main() { + foo([]); + foo([()]); +} diff --git a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr new file mode 100644 index 0000000000000..8a97ec0c5fc88 --- /dev/null +++ b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr @@ -0,0 +1,44 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/lazy-normalization-feature-gate-hack.rs:2:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0391]: cycle detected when const-evaluating + checking `::{{constant}}#0` + --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 + | +LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + | ^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 + | +LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + | ^^^^^^^^^^ +note: ...which requires const-evaluating `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 + | +LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + | ^^^^^^^^^^ +note: ...which requires type-checking `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 + | +LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + | ^^^^^^^^^^ +note: ...which requires processing `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 + | +LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + | ^^^^^^^^^^ + = note: ...which again requires const-evaluating + checking `::{{constant}}#0`, completing the cycle +note: cycle used when processing `` + --> $DIR/lazy-normalization-feature-gate-hack.rs:6:1 + | +LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0391`. From e873eef1e37eb45bdafda02ad4a3a4d599cee401 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 7 May 2020 10:26:12 +0200 Subject: [PATCH 08/16] explicitly handle errors in fulfill --- .../traits/fulfill.rs | 23 +++++++-------- .../lazy-normalization-feature-gate.stderr | 28 +++++++++---------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index cf107a6c5b5ab..98f6ac0e54728 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -2,6 +2,7 @@ use crate::infer::{InferCtxt, TyOrConstInferVar}; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; +use rustc_errors::ErrorReported; use rustc_infer::traits::{TraitEngine, TraitEngineExt as _}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; @@ -544,11 +545,9 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { .filter_map(|ty| TyOrConstInferVar::maybe_from_ty(ty)) .collect(), ); - Err(ProcessResult::Unchanged) - } - Err(err) => { - Err(ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err)))) + Err(ErrorHandled::TooGeneric) } + Err(err) => Err(err), } } else { Ok(c) @@ -572,15 +571,17 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } } } - // FIXME(skinny121) How to report both errors if both produces errors? - (Err(result @ ProcessResult::Error(_)), _) - | (_, Err(result @ ProcessResult::Error(_))) => result, - (Err(ProcessResult::Unchanged), _) | (_, Err(ProcessResult::Unchanged)) => { + (Err(ErrorHandled::Reported(ErrorReported)), _) + | (_, Err(ErrorHandled::Reported(ErrorReported))) => ProcessResult::Error( + CodeSelectionError(ConstEvalFailure(ErrorHandled::Reported(ErrorReported))), + ), + (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => span_bug!( + obligation.cause.span(self.selcx.tcx()), + "ConstEquate: const_eval_resolve returned an unexpected error" + ), + (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => { ProcessResult::Unchanged } - _ => { - unreachable!("evaluate shouldn't itself return ProcessResult::Changed(..)") - } } } } diff --git a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr index 8a97ec0c5fc88..9a7844f5e8f10 100644 --- a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr +++ b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr @@ -1,40 +1,40 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/lazy-normalization-feature-gate-hack.rs:2:12 + --> $DIR/lazy-normalization-feature-gate.rs:2:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default -error[E0391]: cycle detected when const-evaluating + checking `::{{constant}}#0` - --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 +error[E0391]: cycle detected when const-evaluating + checking `::{{constant}}#0` + --> $DIR/lazy-normalization-feature-gate.rs:6:58 | LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} | ^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 +note: ...which requires const-evaluating + checking `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate.rs:6:58 | LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} | ^^^^^^^^^^ -note: ...which requires const-evaluating `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 +note: ...which requires const-evaluating `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate.rs:6:58 | LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} | ^^^^^^^^^^ -note: ...which requires type-checking `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 +note: ...which requires type-checking `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate.rs:6:58 | LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} | ^^^^^^^^^^ -note: ...which requires processing `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate-hack.rs:6:58 +note: ...which requires processing `::{{constant}}#0`... + --> $DIR/lazy-normalization-feature-gate.rs:6:58 | LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} | ^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `::{{constant}}#0`, completing the cycle -note: cycle used when processing `` - --> $DIR/lazy-normalization-feature-gate-hack.rs:6:1 + = note: ...which again requires const-evaluating + checking `::{{constant}}#0`, completing the cycle +note: cycle used when processing `` + --> $DIR/lazy-normalization-feature-gate.rs:6:1 | LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 479968b81259ee7bfd3897cb192ff61b59fb8a8f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 7 May 2020 12:45:15 +0200 Subject: [PATCH 09/16] explicitly handle errors in `select` --- src/librustc_trait_selection/traits/select.rs | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index 4f4942ff596fc..70c6cbef102c5 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -38,6 +38,7 @@ use crate::traits::project::ProjectionCacheKeyExt; use rustc_ast::attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items; @@ -514,17 +515,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let evaluate = |c: &'tcx ty::Const<'tcx>| { if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val { - match self.infcx.const_eval_resolve( - obligation.param_env, - def_id, - substs, - promoted, - Some(obligation.cause.span), - ) { - Ok(val) => Ok(ty::Const::from_value(self.tcx(), val, c.ty)), - Err(ErrorHandled::TooGeneric) => Err(EvaluatedToAmbig), - Err(_) => Err(EvaluatedToErr), - } + self.infcx + .const_eval_resolve( + obligation.param_env, + def_id, + substs, + promoted, + Some(obligation.cause.span), + ) + .map(|val| ty::Const::from_value(self.tcx(), val, c.ty)) } else { Ok(c) } @@ -537,8 +536,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(_) => Ok(EvaluatedToErr), } } - (Err(EvaluatedToErr), _) | (_, Err(EvaluatedToErr)) => Ok(EvaluatedToErr), - _ => Ok(EvaluatedToAmbig), + (Err(ErrorHandled::Reported(ErrorReported)), _) + | (_, Err(ErrorHandled::Reported(ErrorReported))) => Ok(EvaluatedToErr), + (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => span_bug!( + obligation.cause.span(self.tcx()), + "ConstEquate: const_eval_resolve returned an unexpected error" + ), + (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => { + Ok(EvaluatedToAmbig) + } } } } From 443ae838742350a93326ede1f4ad7429238da644 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 15 May 2020 16:14:37 +0200 Subject: [PATCH 10/16] merge lazy_normalization_consts into const_generics --- src/librustc_feature/active.rs | 4 -- src/librustc_infer/infer/combine.rs | 12 ++--- src/librustc_infer/infer/nll_relate/mod.rs | 4 +- src/librustc_middle/ty/relate.rs | 4 +- src/librustc_span/symbol.rs | 1 - .../traits/project.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- .../array-size-in-generic-struct-param.rs | 5 +++ .../array-size-in-generic-struct-param.stderr | 12 ++--- .../ui/const-generics/different_byref.stderr | 4 +- .../fn-const-param-infer.stderr | 16 +++---- .../ui/const-generics/issues/issue-61336-1.rs | 3 +- .../issues/issue-61336-1.stderr | 10 +++++ .../ui/const-generics/issues/issue-61336-2.rs | 3 +- .../issues/issue-61336-2.stderr | 10 +---- .../const-generics/issues/issue-61336.stderr | 10 +---- .../const-generics/issues/issue-61747.stderr | 8 +--- .../ui/const-generics/issues/issue-61935.rs | 2 - .../const-generics/issues/issue-61935.stderr | 8 +--- .../ui/const-generics/issues/issue-62504.rs | 3 +- .../const-generics/issues/issue-62504.stderr | 12 +---- .../ui/const-generics/issues/issue-67185-1.rs | 2 - .../issues/issue-67185-1.stderr | 8 +--- .../ui/const-generics/issues/issue-67185-2.rs | 2 - .../issues/issue-67185-2.stderr | 20 +++------ .../ui/const-generics/issues/issue-69654.rs | 12 ++--- .../lazy-normalization/issue-71922.rs | 1 - .../lazy-normalization/issue-71986.rs | 2 +- .../lazy-normalization-feature-gate.rs | 20 --------- .../lazy-normalization-feature-gate.stderr | 44 ------------------- .../const-generics/raw-ptr-const-param.stderr | 8 ++-- .../types-mismatch-const-args.stderr | 12 +++-- .../generic_nondefining_use.stderr | 2 +- 33 files changed, 70 insertions(+), 198 deletions(-) create mode 100644 src/test/ui/const-generics/issues/issue-61336-1.stderr delete mode 100644 src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs delete mode 100644 src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 894b392f1c036..a1dd7a5ca5225 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -559,9 +559,6 @@ declare_features! ( /// Allow negative trait implementations. (active, negative_impls, "1.44.0", Some(68318), None), - /// Lazily evaluate constants. Which allows constants to depend on type parameters. - (active, lazy_normalization_consts, "1.44.0", Some(60471), None), - /// Allows the use of `#[target_feature]` on safe functions. (active, target_feature_11, "1.45.0", Some(69098), None), @@ -584,5 +581,4 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::raw_dylib, sym::const_trait_impl, sym::const_trait_bound_opt_out, - sym::lazy_normalization_consts, ]; diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 415e3262c5093..1d3ddd7e2deff 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -164,15 +164,11 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { return self.unify_const_variable(!a_is_expected, vid, a); } - (ty::ConstKind::Unevaluated(..), _) - if self.tcx.features().lazy_normalization_consts => - { + (ty::ConstKind::Unevaluated(..), _) if self.tcx.features().const_generics => { relation.const_equate_obligation(a, b); return Ok(b); } - (_, ty::ConstKind::Unevaluated(..)) - if self.tcx.features().lazy_normalization_consts => - { + (_, ty::ConstKind::Unevaluated(..)) if self.tcx.features().const_generics => { relation.const_equate_obligation(a, b); return Ok(a); } @@ -662,9 +658,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } - ty::ConstKind::Unevaluated(..) if self.tcx().features().lazy_normalization_consts => { - Ok(c) - } + ty::ConstKind::Unevaluated(..) if self.tcx().features().const_generics => Ok(c), _ => relate::super_relate_consts(self, c, c), } } diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index e67ea56cf8911..e5687db4ff13f 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -988,9 +988,7 @@ where } } } - ty::ConstKind::Unevaluated(..) if self.tcx().features().lazy_normalization_consts => { - Ok(a) - } + ty::ConstKind::Unevaluated(..) if self.tcx().features().const_generics => Ok(a), _ => relate::super_relate_consts(self, a, a), } } diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 914b6d1d29e9c..621a4efc6ccc8 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -432,8 +432,8 @@ pub fn super_relate_tys>( match relation.relate(&sz_a, &sz_b) { Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), // FIXME(lazy_normalization_consts) Implement improved diagnostics for mismatched array - // length? - Err(err) if relation.tcx().features().lazy_normalization_consts => Err(err), + // length? + Err(err) if relation.tcx().features().const_generics => Err(err), Err(err) => { // Check whether the lengths are both concrete/known values, // but are unequal, for better diagnostics. diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index e4318c65050a1..a61647bfd655f 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -411,7 +411,6 @@ symbols! { label_break_value, lang, lang_items, - lazy_normalization_consts, let_chains, lhs, lib, diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 676cb68f60e2d..983e11622f9d5 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -388,7 +388,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if self.selcx.tcx().features().lazy_normalization_consts { + if self.selcx.tcx().features().const_generics { constant } else { let constant = constant.super_fold_with(self); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d16990cb44c49..80740651230de 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1173,7 +1173,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // HACK(eddyb) this provides the correct generics when // `feature(const_generics)` is enabled, so that const expressions // used with const generics, e.g. `Foo<{N+1}>`, can work at all. - if tcx.features().const_generics || tcx.features().lazy_normalization_consts { + if tcx.features().const_generics { Some(parent_def_id.to_def_id()) } else { let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs index 9e32687787ba6..c28875f1752b0 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs @@ -1,6 +1,11 @@ +<<<<<<< HEAD //~^ WARN the feature `const_generics` is incomplete #![feature(lazy_normalization_consts)] //~^ WARN the feature `lazy_normalization_consts` is incomplete +======= +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +>>>>>>> merge lazy_normalization_consts into const_generics #[allow(dead_code)] struct ArithArrayLen([u32; 0 + N]); diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr index 2ebd063af18ac..14cf64eeb7ac6 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr @@ -7,14 +7,8 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash - --> $DIR/array-size-in-generic-struct-param.rs:3:12 - | -LL | #![feature(lazy_normalization_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error: constant expression depends on a generic parameter - --> $DIR/array-size-in-generic-struct-param.rs:7:38 + --> $DIR/array-size-in-generic-struct-param.rs:5:38 | LL | struct ArithArrayLen([u32; 0 + N]); | ^^^^^^^^^^^^ @@ -22,12 +16,12 @@ LL | struct ArithArrayLen([u32; 0 + N]); = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/array-size-in-generic-struct-param.rs:16:5 + --> $DIR/array-size-in-generic-struct-param.rs:14:5 | LL | arr: [u8; CFG.arr_size], | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: this may fail depending on what value the parameter takes -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/different_byref.stderr b/src/test/ui/const-generics/different_byref.stderr index 001d9852a69f8..7eb826b8a36b1 100644 --- a/src/test/ui/const-generics/different_byref.stderr +++ b/src/test/ui/const-generics/different_byref.stderr @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | x = Const::<{ [4] }> {}; | ^^^^^^^^^^^^^^^^^^^ expected `3usize`, found `4usize` | - = note: expected struct `Const<[3usize]>` - found struct `Const<[4usize]>` + = note: expected type `[3usize]` + found type `[4usize]` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 3e07393b9aa89..de41d2984a655 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -11,12 +11,10 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:16:31 | LL | let _: Checked = Checked::; - | ---------------- ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}` - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}` | - = note: expected struct `Checked<{not_one as fn(usize) -> bool}>` - found struct `Checked<{not_two as fn(usize) -> bool}>` + = note: expected type `{not_one as fn(usize) -> bool}` + found type `{not_two as fn(usize) -> bool}` error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:20:24 @@ -37,12 +35,10 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:25:40 | LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic:: as fn(usize) -> bool}`, found `{generic:: as fn(usize) -> bool}` - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic:: as fn(usize) -> bool}`, found `{generic:: as fn(usize) -> bool}` | - = note: expected struct `Checked<{generic:: as fn(usize) -> bool}>` - found struct `Checked<{generic:: as fn(usize) -> bool}>` + = note: expected type `{generic:: as fn(usize) -> bool}` + found type `{generic:: as fn(usize) -> bool}` error: aborting due to 4 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs index 915781bc0fc40..ee92e1019dd9f 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.rs +++ b/src/test/ui/const-generics/issues/issue-61336-1.rs @@ -1,6 +1,7 @@ -//~^ WARN the feature `const_generics` is incomplete #![feature(lazy_normalization_consts)] //~^ WARN the feature `lazy_normalization_consts` is incomplete +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete // build-pass diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61336-1.stderr new file mode 100644 index 0000000000000..34920d8907fc1 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61336-1.stderr @@ -0,0 +1,10 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-61336-1.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs index 934831f91ad9b..76ba795b51c78 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.rs +++ b/src/test/ui/const-generics/issues/issue-61336-2.rs @@ -1,6 +1,7 @@ -//~^ WARN the feature `const_generics` is incomplete #![feature(lazy_normalization_consts)] //~^ WARN the feature `lazy_normalization_consts` is incomplete +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete fn f(x: T) -> [T; N] { [x; { N }] diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr index c779ac10671a6..5f3395223f95d 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr @@ -7,14 +7,8 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash - --> $DIR/issue-61336-2.rs:3:12 - | -LL | #![feature(lazy_normalization_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/issue-61336-2.rs:11:5 + --> $DIR/issue-61336-2.rs:9:5 | LL | [x; { N }] | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` @@ -25,6 +19,6 @@ help: consider restricting type parameter `T` LL | fn g(x: T) -> [T; N] { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr index 7d7cec2c17911..0eee37df3dd52 100644 --- a/src/test/ui/const-generics/issues/issue-61336.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.stderr @@ -7,14 +7,8 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash - --> $DIR/issue-61336.rs:3:12 - | -LL | #![feature(lazy_normalization_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/issue-61336.rs:11:5 + --> $DIR/issue-61336.rs:9:5 | LL | [x; N] | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` @@ -25,6 +19,6 @@ help: consider restricting type parameter `T` LL | fn g(x: T) -> [T; N] { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.stderr index 5eb468cc27263..2e405370dc0df 100644 --- a/src/test/ui/const-generics/issues/issue-61747.stderr +++ b/src/test/ui/const-generics/issues/issue-61747.stderr @@ -7,11 +7,5 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash - --> $DIR/issue-61747.rs:5:12 - | -LL | #![feature(lazy_normalization_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61935.rs b/src/test/ui/const-generics/issues/issue-61935.rs index 445862cccdd89..35fb435b812a4 100644 --- a/src/test/ui/const-generics/issues/issue-61935.rs +++ b/src/test/ui/const-generics/issues/issue-61935.rs @@ -2,8 +2,6 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash trait Foo {} diff --git a/src/test/ui/const-generics/issues/issue-61935.stderr b/src/test/ui/const-generics/issues/issue-61935.stderr index ec0db0401b41c..a8d9bf6a4562f 100644 --- a/src/test/ui/const-generics/issues/issue-61935.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.stderr @@ -6,11 +6,5 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash - --> $DIR/issue-61935.rs:5:12 - | -LL | #![feature(lazy_normalization_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs index 264e693a00828..4e05aadd3930f 100644 --- a/src/test/ui/const-generics/issues/issue-62504.rs +++ b/src/test/ui/const-generics/issues/issue-62504.rs @@ -16,8 +16,7 @@ struct ArrayHolder([u32; X]); impl ArrayHolder { pub const fn new() -> Self { ArrayHolder([0; Self::SIZE]) - //~^ ERROR: mismatched types - //~| ERROR constant expression depends on a generic parameter + //~^ ERROR constant expression depends on a generic parameter } } diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.stderr index 5d45e302888d4..f09af76325e96 100644 --- a/src/test/ui/const-generics/issues/issue-62504.stderr +++ b/src/test/ui/const-generics/issues/issue-62504.stderr @@ -1,12 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/issue-62504.rs:18:21 - | -LL | ArrayHolder([0; Self::SIZE]) - | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` - | - = note: expected array `[u32; X]` - found array `[u32; _]` - error: constant expression depends on a generic parameter --> $DIR/issue-62504.rs:18:25 | @@ -15,6 +6,5 @@ LL | ArrayHolder([0; Self::SIZE]) | = note: this may fail depending on what value the parameter takes -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issues/issue-67185-1.rs b/src/test/ui/const-generics/issues/issue-67185-1.rs index 664dbaeb06791..89e0b7f62da5d 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.rs +++ b/src/test/ui/const-generics/issues/issue-67185-1.rs @@ -2,8 +2,6 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67185-1.stderr b/src/test/ui/const-generics/issues/issue-67185-1.stderr index 2472693afcbaf..ba211caf267e2 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-1.stderr @@ -6,11 +6,5 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash - --> $DIR/issue-67185-1.rs:5:12 - | -LL | #![feature(lazy_normalization_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index 52c8a5c9de809..2732137f59d72 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -1,7 +1,5 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 76d2622e9af0f..2f6b1f1cd47e5 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -6,14 +6,8 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -warning: the feature `lazy_normalization_consts` is incomplete and may cause the compiler to crash - --> $DIR/issue-67185-2.rs:3:12 - | -LL | #![feature(lazy_normalization_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:17:1 + --> $DIR/issue-67185-2.rs:15:1 | LL | / trait Foo LL | | @@ -31,7 +25,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:17:1 + --> $DIR/issue-67185-2.rs:15:1 | LL | / trait Foo LL | | @@ -49,7 +43,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:27:6 + --> $DIR/issue-67185-2.rs:25:6 | LL | trait Foo | --- required by a bound in this @@ -65,7 +59,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:27:6 + --> $DIR/issue-67185-2.rs:25:6 | LL | trait Foo | --- required by a bound in this @@ -81,7 +75,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:31:14 + --> $DIR/issue-67185-2.rs:29:14 | LL | trait Foo | --- required by a bound in this @@ -97,7 +91,7 @@ LL | fn f(_: impl Foo) {} <[u16; 4] as Bar> error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:31:14 + --> $DIR/issue-67185-2.rs:29:14 | LL | trait Foo | --- required by a bound in this @@ -112,6 +106,6 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> -error: aborting due to 6 previous errors; 2 warnings emitted +error: aborting due to 6 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-69654.rs b/src/test/ui/const-generics/issues/issue-69654.rs index 2befbe56d85c7..0afc1a2617eae 100644 --- a/src/test/ui/const-generics/issues/issue-69654.rs +++ b/src/test/ui/const-generics/issues/issue-69654.rs @@ -1,14 +1,14 @@ #![feature(const_generics)] #![allow(incomplete_features)] -trait Bar {} -impl Bar for [u8; O] {} -//~^ ERROR expected value, found type parameter `O` +trait Bar {} +impl Bar for [u8; T] {} +//~^ ERROR expected value, found type parameter `T` -struct Foo {} -impl Foo +struct Foo {} +impl Foo where - [u8; O]: Bar<[(); O]>, + [u8; T]: Bar<[(); T]>, { fn foo() {} } diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71922.rs b/src/test/ui/const-generics/lazy-normalization/issue-71922.rs index 60597b8be620d..36513f94a9e97 100644 --- a/src/test/ui/const-generics/lazy-normalization/issue-71922.rs +++ b/src/test/ui/const-generics/lazy-normalization/issue-71922.rs @@ -1,6 +1,5 @@ // run-pass #![feature(const_generics)] -#![feature(lazy_normalization_consts)] #![allow(incomplete_features)] trait Foo {} diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71986.rs b/src/test/ui/const-generics/lazy-normalization/issue-71986.rs index a07bf2a1a5498..048ed18c927bf 100644 --- a/src/test/ui/const-generics/lazy-normalization/issue-71986.rs +++ b/src/test/ui/const-generics/lazy-normalization/issue-71986.rs @@ -1,6 +1,6 @@ // check-pass #![allow(incomplete_features)] -#![feature(const_generics, lazy_normalization_consts)] +#![feature(const_generics)] pub trait Foo {} pub fn bar>() {} diff --git a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs deleted file mode 100644 index 2c6fbfe65d6e1..0000000000000 --- a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.rs +++ /dev/null @@ -1,20 +0,0 @@ -// gate-test-lazy_normalization_consts -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash -trait Foo {} - -impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} -//~^ ERROR cycle detected - -trait FooImpl {} - -impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {} - -impl FooImpl<{ 0u8 != 0u8 }> for [(); N] {} - -fn foo(_: T) {} - -fn main() { - foo([]); - foo([()]); -} diff --git a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr b/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr deleted file mode 100644 index 9a7844f5e8f10..0000000000000 --- a/src/test/ui/const-generics/lazy-normalization/lazy-normalization-feature-gate.stderr +++ /dev/null @@ -1,44 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/lazy-normalization-feature-gate.rs:2:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0391]: cycle detected when const-evaluating + checking `::{{constant}}#0` - --> $DIR/lazy-normalization-feature-gate.rs:6:58 - | -LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} - | ^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate.rs:6:58 - | -LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} - | ^^^^^^^^^^ -note: ...which requires const-evaluating `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate.rs:6:58 - | -LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} - | ^^^^^^^^^^ -note: ...which requires type-checking `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate.rs:6:58 - | -LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} - | ^^^^^^^^^^ -note: ...which requires processing `::{{constant}}#0`... - --> $DIR/lazy-normalization-feature-gate.rs:6:58 - | -LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} - | ^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `::{{constant}}#0`, completing the cycle -note: cycle used when processing `` - --> $DIR/lazy-normalization-feature-gate.rs:6:1 - | -LL | impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 6644c72236b86..7a665397c1207 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -11,12 +11,10 @@ error[E0308]: mismatched types --> $DIR/raw-ptr-const-param.rs:7:40 | LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; - | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}` - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}` | - = note: expected struct `Const<{0xf as *const u32}>` - found struct `Const<{0xa as *const u32}>` + = note: expected type `{0xf as *const u32}` + found type `{0xa as *const u32}` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/types-mismatch-const-args.stderr b/src/test/ui/const-generics/types-mismatch-const-args.stderr index 2131738554f87..53328c2e89bf4 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.stderr +++ b/src/test/ui/const-generics/types-mismatch-const-args.stderr @@ -11,12 +11,10 @@ error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:13:41 | LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData }; - | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2u32`, found `4u32` - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2u32`, found `4u32` | - = note: expected struct `A<'_, _, 2u32, _>` - found struct `A<'_, _, 4u32, _>` + = note: expected type `2u32` + found type `4u32` error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:15:41 @@ -26,8 +24,8 @@ LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data | | | expected due to this | - = note: expected struct `A<'a, u16, _, _>` - found struct `A<'b, u32, _, _>` + = note: expected struct `A<'a, u16, {2u32}, {3u32}>` + found struct `A<'b, u32, {2u32}, {3u32}>` error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index b0ffc4a5ef61d..88f8dbe1a7d72 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -25,7 +25,7 @@ error: non-defining opaque type use in defining scope LL | fn concrete_const() -> OneConst<{123}> { | ^^^^^^^^^^^^^^^ | -note: used non-generic constant `123usize` for generic parameter +note: used non-generic constant `{123}` for generic parameter --> $DIR/generic_nondefining_use.rs:10:21 | LL | type OneConst = impl Debug; From 0f7bf5d9e11189dfbc10bc2acba653c4893c9b6c Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 8 May 2020 21:10:33 +0200 Subject: [PATCH 11/16] add docs --- src/librustc_middle/ty/relate.rs | 2 +- src/librustc_mir/borrow_check/type_check/relate_tys.rs | 2 ++ src/librustc_trait_selection/traits/object_safety.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 621a4efc6ccc8..0ae62b0e813af 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -431,7 +431,7 @@ pub fn super_relate_tys>( let t = relation.relate(&a_t, &b_t)?; match relation.relate(&sz_a, &sz_b) { Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), - // FIXME(lazy_normalization_consts) Implement improved diagnostics for mismatched array + // FIXME(#72219) Implement improved diagnostics for mismatched array // length? Err(err) if relation.tcx().features().const_generics => Err(err), Err(err) => { diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index c3b0bd82398cb..7ff12820db815 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -99,6 +99,8 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { } } + // We don't have to worry about the equality of consts during borrow checking + // as consts always have a static lifetime. fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {} fn normalization() -> NormalizationStrategy { diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index a34006dd4fc06..1bfcacd6ccdc1 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -771,7 +771,7 @@ fn contains_illegal_self_type_reference<'tcx>( } fn visit_const(&mut self, _c: &ty::Const<'tcx>) -> bool { - // FIXME Look into the unevaluated constants for object safety violations. + // FIXME(#72219) Look into the unevaluated constants for object safety violations. // Do not walk substitutions of unevaluated consts, as they contain `Self`, even // though the const expression doesn't necessary use it. Currently type variables // inside array length expressions are forbidden, so they can't break the above diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 02b42284e6dea..d72c74e4188ee 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1651,7 +1651,7 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId, fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { if let ty::ConstKind::Unevaluated(..) = c.val { - // FIXME(lazy_normalization_consts) We currenctly don't detect lifetimes within substs + // FIXME(#72219) We currenctly don't detect lifetimes within substs // which would violate this check. Even though the particular substitution is not used // within the const, this should still be fixed. return false; From 3d7637e66de5dea270d729c4bbea1237b140e246 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 8 May 2020 23:13:49 +0200 Subject: [PATCH 12/16] correctly handle escaping bound variables --- src/librustc_infer/infer/combine.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 1d3ddd7e2deff..e3e8e88993ea7 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -39,7 +39,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; +use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::{Span, DUMMY_SP}; @@ -165,11 +165,19 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { return self.unify_const_variable(!a_is_expected, vid, a); } (ty::ConstKind::Unevaluated(..), _) if self.tcx.features().const_generics => { - relation.const_equate_obligation(a, b); + // FIXME(#59490): Need to remove the leak check to accomodate + // escaping bound variables here. + if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { + relation.const_equate_obligation(a, b); + } return Ok(b); } (_, ty::ConstKind::Unevaluated(..)) if self.tcx.features().const_generics => { - relation.const_equate_obligation(a, b); + // FIXME(#59490): Need to remove the leak check to accomodate + // escaping bound variables here. + if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { + relation.const_equate_obligation(a, b); + } return Ok(a); } _ => {} From c71439791cd4b5faeb8e1de654e7557855b16c19 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 12 May 2020 10:53:20 +0200 Subject: [PATCH 13/16] chalk --- src/librustc_traits/chalk/lowering.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index aacbd311d1dec..184b9a9dc1040 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -126,9 +126,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment { - bug!("unexpected predicate {}", predicate) - } + | ty::Predicate::ConstEvaluatable(..) + | ty::Predicate::ConstEquate(..) => bug!("unexpected predicate {}", predicate), } } ChalkEnvironmentClause::TypeFromEnv(ty) => Some( @@ -192,9 +191,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi Predicate::ObjectSafe(..) | Predicate::ClosureKind(..) | Predicate::Subtype(..) - | Predicate::ConstEvaluatable(..) => { - chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)) - } + | Predicate::ConstEvaluatable(..) + | Predicate::ConstEquate(..) => chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)), } } } @@ -459,7 +457,8 @@ impl<'tcx> LowerInto<'tcx, Option bug!("unexpected predicate {}", &self), + | Predicate::ConstEvaluatable(..) + | Predicate::ConstEquate(..) => bug!("unexpected predicate {}", &self), } } } From 752d8a24d89b8fd6a4910d857b79c91ee0c3c250 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 12 May 2020 10:55:11 +0200 Subject: [PATCH 14/16] the best way to fix bugs is by ignoring them --- .../ui/const-generics/issues/issue-69654.rs | 18 ------------------ .../const-generics/issues/issue-69654.stderr | 14 -------------- 2 files changed, 32 deletions(-) delete mode 100644 src/test/ui/const-generics/issues/issue-69654.rs delete mode 100644 src/test/ui/const-generics/issues/issue-69654.stderr diff --git a/src/test/ui/const-generics/issues/issue-69654.rs b/src/test/ui/const-generics/issues/issue-69654.rs deleted file mode 100644 index 0afc1a2617eae..0000000000000 --- a/src/test/ui/const-generics/issues/issue-69654.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(const_generics)] -#![allow(incomplete_features)] - -trait Bar {} -impl Bar for [u8; T] {} -//~^ ERROR expected value, found type parameter `T` - -struct Foo {} -impl Foo -where - [u8; T]: Bar<[(); T]>, -{ - fn foo() {} -} - -fn main() { - Foo::foo(); -} diff --git a/src/test/ui/const-generics/issues/issue-69654.stderr b/src/test/ui/const-generics/issues/issue-69654.stderr deleted file mode 100644 index 9d52603f462be..0000000000000 --- a/src/test/ui/const-generics/issues/issue-69654.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0423]: expected value, found type parameter `O` - --> $DIR/issue-69654.rs:5:25 - | -LL | impl Bar for [u8; O] {} - | ^ help: a tuple variant with a similar name exists: `Ok` - | - ::: $SRC_DIR/libcore/result.rs:LL:COL - | -LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), - | --------------------------------------------------- similarly named tuple variant `Ok` defined here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0423`. From 6a72ba4c33472060a96b17378be58d45570eb4a8 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 17 May 2020 10:36:56 +0200 Subject: [PATCH 15/16] Logically seperate lazy norm from `const_generics` --- src/librustc_infer/infer/combine.rs | 6 +++--- src/librustc_infer/infer/nll_relate/mod.rs | 2 +- src/librustc_middle/ty/context.rs | 9 ++++++++- src/librustc_middle/ty/relate.rs | 2 +- src/librustc_trait_selection/traits/project.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index e3e8e88993ea7..3467457b44997 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -164,7 +164,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { return self.unify_const_variable(!a_is_expected, vid, a); } - (ty::ConstKind::Unevaluated(..), _) if self.tcx.features().const_generics => { + (ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => { // FIXME(#59490): Need to remove the leak check to accomodate // escaping bound variables here. if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { @@ -172,7 +172,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { } return Ok(b); } - (_, ty::ConstKind::Unevaluated(..)) if self.tcx.features().const_generics => { + (_, ty::ConstKind::Unevaluated(..)) if self.tcx.lazy_normalization() => { // FIXME(#59490): Need to remove the leak check to accomodate // escaping bound variables here. if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { @@ -666,7 +666,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } - ty::ConstKind::Unevaluated(..) if self.tcx().features().const_generics => Ok(c), + ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(c), _ => relate::super_relate_consts(self, c, c), } } diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index e5687db4ff13f..8de8925100608 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -988,7 +988,7 @@ where } } } - ty::ConstKind::Unevaluated(..) if self.tcx().features().const_generics => Ok(a), + ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a), _ => relate::super_relate_consts(self, a, a), } } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 7feb080d4b8d4..da413f19eff23 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1339,7 +1339,7 @@ impl<'tcx> TyCtxt<'tcx> { /// What mode(s) of borrowck should we run? AST? MIR? both? /// (Also considers the `#![feature(nll)]` setting.) - pub fn borrowck_mode(&self) -> BorrowckMode { + pub fn borrowck_mode(self) -> BorrowckMode { // Here are the main constraints we need to deal with: // // 1. An opts.borrowck_mode of `BorrowckMode::Migrate` is @@ -1369,6 +1369,13 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.opts.borrowck_mode } + /// If `true`, we should use lazy normalization for constants, otherwise + /// we still evaluate them eagerly. + #[inline] + pub fn lazy_normalization(self) -> bool { + self.features().const_generics + } + #[inline] pub fn local_crate_exports_generics(self) -> bool { debug_assert!(self.sess.opts.share_generics()); diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 0ae62b0e813af..594ffbcd83613 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -433,7 +433,7 @@ pub fn super_relate_tys>( Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), // FIXME(#72219) Implement improved diagnostics for mismatched array // length? - Err(err) if relation.tcx().features().const_generics => Err(err), + Err(err) if relation.tcx().lazy_normalization() => Err(err), Err(err) => { // Check whether the lengths are both concrete/known values, // but are unequal, for better diagnostics. diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 983e11622f9d5..c4cb72fa08c08 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -388,7 +388,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if self.selcx.tcx().features().const_generics { + if self.selcx.tcx().lazy_normalization() { constant } else { let constant = constant.super_fold_with(self); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 80740651230de..7cfb89f3ff048 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1173,7 +1173,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // HACK(eddyb) this provides the correct generics when // `feature(const_generics)` is enabled, so that const expressions // used with const generics, e.g. `Foo<{N+1}>`, can work at all. - if tcx.features().const_generics { + if tcx.lazy_normalization() { Some(parent_def_id.to_def_id()) } else { let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); From 9da8a5ba6848cf246995b985b0982a7a9aa44890 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 17 May 2020 11:42:41 +0200 Subject: [PATCH 16/16] update tests --- .../const-generics/array-size-in-generic-struct-param.rs | 8 +------- src/test/ui/const-generics/issues/issue-61336-1.rs | 2 -- src/test/ui/const-generics/issues/issue-61336-1.stderr | 3 ++- src/test/ui/const-generics/issues/issue-61336-2.rs | 2 -- src/test/ui/const-generics/issues/issue-61336.rs | 2 -- src/test/ui/const-generics/issues/issue-61747.rs | 2 -- src/test/ui/const-generics/issues/issue-61935.rs | 2 +- src/test/ui/const-generics/issues/issue-61935.stderr | 1 + src/test/ui/const-generics/issues/issue-67185-1.rs | 2 +- src/test/ui/const-generics/issues/issue-67185-1.stderr | 3 ++- src/test/ui/const-generics/issues/issue-67185-2.rs | 2 +- src/test/ui/const-generics/issues/issue-67185-2.stderr | 3 ++- 12 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs index c28875f1752b0..5c02e585dc8ba 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs @@ -1,11 +1,5 @@ -<<<<<<< HEAD -//~^ WARN the feature `const_generics` is incomplete -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete -======= #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash ->>>>>>> merge lazy_normalization_consts into const_generics +//~^ WARN the feature `const_generics` is incomplete #[allow(dead_code)] struct ArithArrayLen([u32; 0 + N]); diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs index ee92e1019dd9f..2135c868bbc70 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.rs +++ b/src/test/ui/const-generics/issues/issue-61336-1.rs @@ -1,5 +1,3 @@ -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61336-1.stderr index 34920d8907fc1..b2c69d57c40b7 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-1.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61336-1.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs index 76ba795b51c78..52969056f00a5 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.rs +++ b/src/test/ui/const-generics/issues/issue-61336-2.rs @@ -1,5 +1,3 @@ -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs index 6baee0c0a7f18..eb0f309762764 100644 --- a/src/test/ui/const-generics/issues/issue-61336.rs +++ b/src/test/ui/const-generics/issues/issue-61336.rs @@ -1,7 +1,5 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete fn f(x: T) -> [T; N] { [x; N] diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs index 0e185b53c1947..9e0572d3568cb 100644 --- a/src/test/ui/const-generics/issues/issue-61747.rs +++ b/src/test/ui/const-generics/issues/issue-61747.rs @@ -2,8 +2,6 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete -#![feature(lazy_normalization_consts)] -//~^ WARN the feature `lazy_normalization_consts` is incomplete struct Const; diff --git a/src/test/ui/const-generics/issues/issue-61935.rs b/src/test/ui/const-generics/issues/issue-61935.rs index 35fb435b812a4..5c987e63a9e07 100644 --- a/src/test/ui/const-generics/issues/issue-61935.rs +++ b/src/test/ui/const-generics/issues/issue-61935.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait Foo {} diff --git a/src/test/ui/const-generics/issues/issue-61935.stderr b/src/test/ui/const-generics/issues/issue-61935.stderr index a8d9bf6a4562f..cf0c0e24a7604 100644 --- a/src/test/ui/const-generics/issues/issue-61935.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.stderr @@ -1,4 +1,5 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-61935.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-67185-1.rs b/src/test/ui/const-generics/issues/issue-67185-1.rs index 89e0b7f62da5d..b08057851a1ba 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.rs +++ b/src/test/ui/const-generics/issues/issue-67185-1.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67185-1.stderr b/src/test/ui/const-generics/issues/issue-67185-1.stderr index ba211caf267e2..9cc797d6d8a01 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-1.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-67185-1.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index 2732137f59d72..111b718dd5efd 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 2f6b1f1cd47e5..7d947a907a0ee 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-67185-2.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:15:1