convert to future compat lint

This commit is contained in:
Bastian Kauschke 2020-08-06 10:48:36 +02:00
parent c81935e6df
commit ef6100e846
6 changed files with 67 additions and 41 deletions

View File

@ -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,
]
}

View File

@ -1,10 +1,11 @@
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;
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, TypeFoldable};
use rustc_session::lint;
use rustc_span::def_id::DefId;
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)
}
}
}
concrete.map(drop)
}

View File

@ -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<T> {
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() {

View File

@ -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

View File

@ -1,3 +1,4 @@
// check-pass
#![feature(lazy_normalization_consts)]
#![allow(incomplete_features)]
@ -9,6 +10,7 @@ impl<T: ?Sized> L<T> {
}
impl<T> X<T, [u8; L::<T>::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() {}

View File

@ -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<T> X<T, [u8; L::<T>::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