From c81935e6dfd3877db266f0a01d9323f203f92eda Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 6 Aug 2020 10:00:08 +0200 Subject: [PATCH 1/7] make `ConstEvaluatable` more strict --- compiler/rustc_middle/src/mir/mod.rs | 27 ++++++++-- .../src/traits/fulfill.rs | 18 ++++--- .../rustc_trait_selection/src/traits/mod.rs | 1 + .../src/traits/select/mod.rs | 20 +++---- .../traits/const_evaluatable.rs | 54 +++++++++++++++++++ .../ui/const_evaluatable/associated_const.rs | 11 ++++ .../issue-70453-polymorphic-ctfe.rs | 3 +- .../issue-70453-polymorphic-ctfe.stderr | 10 ++++ src/test/ui/impl-trait/issue-56445.rs | 3 +- .../lazy_normalization_consts/issue-73980.rs | 2 +- .../issue-73980.stderr | 10 ++++ 11 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 src/librustc_trait_selection/traits/const_evaluatable.rs create mode 100644 src/test/ui/const_evaluatable/associated_const.rs create mode 100644 src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr create mode 100644 src/test/ui/lazy_normalization_consts/issue-73980.stderr diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 96e2a0ba618a3..197e8dd534112 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -186,6 +186,19 @@ pub struct Body<'tcx> { /// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components. pub ignore_interior_mut_in_const_validation: bool, + /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check. + /// + /// Note that this does not actually mean that this body is not computable right now. + /// The repeat count in the following example is polymorphic, but can still be evaluated + /// without knowing anything about the type parameter `T`. + /// + /// ```rust + /// fn test() { + /// let _ = [0; std::mem::size_of::<*mut T>()]; + /// } + /// ``` + pub is_polymorphic: bool, + predecessor_cache: PredecessorCache, } @@ -208,7 +221,7 @@ impl<'tcx> Body<'tcx> { local_decls.len() ); - Body { + let mut body = Body { phase: MirPhase::Build, basic_blocks, source_scopes, @@ -224,8 +237,11 @@ impl<'tcx> Body<'tcx> { span, required_consts: Vec::new(), ignore_interior_mut_in_const_validation: false, + is_polymorphic: false, predecessor_cache: PredecessorCache::new(), - } + }; + body.is_polymorphic = body.has_param_types_or_consts(); + body } /// Returns a partially initialized MIR body containing only a list of basic blocks. @@ -234,7 +250,7 @@ impl<'tcx> Body<'tcx> { /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different /// crate. pub fn new_cfg_only(basic_blocks: IndexVec>) -> Self { - Body { + let mut body = Body { phase: MirPhase::Build, basic_blocks, source_scopes: IndexVec::new(), @@ -250,8 +266,11 @@ impl<'tcx> Body<'tcx> { generator_kind: None, var_debug_info: Vec::new(), ignore_interior_mut_in_const_validation: false, + is_polymorphic: false, predecessor_cache: PredecessorCache::new(), - } + }; + body.is_polymorphic = body.has_param_types_or_consts(); + body } #[inline] diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index a5c6dc042abc3..989c6e6dbc215 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable}; use std::marker::PhantomData; +use super::const_evaluatable; use super::project; use super::select::SelectionContext; use super::wf; @@ -458,16 +459,17 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } ty::PredicateAtom::ConstEvaluatable(def_id, substs) => { - match self.selcx.infcx().const_eval_resolve( - obligation.param_env, + const_evaluatable::is_const_evaluatable( + self.selcx.infcx(), def_id, substs, - None, - Some(obligation.cause.span), - ) { - Ok(_) => ProcessResult::Changed(vec![]), - Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))), - } + obligation.param_env, + obligation.cause.span, + ) + .map_or_else( + |e| ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))), + |()| ProcessResult::Changed(vec![]), + ) } ty::PredicateAtom::ConstEquate(c1, c2) => { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index fe406e88c5260..49dac873cde2d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -7,6 +7,7 @@ pub mod auto_trait; mod chalk_fulfill; pub mod codegen; mod coherence; +mod const_evaluatable; mod engine; pub mod error_reporting; mod fulfill; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4258d8e3010a4..5a1e1eb89a60c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -6,6 +6,7 @@ use self::EvaluationResult::*; use self::SelectionCandidate::*; use super::coherence::{self, Conflict}; +use super::const_evaluatable; use super::project; use super::project::normalize_with_depth_to; use super::util; @@ -542,17 +543,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateAtom::ConstEvaluatable(def_id, substs) => { - match self.tcx().const_eval_resolve( - obligation.param_env, + const_evaluatable::is_const_evaluatable( + self.infcx, def_id, substs, - None, - None, - ) { - Ok(_) => Ok(EvaluatedToOk), - Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig), - Err(_) => Ok(EvaluatedToErr), - } + obligation.param_env, + obligation.cause.span, + ) + .map(|()| EvaluatedToOk) + .or_else(|e| match e { + ErrorHandled::TooGeneric => Ok(EvaluatedToAmbig), + _ => Ok(EvaluatedToErr), + }) } ty::PredicateAtom::ConstEquate(c1, c2) => { diff --git a/src/librustc_trait_selection/traits/const_evaluatable.rs b/src/librustc_trait_selection/traits/const_evaluatable.rs new file mode 100644 index 0000000000000..eb0e7f16fa37a --- /dev/null +++ b/src/librustc_trait_selection/traits/const_evaluatable.rs @@ -0,0 +1,54 @@ +use rustc_middle::ty::{self, TypeFoldable}; +use rustc_infer::infer::InferCtxt; +use rustc_middle::ty::subst::SubstsRef; +use rustc_span::Span; +use rustc_span::def_id::DefId; +use rustc_middle::mir::interpret::ErrorHandled; +use rustc_hir::def::DefKind; + +pub fn is_const_evaluatable<'cx, 'tcx>( + infcx: &InferCtxt<'cx, 'tcx>, + def: ty::WithOptConstParam, + substs: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + span: Span, +) -> Result<(), ErrorHandled> +{ + let def_kind = infcx.tcx.def_kind(def.did); + match def_kind { + DefKind::AnonConst => { + let mir_body = if let Some(def) = def.as_const_arg() { + infcx.tcx.optimized_mir_of_const_arg(def) + } else { + infcx.tcx.optimized_mir(def.did) + }; + if mir_body.is_polymorphic { + return Err(ErrorHandled::TooGeneric); + } + } + _ => { + if substs.has_param_types_or_consts() { + return Err(ErrorHandled::TooGeneric); + } + } + } + + match infcx.const_eval_resolve( + param_env, + def, + substs, + None, + Some(span), + ) { + Ok(_) => Ok(()), + Err(err) => { + if matches!(err, ErrorHandled::TooGeneric) { + infcx.tcx.sess.delay_span_bug( + span, + &format!("ConstEvaluatable too generic: {:?}, {:?}, {:?}", def, substs, param_env), + ); + } + Err(err) + } + } +} \ No newline at end of file diff --git a/src/test/ui/const_evaluatable/associated_const.rs b/src/test/ui/const_evaluatable/associated_const.rs new file mode 100644 index 0000000000000..a6777632254b7 --- /dev/null +++ b/src/test/ui/const_evaluatable/associated_const.rs @@ -0,0 +1,11 @@ +// check-pass +struct Foo(T); +impl Foo { + const VALUE: usize = std::mem::size_of::(); +} + +fn test() { + let _ = [0; Foo::::VALUE]; +} + +fn main() {} diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs index 5a528379b0414..5fe526df5a741 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -1,5 +1,3 @@ -// run-pass - #![feature(arbitrary_enum_discriminant, core_intrinsics)] extern crate core; @@ -9,6 +7,7 @@ use core::intrinsics::discriminant_value; enum MyWeirdOption { None = 0, Some(T) = core::mem::size_of::<*mut T>(), + //~^ ERROR constant expression depends on a generic parameter } fn main() { diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr new file mode 100644 index 0000000000000..9aba2ea543f4c --- /dev/null +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-70453-polymorphic-ctfe.rs:9:15 + | +LL | Some(T) = core::mem::size_of::<*mut T>(), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/issue-56445.rs b/src/test/ui/impl-trait/issue-56445.rs index a34d7bae3a6ca..6dd1648c9b84c 100644 --- a/src/test/ui/impl-trait/issue-56445.rs +++ b/src/test/ui/impl-trait/issue-56445.rs @@ -5,8 +5,7 @@ use std::marker::PhantomData; -pub struct S<'a> -{ +pub struct S<'a> { pub m1: PhantomData<&'a u8>, pub m2: [u8; S::size()], } diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.rs b/src/test/ui/lazy_normalization_consts/issue-73980.rs index 339b22c0b423d..2e4cb9ff7a825 100644 --- a/src/test/ui/lazy_normalization_consts/issue-73980.rs +++ b/src/test/ui/lazy_normalization_consts/issue-73980.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(lazy_normalization_consts)] #![allow(incomplete_features)] @@ -10,5 +9,6 @@ impl L { } impl X::S]> {} +//~^ ERROR constant expression depends on a generic parameter fn main() {} diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.stderr b/src/test/ui/lazy_normalization_consts/issue-73980.stderr new file mode 100644 index 0000000000000..5ca11bf55fc58 --- /dev/null +++ b/src/test/ui/lazy_normalization_consts/issue-73980.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-73980.rs:11:9 + | +LL | impl X::S]> {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + From ef6100e846f215b92f0d3b951557ed2528000f61 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 6 Aug 2020 10:48:36 +0200 Subject: [PATCH 2/7] convert to future compat lint --- compiler/rustc_session/src/lint/builtin.rs | 11 ++++ .../traits/const_evaluatable.rs | 65 ++++++++++--------- .../issue-70453-polymorphic-ctfe.rs | 4 +- .../issue-70453-polymorphic-ctfe.stderr | 10 +-- .../lazy_normalization_consts/issue-73980.rs | 4 +- .../issue-73980.stderr | 10 +-- 6 files changed, 65 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs index 2db4d2a7f51d9..66497df66cad5 100644 --- a/compiler/rustc_session/src/lint/builtin.rs +++ b/compiler/rustc_session/src/lint/builtin.rs @@ -539,6 +539,16 @@ declare_lint! { }; } +declare_lint! { + pub CONST_EVALUATABLE_UNCHECKED, + Warn, + "detects a generic constant is used in a type without a emitting a warning", + @future_incompatible = FutureIncompatibleInfo { + reference: "TODO", + edition: None, + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -612,6 +622,7 @@ declare_lint_pass! { UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, CENUM_IMPL_DROP_CAST, + CONST_EVALUATABLE_UNCHECKED, ] } diff --git a/src/librustc_trait_selection/traits/const_evaluatable.rs b/src/librustc_trait_selection/traits/const_evaluatable.rs index eb0e7f16fa37a..87762cc43a199 100644 --- a/src/librustc_trait_selection/traits/const_evaluatable.rs +++ b/src/librustc_trait_selection/traits/const_evaluatable.rs @@ -1,10 +1,11 @@ -use rustc_middle::ty::{self, TypeFoldable}; +use rustc_hir::def::DefKind; use rustc_infer::infer::InferCtxt; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::subst::SubstsRef; -use rustc_span::Span; +use rustc_middle::ty::{self, TypeFoldable}; +use rustc_session::lint; use rustc_span::def_id::DefId; -use rustc_middle::mir::interpret::ErrorHandled; -use rustc_hir::def::DefKind; +use rustc_span::Span; pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, @@ -12,8 +13,31 @@ pub fn is_const_evaluatable<'cx, 'tcx>( substs: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, -) -> Result<(), ErrorHandled> -{ +) -> Result<(), ErrorHandled> { + let future_compat_lint = || { + if let Some(local_def_id) = def.did.as_local() { + infcx.tcx.struct_span_lint_hir( + lint::builtin::CONST_EVALUATABLE_UNCHECKED, + infcx.tcx.hir().as_local_hir_id(local_def_id), + span, + |err| { + err.build("cannot use constants which depend on generic parameters in types") + .emit(); + }, + ); + } + }; + + // FIXME: We should only try to evaluate a given constant here if it is fully concrete + // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`. + // + // We previously did not check this, so we only emit a future compat warning if + // const evaluation succeeds and the given constant is still polymorphic for now + // and hopefully soon change this to an error. + // + // See #74595 for more details about this. + let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span)); + let def_kind = infcx.tcx.def_kind(def.did); match def_kind { DefKind::AnonConst => { @@ -22,33 +46,16 @@ pub fn is_const_evaluatable<'cx, 'tcx>( } else { infcx.tcx.optimized_mir(def.did) }; - if mir_body.is_polymorphic { - return Err(ErrorHandled::TooGeneric); + if mir_body.is_polymorphic && concrete.is_ok() { + future_compat_lint(); } } _ => { - if substs.has_param_types_or_consts() { - return Err(ErrorHandled::TooGeneric); + if substs.has_param_types_or_consts() && concrete.is_ok() { + future_compat_lint(); } } } - match infcx.const_eval_resolve( - param_env, - def, - substs, - None, - Some(span), - ) { - Ok(_) => Ok(()), - Err(err) => { - if matches!(err, ErrorHandled::TooGeneric) { - infcx.tcx.sess.delay_span_bug( - span, - &format!("ConstEvaluatable too generic: {:?}, {:?}, {:?}", def, substs, param_env), - ); - } - Err(err) - } - } -} \ No newline at end of file + concrete.map(drop) +} diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs index 5fe526df5a741..cdc1db4c0b482 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -1,3 +1,4 @@ +// run-pass #![feature(arbitrary_enum_discriminant, core_intrinsics)] extern crate core; @@ -7,7 +8,8 @@ use core::intrinsics::discriminant_value; enum MyWeirdOption { None = 0, Some(T) = core::mem::size_of::<*mut T>(), - //~^ ERROR constant expression depends on a generic parameter + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out } fn main() { diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr index 9aba2ea543f4c..2aeb1b32bcb0a 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr @@ -1,10 +1,12 @@ -error: constant expression depends on a generic parameter - --> $DIR/issue-70453-polymorphic-ctfe.rs:9:15 +warning: cannot use constants which depend on generic parameters in types + --> $DIR/issue-70453-polymorphic-ctfe.rs:10:15 | LL | Some(T) = core::mem::size_of::<*mut T>(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this may fail depending on what value the parameter takes + = note: `#[warn(const_evaluatable_unchecked)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see TODO -error: aborting due to previous error +warning: 1 warning emitted diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.rs b/src/test/ui/lazy_normalization_consts/issue-73980.rs index 2e4cb9ff7a825..e10040652c78d 100644 --- a/src/test/ui/lazy_normalization_consts/issue-73980.rs +++ b/src/test/ui/lazy_normalization_consts/issue-73980.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(lazy_normalization_consts)] #![allow(incomplete_features)] @@ -9,6 +10,7 @@ impl L { } impl X::S]> {} -//~^ ERROR constant expression depends on a generic parameter +//~^ WARN cannot use constants which depend on generic parameters +//~| WARN this was previously accepted by the compiler but is being phased out fn main() {} diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.stderr b/src/test/ui/lazy_normalization_consts/issue-73980.stderr index 5ca11bf55fc58..8636407a3a102 100644 --- a/src/test/ui/lazy_normalization_consts/issue-73980.stderr +++ b/src/test/ui/lazy_normalization_consts/issue-73980.stderr @@ -1,10 +1,12 @@ -error: constant expression depends on a generic parameter - --> $DIR/issue-73980.rs:11:9 +warning: cannot use constants which depend on generic parameters in types + --> $DIR/issue-73980.rs:12:9 | LL | impl X::S]> {} | ^^^^^^^^^^^^^^^^^^^^^ | - = note: this may fail depending on what value the parameter takes + = note: `#[warn(const_evaluatable_unchecked)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see TODO -error: aborting due to previous error +warning: 1 warning emitted From c10ad0d888df19e7185e15f811fdb011278f3c20 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 6 Aug 2020 22:12:21 +0200 Subject: [PATCH 3/7] review --- compiler/rustc_middle/src/mir/mod.rs | 4 ++++ .../rustc_trait_selection/src/traits/fulfill.rs | 11 +++++------ .../rustc_trait_selection/src/traits/select/mod.rs | 13 ++++++------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 197e8dd534112..3c041bbc0aedd 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -197,6 +197,10 @@ pub struct Body<'tcx> { /// let _ = [0; std::mem::size_of::<*mut T>()]; /// } /// ``` + /// + /// **WARNING**: Do not change this flags after the MIR was originally created, even if an optimization + /// removed the last mention of all generic params. We do not want to rely on optimizations and + /// potentially allow things like `[u8; std::mem::size_of::() * 0]` due to this. pub is_polymorphic: bool, predecessor_cache: PredecessorCache, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 989c6e6dbc215..4818022bf6202 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -459,17 +459,16 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } ty::PredicateAtom::ConstEvaluatable(def_id, substs) => { - const_evaluatable::is_const_evaluatable( + match const_evaluatable::is_const_evaluatable( self.selcx.infcx(), def_id, substs, obligation.param_env, obligation.cause.span, - ) - .map_or_else( - |e| ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))), - |()| ProcessResult::Changed(vec![]), - ) + ) { + Ok(()) => ProcessResult::Changed(vec![]), + Err(e) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))), + } } ty::PredicateAtom::ConstEquate(c1, c2) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5a1e1eb89a60c..7e8e2baa8a13d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -543,18 +543,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateAtom::ConstEvaluatable(def_id, substs) => { - const_evaluatable::is_const_evaluatable( + match const_evaluatable::is_const_evaluatable( self.infcx, def_id, substs, obligation.param_env, obligation.cause.span, - ) - .map(|()| EvaluatedToOk) - .or_else(|e| match e { - ErrorHandled::TooGeneric => Ok(EvaluatedToAmbig), - _ => Ok(EvaluatedToErr), - }) + ) { + Ok(()) => Ok(EvaluatedToOk), + Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig), + Err(_) => Ok(EvaluatedToErr), + } } ty::PredicateAtom::ConstEquate(c1, c2) => { From 78046448638c8db12db51b8f7bbbe29860d79c4e Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 6 Aug 2020 22:32:12 +0200 Subject: [PATCH 4/7] add tests --- ...{associated_const.rs => associated-const.rs} | 0 src/test/ui/const_evaluatable/function-call.rs | 17 +++++++++++++++++ .../ui/const_evaluatable/function-call.stderr | 12 ++++++++++++ 3 files changed, 29 insertions(+) rename src/test/ui/const_evaluatable/{associated_const.rs => associated-const.rs} (100%) create mode 100644 src/test/ui/const_evaluatable/function-call.rs create mode 100644 src/test/ui/const_evaluatable/function-call.stderr diff --git a/src/test/ui/const_evaluatable/associated_const.rs b/src/test/ui/const_evaluatable/associated-const.rs similarity index 100% rename from src/test/ui/const_evaluatable/associated_const.rs rename to src/test/ui/const_evaluatable/associated-const.rs diff --git a/src/test/ui/const_evaluatable/function-call.rs b/src/test/ui/const_evaluatable/function-call.rs new file mode 100644 index 0000000000000..b13a0369a00eb --- /dev/null +++ b/src/test/ui/const_evaluatable/function-call.rs @@ -0,0 +1,17 @@ +// check-pass + +const fn foo() -> usize { + if std::mem::size_of::<*mut T>() < 8 { // size of *mut T does not depend on T + std::mem::size_of::() + } else { + 8 + } +} + +fn test() { + let _ = [0; foo::()]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + +fn main() {} diff --git a/src/test/ui/const_evaluatable/function-call.stderr b/src/test/ui/const_evaluatable/function-call.stderr new file mode 100644 index 0000000000000..5240015c37a34 --- /dev/null +++ b/src/test/ui/const_evaluatable/function-call.stderr @@ -0,0 +1,12 @@ +warning: cannot use constants which depend on generic parameters in types + --> $DIR/function-call.rs:12:17 + | +LL | let _ = [0; foo::()]; + | ^^^^^^^^^^ + | + = note: `#[warn(const_evaluatable_unchecked)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see TODO + +warning: 1 warning emitted + From 1dd00e60b92cba4a84da0946ef63346e12ebd3d2 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 1 Sep 2020 16:17:41 +0200 Subject: [PATCH 5/7] add tracking issue, fix rebase --- compiler/rustc_session/src/lint/builtin.rs | 2 +- .../rustc_trait_selection/src}/traits/const_evaluatable.rs | 2 +- src/test/ui/const_evaluatable/function-call.stderr | 2 +- .../ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr | 2 +- src/test/ui/lazy_normalization_consts/issue-73980.stderr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename {src/librustc_trait_selection => compiler/rustc_trait_selection/src}/traits/const_evaluatable.rs (96%) diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs index 66497df66cad5..2bcf10b8b3878 100644 --- a/compiler/rustc_session/src/lint/builtin.rs +++ b/compiler/rustc_session/src/lint/builtin.rs @@ -544,7 +544,7 @@ declare_lint! { Warn, "detects a generic constant is used in a type without a emitting a warning", @future_incompatible = FutureIncompatibleInfo { - reference: "TODO", + reference: "issue #76200 ", edition: None, }; } diff --git a/src/librustc_trait_selection/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs similarity index 96% rename from src/librustc_trait_selection/traits/const_evaluatable.rs rename to compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 87762cc43a199..013cd71ea305d 100644 --- a/src/librustc_trait_selection/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -18,7 +18,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( if let Some(local_def_id) = def.did.as_local() { infcx.tcx.struct_span_lint_hir( lint::builtin::CONST_EVALUATABLE_UNCHECKED, - infcx.tcx.hir().as_local_hir_id(local_def_id), + infcx.tcx.hir().local_def_id_to_hir_id(local_def_id), span, |err| { err.build("cannot use constants which depend on generic parameters in types") diff --git a/src/test/ui/const_evaluatable/function-call.stderr b/src/test/ui/const_evaluatable/function-call.stderr index 5240015c37a34..a15637196062f 100644 --- a/src/test/ui/const_evaluatable/function-call.stderr +++ b/src/test/ui/const_evaluatable/function-call.stderr @@ -6,7 +6,7 @@ LL | let _ = [0; foo::()]; | = note: `#[warn(const_evaluatable_unchecked)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see TODO + = note: for more information, see issue #76200 warning: 1 warning emitted diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr index 2aeb1b32bcb0a..906927e705ee8 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr @@ -6,7 +6,7 @@ LL | Some(T) = core::mem::size_of::<*mut T>(), | = note: `#[warn(const_evaluatable_unchecked)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see TODO + = note: for more information, see issue #76200 warning: 1 warning emitted diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.stderr b/src/test/ui/lazy_normalization_consts/issue-73980.stderr index 8636407a3a102..5ed1ca362f411 100644 --- a/src/test/ui/lazy_normalization_consts/issue-73980.stderr +++ b/src/test/ui/lazy_normalization_consts/issue-73980.stderr @@ -6,7 +6,7 @@ LL | impl X::S]> {} | = note: `#[warn(const_evaluatable_unchecked)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see TODO + = note: for more information, see issue #76200 warning: 1 warning emitted From 4226a17845333e3c0495bd85e5836c24b2a70b97 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 8 Sep 2020 16:47:19 +0200 Subject: [PATCH 6/7] fix test --- src/test/ui/const_evaluatable/function-call.rs | 1 + src/test/ui/const_evaluatable/function-call.stderr | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/ui/const_evaluatable/function-call.rs b/src/test/ui/const_evaluatable/function-call.rs index b13a0369a00eb..9b54a541e6906 100644 --- a/src/test/ui/const_evaluatable/function-call.rs +++ b/src/test/ui/const_evaluatable/function-call.rs @@ -1,4 +1,5 @@ // check-pass +#![warn(const_evaluatable_unchecked)] const fn foo() -> usize { if std::mem::size_of::<*mut T>() < 8 { // size of *mut T does not depend on T diff --git a/src/test/ui/const_evaluatable/function-call.stderr b/src/test/ui/const_evaluatable/function-call.stderr index a15637196062f..a63a2643ad2c2 100644 --- a/src/test/ui/const_evaluatable/function-call.stderr +++ b/src/test/ui/const_evaluatable/function-call.stderr @@ -1,10 +1,14 @@ warning: cannot use constants which depend on generic parameters in types - --> $DIR/function-call.rs:12:17 + --> $DIR/function-call.rs:13:17 | LL | let _ = [0; foo::()]; | ^^^^^^^^^^ | - = note: `#[warn(const_evaluatable_unchecked)]` on by default +note: the lint level is defined here + --> $DIR/function-call.rs:2:9 + | +LL | #![warn(const_evaluatable_unchecked)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #76200 From 74e07198a08fea62ab2fba9ae258f4d118d7dffe Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 9 Sep 2020 20:10:23 +0200 Subject: [PATCH 7/7] fix test on 32 bit systems --- src/test/ui/const_evaluatable/function-call.rs | 5 +++-- src/test/ui/const_evaluatable/function-call.stderr | 8 ++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/test/ui/const_evaluatable/function-call.rs b/src/test/ui/const_evaluatable/function-call.rs index 9b54a541e6906..b5de66621c50e 100644 --- a/src/test/ui/const_evaluatable/function-call.rs +++ b/src/test/ui/const_evaluatable/function-call.rs @@ -1,8 +1,9 @@ // check-pass -#![warn(const_evaluatable_unchecked)] const fn foo() -> usize { - if std::mem::size_of::<*mut T>() < 8 { // size of *mut T does not depend on T + // We might instead branch on `std::mem::size_of::<*mut T>() < 8` here, + // which would cause this function to fail on 32 bit systems. + if false { std::mem::size_of::() } else { 8 diff --git a/src/test/ui/const_evaluatable/function-call.stderr b/src/test/ui/const_evaluatable/function-call.stderr index a63a2643ad2c2..0d8463714e8df 100644 --- a/src/test/ui/const_evaluatable/function-call.stderr +++ b/src/test/ui/const_evaluatable/function-call.stderr @@ -1,14 +1,10 @@ warning: cannot use constants which depend on generic parameters in types - --> $DIR/function-call.rs:13:17 + --> $DIR/function-call.rs:14:17 | LL | let _ = [0; foo::()]; | ^^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/function-call.rs:2:9 - | -LL | #![warn(const_evaluatable_unchecked)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_evaluatable_unchecked)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #76200