From b0625eb7127683e301c37e3d7fb8e3c8a6f66456 Mon Sep 17 00:00:00 2001 From: Ellen Date: Wed, 27 Jan 2021 02:42:18 +0000 Subject: [PATCH 1/3] boop, ur abstract consts are now expanded --- .../src/traits/const_evaluatable.rs | 24 +++++++++++--- .../nested-abstract-consts-1.rs | 22 +++++++++++++ .../nested-abstract-consts-2.rs | 32 +++++++++++++++++++ .../nested_uneval_unification-1.rs | 32 +++++++++++++++++++ .../nested_uneval_unification-2.rs | 26 +++++++++++++++ 5 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index ad229e03b0b6b..272588ad516c2 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -609,9 +609,27 @@ where /// Tries to unify two abstract constants using structural equality. pub(super) fn try_unify<'tcx>( tcx: TyCtxt<'tcx>, - a: AbstractConst<'tcx>, - b: AbstractConst<'tcx>, + mut a: AbstractConst<'tcx>, + mut b: AbstractConst<'tcx>, ) -> bool { + while let Node::Leaf(a_ct) = a.root() { + let a_ct = a_ct.subst(tcx, a.substs); + match AbstractConst::from_const(tcx, a_ct) { + Ok(Some(a_act)) => a = a_act, + Ok(None) => break, + Err(_) => return true, + } + } + + while let Node::Leaf(b_ct) = b.root() { + let b_ct = b_ct.subst(tcx, b.substs); + match AbstractConst::from_const(tcx, b_ct) { + Ok(Some(b_act)) => b = b_act, + Ok(None) => break, + Err(_) => return true, + } + } + match (a.root(), b.root()) { (Node::Leaf(a_ct), Node::Leaf(b_ct)) => { let a_ct = a_ct.subst(tcx, a.substs); @@ -632,8 +650,6 @@ pub(super) fn try_unify<'tcx>( // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This // means that we only allow inference variables if they are equal. (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val, - // We may want to instead recurse into unevaluated constants here. That may require some - // care to prevent infinite recursion, so let's just ignore this for now. ( ty::ConstKind::Unevaluated(a_def, a_substs, None), ty::ConstKind::Unevaluated(b_def, b_substs, None), diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs new file mode 100644 index 0000000000000..124cd317da565 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs @@ -0,0 +1,22 @@ +// run-pass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +fn callee() -> usize +where + [u8; M2 + 1]: Sized, +{ + M2 +} + +fn caller() -> usize +where + [u8; N1 + 1]: Sized, + [u8; (N1 + 1) + 1]: Sized, +{ + callee::<{ N1 + 1 }>() +} + +fn main() { + assert_eq!(caller::<4>(), 5); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs new file mode 100644 index 0000000000000..5936662dadb20 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs @@ -0,0 +1,32 @@ +// run-pass +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] + +struct Generic; + +struct ConstU64; + +impl Generic +where + ConstU64<{ K - 1 }>: , +{ + fn foo(self) -> u64 { + K + } +} + +impl Generic +where + ConstU64<{ K - 1 }>: , + ConstU64<{ K + 1 }>: , + ConstU64<{ K + 1 - 1 }>: , +{ + fn bar(self) -> u64 { + let x: Generic<{ K + 1 }> = Generic; + x.foo() + } +} + +fn main() { + assert_eq!((Generic::<10>).bar(), 11); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs new file mode 100644 index 0000000000000..ff0f2efaee9cb --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs @@ -0,0 +1,32 @@ +// run-pass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +fn zero_init() -> Substs1 +where + [u8; N + 1]: , +{ + Substs1([0; N + 1]) +} +struct Substs1([u8; N + 1]) +where + [(); N + 1]: ; + +fn substs2() -> Substs1<{ M * 2 }> +where + [(); { M * 2 } + 1]: , +{ + zero_init::<{ M * 2 }>() +} + +fn substs3() -> Substs1<{ (L - 1) * 2 }> +where + [(); (L - 1)]: , + [(); (L - 1) * 2 + 1]: , +{ + substs2::<{ L - 1 }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 3]); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs new file mode 100644 index 0000000000000..806f7ba920310 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs @@ -0,0 +1,26 @@ +// run-pass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features, unused_parens, unused_braces)] + +fn zero_init() -> Substs1<{ (N) }> +where + [u8; { (N) }]: , +{ + Substs1([0; { (N) }]) +} + +struct Substs1([u8; { (N) }]) +where + [(); { (N) }]: ; + +fn substs2() -> Substs1<{ (M) }> { + zero_init::<{ (M) }>() +} + +fn substs3() -> Substs1<{ (L) }> { + substs2::<{ (L) }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 2]); +} From f4261772d8d4e2d4fb7e9dd4685b995a7176e506 Mon Sep 17 00:00:00 2001 From: Ellen Date: Wed, 27 Jan 2021 14:46:43 +0000 Subject: [PATCH 2/3] comments --- .../rustc_trait_selection/src/traits/const_evaluatable.rs | 4 +++- .../const_evaluatable_checked/nested-abstract-consts-1.rs | 2 ++ .../const_evaluatable_checked/nested-abstract-consts-2.rs | 2 ++ .../const_evaluatable_checked/nested_uneval_unification-1.rs | 2 ++ .../const_evaluatable_checked/nested_uneval_unification-2.rs | 2 ++ 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 272588ad516c2..b587ed6487e3c 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -612,6 +612,9 @@ pub(super) fn try_unify<'tcx>( mut a: AbstractConst<'tcx>, mut b: AbstractConst<'tcx>, ) -> bool { + // We substitute generics repeatedly to allow AbstractConsts to unify where a + // ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g. + // Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])] while let Node::Leaf(a_ct) = a.root() { let a_ct = a_ct.subst(tcx, a.substs); match AbstractConst::from_const(tcx, a_ct) { @@ -620,7 +623,6 @@ pub(super) fn try_unify<'tcx>( Err(_) => return true, } } - while let Node::Leaf(b_ct) = b.root() { let b_ct = b_ct.subst(tcx, b.substs); match AbstractConst::from_const(tcx, b_ct) { diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs index 124cd317da565..0fe84c1cd2a72 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs @@ -20,3 +20,5 @@ where fn main() { assert_eq!(caller::<4>(), 5); } + +// Test that the ``(N1 + 1) + 1`` bound on ``caller`` satisfies the ``M2 + 1`` bound on ``callee`` diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs index 5936662dadb20..fe5c2237a7603 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs @@ -30,3 +30,5 @@ where fn main() { assert_eq!((Generic::<10>).bar(), 11); } + +// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs index ff0f2efaee9cb..f686bfd1d2b02 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs @@ -30,3 +30,5 @@ where fn main() { assert_eq!(substs3::<2>().0, [0; 3]); } + +// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the ``{ N + 1 }`` bound on ``Substs1`` diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs index 806f7ba920310..4cdfb107417a6 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs @@ -24,3 +24,5 @@ fn substs3() -> Substs1<{ (L) }> { fn main() { assert_eq!(substs3::<2>().0, [0; 2]); } + +// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the ``{ (N) }`` bound on ``Substs1`` From ab421a176240a658ed02e8eee70b7ea211c087e3 Mon Sep 17 00:00:00 2001 From: Ellen Date: Wed, 27 Jan 2021 15:09:17 +0000 Subject: [PATCH 3/3] fix tidy errors --- .../const_evaluatable_checked/nested-abstract-consts-2.rs | 3 ++- .../const_evaluatable_checked/nested_uneval_unification-1.rs | 3 ++- .../const_evaluatable_checked/nested_uneval_unification-2.rs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs index fe5c2237a7603..4f588238e23ff 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs @@ -31,4 +31,5 @@ fn main() { assert_eq!((Generic::<10>).bar(), 11); } -// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block +// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the +// ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs index f686bfd1d2b02..1428f774b0d70 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs @@ -31,4 +31,5 @@ fn main() { assert_eq!(substs3::<2>().0, [0; 3]); } -// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the ``{ N + 1 }`` bound on ``Substs1`` +// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the +// ``{ N + 1 }`` bound on ``Substs1`` diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs index 4cdfb107417a6..be8219a744669 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs @@ -25,4 +25,5 @@ fn main() { assert_eq!(substs3::<2>().0, [0; 2]); } -// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the ``{ (N) }`` bound on ``Substs1`` +// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the +// ``{ (N) }`` bound on ``Substs1``