Put lazy normalization behind a feature gate

This commit is contained in:
Ben Lewis 2020-01-04 18:54:19 +13:00 committed by Bastian Kauschke
parent 3ef831069a
commit 93d15b9480
26 changed files with 207 additions and 67 deletions

View File

@ -559,6 +559,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,
];

View File

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

View File

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

View File

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

View File

@ -431,18 +431,20 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
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<R: TypeRelation<'tcx>>(
}
// 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 }))

View File

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

View File

@ -411,6 +411,7 @@ symbols! {
label_break_value,
lang,
lang_items,
lazy_normalization_consts,
let_chains,
lhs,
lib,

View File

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

View File

@ -201,4 +201,9 @@ impl<'cx, 'tcx> 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)
}
}

View File

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

View File

@ -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<const N: usize>([u32; 0 + N]);

View File

@ -7,8 +7,14 @@ LL | #![feature(const_generics)]
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/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<const N: usize>([u32; 0 + N]);
| ^^^^^^^^^^^^
@ -16,7 +22,7 @@ LL | struct ArithArrayLen<const N: usize>([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],
| ^^^^^^^^^^^^^^^^^^^^^^^

View File

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

View File

@ -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<T: Copy, const N: usize>(x: T) -> [T; N] {
[x; { N }]

View File

@ -7,6 +7,12 @@ LL | #![feature(const_generics)]
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/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
|

View File

@ -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<T: Copy, const N: usize>(x: T) -> [T; N] {
[x; N]

View File

@ -7,6 +7,12 @@ LL | #![feature(const_generics)]
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/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
|

View File

@ -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<const N: usize>;

View File

@ -7,5 +7,13 @@ LL | #![feature(const_generics)]
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/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.

View File

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

View File

@ -6,3 +6,9 @@ LL | #![feature(const_generics)]
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,5 +1,6 @@
#![allow(incomplete_features, dead_code, unconditional_recursion)]
#![feature(const_generics)]
#![feature(lazy_normalization_consts)]
fn fact<const N: usize>() {
fact::<{ N - 1 }>();

View File

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

View File

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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
[<u8 as Baz>::Quaks; 2]: Bar,
<u8 as Baz>::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)

View File

@ -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 | | [<u8 as Baz>::Quaks; 2]: Bar,
LL | | <u8 as Baz>::Quaks: Bar,
LL | | {
LL | | }
| |_^ 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>
= 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]; 2]: Bar` is not satisfied
--> $DIR/issue-67185-2.rs:17:1
|
LL | / trait Foo
LL | |
LL | | where
LL | | [<u8 as Baz>::Quaks; 2]: Bar,
LL | | <u8 as Baz>::Quaks: Bar,
LL | | {
LL | | }
| |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
|
= 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]: 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 | / trait Foo
LL | |
LL | | where
LL | | [<u8 as Baz>::Quaks; 2]: Bar,
LL | | <u8 as Baz>::Quaks: Bar,
LL | | {
LL | | }
| |_- required by `Foo`
...
LL | fn f(_: impl Foo) {}
| ^^^^^^^^^^^^^^^^^^^^ 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]: Bar` is not satisfied
--> $DIR/issue-67185-2.rs:31:14
|
LL | / trait Foo
LL | |
LL | | where
LL | | [<u8 as Baz>::Quaks; 2]: Bar,
LL | | <u8 as Baz>::Quaks: Bar,
LL | | {
LL | | }
| |_- required by `Foo`
...
LL | fn f(_: impl Foo) {}
| ^^^^^^^^^^^^^^^^^^^^ 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: 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`.