From 696c88d69ce01cc41acd9744d120e12be260a4b6 Mon Sep 17 00:00:00 2001 From: Ellen Date: Thu, 19 Aug 2021 19:46:35 +0100 Subject: [PATCH 1/3] canonicalize const equate predicates --- .../rustc_trait_selection/src/traits/fulfill.rs | 13 ++++++++----- .../rustc_trait_selection/src/traits/select/mod.rs | 12 ++++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 7048f0dbedcb6..1d44e17180703 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -4,6 +4,7 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome} use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; use rustc_hir as hir; +use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; @@ -552,11 +553,13 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - if self - .selcx - .tcx() - .try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs))) - { + let canonical = infcx.canonicalize_query( + ((a.def, a.substs), (b.def, b.substs)), + &mut OriginalQueryValues::default(), + ); + debug!("canonical consts: {:?}", &canonical.value); + + if self.selcx.tcx().try_unify_abstract_consts(canonical.value) { return ProcessResult::Changed(vec![]); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index dcf5ac63b78ea..60484b4d0656c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -33,6 +33,7 @@ use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::Constness; +use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::abstract_const::NotConstEvaluatable; @@ -608,10 +609,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - if self - .tcx() - .try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs))) - { + let canonical = self.infcx.canonicalize_query( + ((a.def, a.substs), (b.def, b.substs)), + &mut OriginalQueryValues::default(), + ); + debug!("canonical consts: {:?}", &canonical.value); + + if self.tcx().try_unify_abstract_consts(canonical.value) { return Ok(EvaluatedToOk); } } From ab61e722eeb6c37b19f6ad6f53fc8a05a79859f5 Mon Sep 17 00:00:00 2001 From: Ellen Date: Thu, 19 Aug 2021 19:13:57 +0100 Subject: [PATCH 2/3] regression tests --- .../issue-77708-1.rs | 23 +++++++++++++ .../issue-77708-2.rs | 18 ++++++++++ .../issue-77708-3.rs | 22 ++++++++++++ .../issue-82034.rs | 34 +++++++++++++++++++ .../issue-85031-1.rs | 23 +++++++++++++ .../issue-85031-2.rs | 14 ++++++++ .../issue-85031-3.rs | 25 ++++++++++++++ .../issue-86953.rs | 16 +++++++++ .../issue-88022.rs | 28 +++++++++++++++ 9 files changed, 203 insertions(+) create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs create mode 100644 src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs new file mode 100644 index 0000000000000..a6edbb2e9f996 --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs @@ -0,0 +1,23 @@ +// revisions: cfail +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features, unused_braces)] + +trait Delegates {} + +struct FileCap {} + +fn writes_to_path(cap: &C) +where + C: Delegates>, +{ + writes_to_specific_path(&cap); + //~^ error: the trait bound +} + +fn writes_to_specific_path(cap: &C) +where + C: Delegates>, +{ +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs new file mode 100644 index 0000000000000..52eeec73b0dd3 --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs @@ -0,0 +1,18 @@ +// revisions: rpass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +struct Z; +const fn one() -> usize { + 1 +} + +fn from_a_to_b(source: [u8; one()]) -> T { + todo!() +} + +fn not_main() { + let _: &Z = from_a_to_b([0; 1]); +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs new file mode 100644 index 0000000000000..11cca942dd639 --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs @@ -0,0 +1,22 @@ +// revisions: rpass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +use std::{convert::TryFrom, num::NonZeroUsize}; + +struct A([u8; N.get()]) +where + [u8; N.get()]: Sized; + +impl<'a, const N: NonZeroUsize> TryFrom<&'a [u8]> for A +where + [u8; N.get()]: Sized, +{ + type Error = (); + fn try_from(slice: &'a [u8]) -> Result, ()> { + let _x = <&[u8; N.get()] as TryFrom<&[u8]>>::try_from(slice); + unimplemented!(); + } +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs new file mode 100644 index 0000000000000..1b769d0a30dce --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs @@ -0,0 +1,34 @@ +// revisions: rpass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] +pub trait IsTrue {} +pub trait IsFalse {} + +pub struct Assert {} + +impl IsTrue for Assert {} +impl IsFalse for Assert {} + +pub struct SliceConstWriter<'a, const N: usize> { + ptr: &'a mut [u8], +} +impl<'a, const N: usize> SliceConstWriter<'a, { N }> { + pub fn from_slice(vec: &'a mut [u8]) -> Self { + Self { ptr: vec } + } + + pub fn convert(mut self) -> SliceConstWriter<'a, { NN }> { + SliceConstWriter { ptr: self.ptr } + } +} + +impl<'a, const N: usize> SliceConstWriter<'a, { N }> +where + Assert<{ N >= 2 }>: IsTrue, +{ + pub fn write_u8(mut self) -> SliceConstWriter<'a, { N - 2 }> { + self.convert() + } +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs new file mode 100644 index 0000000000000..20d4993774de3 --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs @@ -0,0 +1,23 @@ +// revisions: rpass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +pub struct Ref<'a, const NUM: usize>(&'a i32); + +impl<'a, const NUM: usize> Ref<'a, NUM> { + pub fn foo(r: Ref<'a, A>) -> Self + where + ([(); NUM - A], [(); A - NUM]): Sized, + { + Self::bar(r) + } + + pub fn bar(r: Ref<'a, A>) -> Self + where + ([(); NUM - A], [(); A - NUM]): Sized, + { + Self(r.0) + } +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs new file mode 100644 index 0000000000000..be7ad6d1fa031 --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs @@ -0,0 +1,14 @@ +// revisions: cfail +#![allow(incomplete_features)] +#![feature(const_generics, const_evaluatable_checked)] + +pub struct Ref<'a>(&'a i32); + +impl<'a> Ref<'a> { + pub fn foo() -> [(); A - 0] { + Self::foo() + //~^ error: type annotations needed + } +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs new file mode 100644 index 0000000000000..af4f209c90458 --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs @@ -0,0 +1,25 @@ +// revisions: rpass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +fn test() {} + +trait SomeTrait { + const SIZE: usize; +} + +struct A<'a, T> { + some_ref: &'a str, + _maker: core::marker::PhantomData, +} + +impl<'a, T: SomeTrait> A<'a, T> +where + [(); T::SIZE]: , +{ + fn call_test() { + test::<{ T::SIZE }>(); + } +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs new file mode 100644 index 0000000000000..ba86336962633 --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs @@ -0,0 +1,16 @@ +// revisions: rpass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +struct Foo; +impl<'a> std::ops::Add<&'a Foo> for Foo +where + [(); 0 + 0]: Sized, +{ + type Output = (); + fn add(self, _: &Foo) -> Self::Output { + loop {} + } +} + +fn main() {} diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs new file mode 100644 index 0000000000000..da713631cc1fc --- /dev/null +++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs @@ -0,0 +1,28 @@ +// revisions: cfail +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features, unused_braces)] + +struct Buffer +where + [(); { S * 2 }]: Default, +{ + data: [T; { S * 2 }], +} + +struct BufferIter<'a, T, const S: usize>(&'a Buffer) +where + [(); { S * 2 }]: Default; + +impl<'a, T, const S: usize> Iterator for BufferIter<'a, T, S> { + //~^ error: the trait bound + //~^^ error: unconstrained generic constant + type Item = &'a T; + + fn next(&mut self) -> Option { + //~^ error: the trait bound + //~^^ error: unconstrained generic constant + None + } +} + +fn main() {} From c2b61fbafe53d655ec010471d8f4a3bf34c724bd Mon Sep 17 00:00:00 2001 From: Ellen Date: Thu, 19 Aug 2021 21:04:04 +0100 Subject: [PATCH 3/3] move code to `InferCtxt` method --- compiler/rustc_infer/src/infer/mod.rs | 16 ++++++++++++++++ .../rustc_trait_selection/src/traits/fulfill.rs | 9 +-------- .../src/traits/select/mod.rs | 9 +-------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 10217a5f57498..1bc20180f04b4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -670,6 +670,22 @@ pub struct CombinedSnapshot<'a, 'tcx> { } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { + /// calls `tcx.try_unify_abstract_consts` after + /// canonicalizing the consts. + pub fn try_unify_abstract_consts( + &self, + a: ty::Unevaluated<'tcx>, + b: ty::Unevaluated<'tcx>, + ) -> bool { + let canonical = self.canonicalize_query( + ((a.def, a.substs), (b.def, b.substs)), + &mut OriginalQueryValues::default(), + ); + debug!("canonical consts: {:?}", &canonical.value); + + self.tcx.try_unify_abstract_consts(canonical.value) + } + pub fn is_in_snapshot(&self) -> bool { self.in_snapshot.get() } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 1d44e17180703..9cb074e8f54c5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -4,7 +4,6 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome} use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; @@ -553,13 +552,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - let canonical = infcx.canonicalize_query( - ((a.def, a.substs), (b.def, b.substs)), - &mut OriginalQueryValues::default(), - ); - debug!("canonical consts: {:?}", &canonical.value); - - if self.selcx.tcx().try_unify_abstract_consts(canonical.value) { + if infcx.try_unify_abstract_consts(a, b) { return ProcessResult::Changed(vec![]); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 60484b4d0656c..c2e3cdee6623f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -33,7 +33,6 @@ use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::Constness; -use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::abstract_const::NotConstEvaluatable; @@ -609,13 +608,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - let canonical = self.infcx.canonicalize_query( - ((a.def, a.substs), (b.def, b.substs)), - &mut OriginalQueryValues::default(), - ); - debug!("canonical consts: {:?}", &canonical.value); - - if self.tcx().try_unify_abstract_consts(canonical.value) { + if self.infcx.try_unify_abstract_consts(a, b) { return Ok(EvaluatedToOk); } }