From 81b1810cd7b5f1cb74d498f20fa0ef5887420d33 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 30 Jul 2022 18:01:03 +0000 Subject: [PATCH 01/19] Require `#[const_trait]` for `const` `impl`s --- compiler/rustc_passes/src/check_const.rs | 22 ++++++++++++++++++++++ library/core/src/convert/mod.rs | 1 + library/core/src/default.rs | 1 + library/core/src/ops/index.rs | 2 ++ library/core/src/slice/index.rs | 1 + 5 files changed, 27 insertions(+) diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 70518284cf9..4062862ad74 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -192,6 +192,28 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + let tcx = self.tcx; + if let hir::ItemKind::Impl(hir::Impl { + constness: hir::Constness::Const, + of_trait: Some(trait_ref), + .. + }) = item.kind + { + let def_id = trait_ref.trait_def_id().unwrap(); + let source_map = tcx.sess.source_map(); + if !tcx.has_attr(def_id, sym::const_trait) { + tcx.sess + .struct_span_err( + source_map.guess_head_span(item.span), + "const `impl`s must be for traits marked with `#[const_trait]`", + ) + .span_note( + source_map.guess_head_span(tcx.def_span(def_id)), + "this trait must be annotated with `#[const_trait]`", + ) + .emit(); + } + } intravisit::walk_item(self, item); } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 05637c16622..95900828451 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -368,6 +368,7 @@ pub trait Into: Sized { all(_Self = "&str", T = "std::string::String"), note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix", ))] +#[const_trait] pub trait From: Sized { /// Converts to this type from the input type. #[lang = "from"] diff --git a/library/core/src/default.rs b/library/core/src/default.rs index b53cd6074b5..d96b53de0a3 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -99,6 +99,7 @@ /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index e2e569cb7ea..5e3dc48b6ca 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -55,6 +55,7 @@ #[doc(alias = "]")] #[doc(alias = "[")] #[doc(alias = "[]")] +#[const_trait] pub trait Index { /// The returned type after indexing. #[stable(feature = "rust1", since = "1.0.0")] @@ -163,6 +164,7 @@ see chapter in The Book : Index { /// Performs the mutable indexing (`container[index]`) operation. /// diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 3403a5a86f7..3d99bb7f9a0 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -158,6 +158,7 @@ mod private_slice_index { message = "the type `{T}` cannot be indexed by `{Self}`", label = "slice indices are of type `usize` or ranges of `usize`" )] +#[const_trait] pub unsafe trait SliceIndex: private_slice_index::Sealed { /// The output type returned by methods. #[stable(feature = "slice_get_slice", since = "1.28.0")] From be65e03676607dabac87cb4771692e5fc0fb6ad7 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 9 Aug 2022 17:39:09 +0000 Subject: [PATCH 02/19] Add `const_trait`s --- library/core/src/borrow.rs | 2 ++ library/core/src/iter/traits/collect.rs | 1 + library/core/src/ops/arith.rs | 2 ++ library/core/src/ops/bit.rs | 3 +++ library/core/src/ops/deref.rs | 1 + library/core/src/ops/try_trait.rs | 2 ++ 6 files changed, 11 insertions(+) diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs index 8378611eb18..fdd56cb4eaa 100644 --- a/library/core/src/borrow.rs +++ b/library/core/src/borrow.rs @@ -154,6 +154,7 @@ /// [`String`]: ../../std/string/struct.String.html #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Borrow"] +#[const_trait] pub trait Borrow { /// Immutably borrows from an owned value. /// @@ -184,6 +185,7 @@ pub trait Borrow { /// an underlying type by providing a mutable reference. See [`Borrow`] /// for more information on borrowing as another type. #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait BorrowMut: Borrow { /// Mutably borrows from an owned value. /// diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 12ca508bed2..e598a54b4f1 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -228,6 +228,7 @@ pub trait FromIterator: Sized { #[rustc_diagnostic_item = "IntoIterator"] #[rustc_skip_array_during_method_dispatch] #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait IntoIterator { /// The type of the elements being iterated over. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index e367be8c167..20bd9590422 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -938,6 +938,7 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "/")] #[doc(alias = "/=")] +#[const_trait] pub trait DivAssign { /// Performs the `/=` operation. /// @@ -999,6 +1000,7 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "%")] #[doc(alias = "%=")] +#[const_trait] pub trait RemAssign { /// Performs the `%=` operation. /// diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index 7c664226fc2..ec8f12cd161 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -31,6 +31,7 @@ #[lang = "not"] #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "!")] +#[const_trait] pub trait Not { /// The resulting type after applying the `!` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -906,6 +907,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} <<= {Rhs}`", label = "no implementation for `{Self} <<= {Rhs}`" )] +#[const_trait] pub trait ShlAssign { /// Performs the `<<=` operation. /// @@ -989,6 +991,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } message = "no implementation for `{Self} >>= {Rhs}`", label = "no implementation for `{Self} >>= {Rhs}`" )] +#[const_trait] pub trait ShrAssign { /// Performs the `>>=` operation. /// diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index d68932402a4..1f2df351e96 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -61,6 +61,7 @@ #[doc(alias = "&*")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Deref"] +#[const_trait] pub trait Deref { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 10f04134409..dfde0b37acf 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -128,6 +128,7 @@ use crate::ops::ControlFlow; )] #[doc(alias = "?")] #[lang = "Try"] +#[const_trait] pub trait Try: FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277")] @@ -384,6 +385,7 @@ pub trait Try: FromResidual { ))] #[rustc_diagnostic_item = "FromResidual"] #[unstable(feature = "try_trait_v2", issue = "84277")] +#[const_trait] pub trait FromResidual::Residual> { /// Constructs the type from a compatible `Residual` type. /// From 4b539b04a6a6fbe77ee6168716f5d282bc0e5e49 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 25 Aug 2022 03:00:48 +0000 Subject: [PATCH 03/19] Add more `const_trait` annotations --- library/core/src/convert/mod.rs | 5 +++++ library/core/src/ops/arith.rs | 9 +++++++++ library/core/src/ops/bit.rs | 8 ++++++++ library/core/src/ops/deref.rs | 3 ++- library/core/src/ops/index.rs | 4 ++-- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 95900828451..0480704a6d6 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -155,6 +155,7 @@ pub const fn identity(x: T) -> T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")] +#[const_trait] pub trait AsRef { /// Converts this type into a shared reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] @@ -197,6 +198,7 @@ pub trait AsRef { /// [`Box`]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")] +#[const_trait] pub trait AsMut { /// Converts this type into a mutable reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] @@ -273,6 +275,7 @@ pub trait AsMut { /// [`Vec`]: ../../std/vec/struct.Vec.html #[rustc_diagnostic_item = "Into"] #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait Into: Sized { /// Converts this type into the (usually inferred) input type. #[must_use] @@ -393,6 +396,7 @@ pub trait From: Sized { /// [`Into`], see there for details. #[rustc_diagnostic_item = "TryInto"] #[stable(feature = "try_from", since = "1.34.0")] +#[const_trait] pub trait TryInto: Sized { /// The type returned in the event of a conversion error. #[stable(feature = "try_from", since = "1.34.0")] @@ -469,6 +473,7 @@ pub trait TryInto: Sized { /// [`try_from`]: TryFrom::try_from #[rustc_diagnostic_item = "TryFrom"] #[stable(feature = "try_from", since = "1.34.0")] +#[const_trait] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. #[stable(feature = "try_from", since = "1.34.0")] diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 20bd9590422..8d74f9d2d98 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -97,6 +97,7 @@ ) )] #[doc(alias = "+")] +#[const_trait] pub trait Add { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -204,6 +205,7 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } label = "no implementation for `{Self} - {Rhs}`" )] #[doc(alias = "-")] +#[const_trait] pub trait Sub { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -333,6 +335,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } label = "no implementation for `{Self} * {Rhs}`" )] #[doc(alias = "*")] +#[const_trait] pub trait Mul { /// The resulting type after applying the `*` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -466,6 +469,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } label = "no implementation for `{Self} / {Rhs}`" )] #[doc(alias = "/")] +#[const_trait] pub trait Div { /// The resulting type after applying the `/` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -568,6 +572,7 @@ div_impl_float! { f32 f64 } label = "no implementation for `{Self} % {Rhs}`" )] #[doc(alias = "%")] +#[const_trait] pub trait Rem { /// The resulting type after applying the `%` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -682,6 +687,7 @@ rem_impl_float! { f32 f64 } #[lang = "neg"] #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "-")] +#[const_trait] pub trait Neg { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -755,6 +761,7 @@ neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "+")] #[doc(alias = "+=")] +#[const_trait] pub trait AddAssign { /// Performs the `+=` operation. /// @@ -822,6 +829,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "-")] #[doc(alias = "-=")] +#[const_trait] pub trait SubAssign { /// Performs the `-=` operation. /// @@ -880,6 +888,7 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "*")] #[doc(alias = "*=")] +#[const_trait] pub trait MulAssign { /// Performs the `*=` operation. /// diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index ec8f12cd161..327009801d1 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -144,6 +144,7 @@ impl const Not for ! { message = "no implementation for `{Self} & {Rhs}`", label = "no implementation for `{Self} & {Rhs}`" )] +#[const_trait] pub trait BitAnd { /// The resulting type after applying the `&` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -245,6 +246,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} | {Rhs}`", label = "no implementation for `{Self} | {Rhs}`" )] +#[const_trait] pub trait BitOr { /// The resulting type after applying the `|` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -346,6 +348,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} ^ {Rhs}`", label = "no implementation for `{Self} ^ {Rhs}`" )] +#[const_trait] pub trait BitXor { /// The resulting type after applying the `^` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -446,6 +449,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} << {Rhs}`", label = "no implementation for `{Self} << {Rhs}`" )] +#[const_trait] pub trait Shl { /// The resulting type after applying the `<<` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -565,6 +569,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } message = "no implementation for `{Self} >> {Rhs}`", label = "no implementation for `{Self} >> {Rhs}`" )] +#[const_trait] pub trait Shr { /// The resulting type after applying the `>>` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -693,6 +698,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } message = "no implementation for `{Self} &= {Rhs}`", label = "no implementation for `{Self} &= {Rhs}`" )] +#[const_trait] pub trait BitAndAssign { /// Performs the `&=` operation. /// @@ -765,6 +771,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} |= {Rhs}`", label = "no implementation for `{Self} |= {Rhs}`" )] +#[const_trait] pub trait BitOrAssign { /// Performs the `|=` operation. /// @@ -837,6 +844,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} ^= {Rhs}`", label = "no implementation for `{Self} ^= {Rhs}`" )] +#[const_trait] pub trait BitXorAssign { /// Performs the `^=` operation. /// diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 1f2df351e96..4f4c99c4ad9 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -61,7 +61,7 @@ #[doc(alias = "&*")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Deref"] -#[const_trait] +#[cfg_attr(not(bootstrap), const_trait)] pub trait Deref { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] @@ -170,6 +170,7 @@ impl const Deref for &mut T { #[lang = "deref_mut"] #[doc(alias = "*")] #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait DerefMut: Deref { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index 5e3dc48b6ca..dd4e3ac1c2f 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -55,7 +55,7 @@ #[doc(alias = "]")] #[doc(alias = "[")] #[doc(alias = "[]")] -#[const_trait] +#[cfg_attr(not(bootstrap), const_trait)] pub trait Index { /// The returned type after indexing. #[stable(feature = "rust1", since = "1.0.0")] @@ -164,7 +164,7 @@ see chapter in The Book : Index { /// Performs the mutable indexing (`container[index]`) operation. /// From 42316617898cacd52489121e9abebeff247e0840 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 04:02:43 +0000 Subject: [PATCH 04/19] Do not require const predicates to hold when checking if a projection type is wf --- compiler/rustc_trait_selection/src/traits/wf.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f95e217da30..a86234291ca 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -392,7 +392,8 @@ impl<'tcx> WfPredicates<'tcx> { // `i32: Clone` // `i32: Copy` // ] - let obligations = self.nominal_obligations(data.item_def_id, data.substs); + // Projection types do not require const predicates. + let obligations = self.nominal_obligations_without_const(data.item_def_id, data.substs); self.out.extend(obligations); let tcx = self.tcx(); From bc6483d11e692f01a4c9845212559017ab23ef4b Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 04:03:11 +0000 Subject: [PATCH 05/19] Prevent errors for stage0 rustc build --- library/core/src/default.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/default.rs b/library/core/src/default.rs index d96b53de0a3..a5b4e965552 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -99,7 +99,7 @@ /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] +#[cfg_attr(not(bootstrap), const_trait)] pub trait Default: Sized { /// Returns the "default value" for a type. /// From 5a6273e263f7621936491e2214b336666a3178c9 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 04:03:22 +0000 Subject: [PATCH 06/19] Do not implement `Unpin` as const --- library/alloc/src/boxed.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 65e323c9e00..0aff1323f97 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2037,8 +2037,7 @@ impl AsMut for Box { * could have a method to project a Pin from it. */ #[stable(feature = "pin", since = "1.33.0")] -#[rustc_const_unstable(feature = "const_box", issue = "92521")] -impl const Unpin for Box where A: 'static {} +impl Unpin for Box where A: 'static {} #[unstable(feature = "generator_trait", issue = "43122")] impl + Unpin, R, A: Allocator> Generator for Box From 03ac7e0d0be88e8dbdc529c89ccc74d80ce9c1c9 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 04:17:12 +0000 Subject: [PATCH 07/19] Add test --- .../const-impl-requires-const-trait.rs | 9 +++++++++ .../const-impl-requires-const-trait.stderr | 14 ++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs new file mode 100644 index 00000000000..1aff0562785 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs @@ -0,0 +1,9 @@ +#![feature(const_trait_impl)] + +pub trait A {} +//~^ NOTE: this trait must be annotated with `#[const_trait]` + +impl const A for () {} +//~^ ERROR: const `impl`s must be for traits marked with `#[const_trait]` + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr new file mode 100644 index 00000000000..6b465a9c62e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr @@ -0,0 +1,14 @@ +error: const `impl`s must be for traits marked with `#[const_trait]` + --> $DIR/const-impl-requires-const-trait.rs:6:1 + | +LL | impl const A for () {} + | ^^^^^^^^^^^^^^^^^^^ + | +note: this trait must be annotated with `#[const_trait]` + --> $DIR/const-impl-requires-const-trait.rs:3:1 + | +LL | pub trait A {} + | ^^^^^^^^^^^ + +error: aborting due to previous error + From a77f4bc6d31a6f3bc320c67eddb24003799a1722 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 04:32:27 +0000 Subject: [PATCH 08/19] Mark `Drop` with `#[const_trait]` --- library/core/src/ops/drop.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index de9ddb852df..a2c3d978cc4 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -134,6 +134,7 @@ /// these types cannot have destructors. #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait Drop { /// Executes the destructor for this type. /// From 07608bd60ecfa75a72c13372c1545665ab147f2c Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 04:53:36 +0000 Subject: [PATCH 09/19] fix `const_trait` unstable message --- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index b50c972e6f6..117273a4f2f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -468,7 +468,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // RFC 2632 gated!( const_trait, Normal, template!(Word), WarnFollowing, const_trait_impl, - "`const` is a temporary placeholder for marking a trait that is suitable for `const` \ + "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \ `impls` and all default bodies as `const`, which may be removed or renamed in the \ future." ), From 77b0c47b8284bbb24dab9a5ff95b93f083ce7c54 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 06:27:01 +0000 Subject: [PATCH 10/19] Normalize param_env for trait assoc consts in typeck --- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 40596078f04..92fee9f3527 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -130,7 +130,7 @@ pub fn predicates_for_generics<'tcx>( move |(idx, (predicate, span))| Obligation { cause: cause(idx, span), recursion_depth: 0, - param_env: param_env, + param_env, predicate, }, ) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index a40478db969..a7b4d08cbf3 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1418,13 +1418,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs: SubstsRef<'tcx>, code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>, ) { + // Associated consts have `Self: ~const Trait` bounds that should be satisfiable when + // `Self: Trait` is satisfied because it does not matter whether the impl is `const`. + // Therefore we have to remap the param env here to be non-const. + let param_env = if let hir::def::DefKind::AssocConst = self.tcx.def_kind(def_id) { + self.param_env.without_const() + } else { + self.param_env + }; let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); for obligation in traits::predicates_for_generics( |idx, predicate_span| { traits::ObligationCause::new(span, self.body_id, code(idx, predicate_span)) }, - self.param_env, + param_env, bounds, ) { self.register_predicate(obligation); From 08ac185e9917a5ccb0b3b55a4acee7eab38ce734 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 06:27:15 +0000 Subject: [PATCH 11/19] append_const_msg for std traits --- library/core/src/cmp.rs | 36 +++++++------------------------- library/core/src/ops/arith.rs | 39 +++++++---------------------------- 2 files changed, 16 insertions(+), 59 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index d9f2d3d64d6..50b8264bac7 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -204,20 +204,10 @@ use self::Ordering::*; #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "==")] #[doc(alias = "!=")] -#[cfg_attr( - bootstrap, - rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} == {Rhs}`" - ) -)] -#[cfg_attr( - not(bootstrap), - rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} == {Rhs}`", - append_const_msg, - ) +#[rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} == {Rhs}`", + append_const_msg )] #[const_trait] #[rustc_diagnostic_item = "PartialEq"] @@ -1076,20 +1066,10 @@ impl const PartialOrd for Ordering { #[doc(alias = "<")] #[doc(alias = "<=")] #[doc(alias = ">=")] -#[cfg_attr( - bootstrap, - rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", - ) -)] -#[cfg_attr( - not(bootstrap), - rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", - append_const_msg, - ) +#[rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", + append_const_msg )] #[const_trait] #[rustc_diagnostic_item = "PartialOrd"] diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 8d74f9d2d98..75c52d3ecfc 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -65,36 +65,12 @@ /// ``` #[lang = "add"] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr( - bootstrap, - rustc_on_unimplemented( - on( - all(_Self = "{integer}", Rhs = "{float}"), - message = "cannot add a float to an integer", - ), - on( - all(_Self = "{float}", Rhs = "{integer}"), - message = "cannot add an integer to a float", - ), - message = "cannot add `{Rhs}` to `{Self}`", - label = "no implementation for `{Self} + {Rhs}`" - ) -)] -#[cfg_attr( - not(bootstrap), - rustc_on_unimplemented( - on( - all(_Self = "{integer}", Rhs = "{float}"), - message = "cannot add a float to an integer", - ), - on( - all(_Self = "{float}", Rhs = "{integer}"), - message = "cannot add an integer to a float", - ), - message = "cannot add `{Rhs}` to `{Self}`", - label = "no implementation for `{Self} + {Rhs}`", - append_const_msg, - ) +#[rustc_on_unimplemented( + on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",), + on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`", + append_const_msg )] #[doc(alias = "+")] #[const_trait] @@ -202,7 +178,8 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented( message = "cannot subtract `{Rhs}` from `{Self}`", - label = "no implementation for `{Self} - {Rhs}`" + label = "no implementation for `{Self} - {Rhs}`", + append_const_msg )] #[doc(alias = "-")] #[const_trait] From 1bcc26a6b135fb934bf5f91d03d525f204323829 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Aug 2022 06:27:31 +0000 Subject: [PATCH 12/19] bless tests --- .../const_trait_fn-issue-88433.rs | 1 + .../ui/const-generics/issues/issue-88119.rs | 1 + .../ui/const-generics/issues/issue-98629.rs | 1 + .../const-generics/issues/issue-98629.stderr | 2 +- .../const-eval/const-eval-overflow-3b.stderr | 4 +- .../const-eval/const-eval-overflow-4b.stderr | 4 +- src/test/ui/consts/const-fn-error.rs | 4 +- src/test/ui/consts/const-fn-error.stderr | 44 +++++++------------ src/test/ui/consts/const-for-feature-gate.rs | 1 + .../ui/consts/const-for-feature-gate.stderr | 19 +++++++- src/test/ui/consts/const-for.rs | 3 +- src/test/ui/consts/const-for.stderr | 29 +++++------- src/test/ui/consts/control-flow/loop.rs | 2 + src/test/ui/consts/control-flow/loop.stderr | 37 ++++++++++++++-- src/test/ui/consts/issue-94675.rs | 5 +-- src/test/ui/consts/issue-94675.stderr | 33 ++++++-------- ...de-confusable-in-float-literal-expt.stderr | 4 +- src/test/ui/issues/issue-20605.stderr | 2 +- src/test/ui/issues/issue-25901.rs | 2 +- src/test/ui/issues/issue-25901.stderr | 24 ++++------ src/test/ui/issues/issue-32709.stderr | 4 +- src/test/ui/issues/issue-50582.rs | 1 + src/test/ui/issues/issue-50582.stderr | 20 +++++++-- src/test/ui/issues/issue-50585.rs | 1 + src/test/ui/issues/issue-50585.stderr | 20 +++++++-- src/test/ui/never_type/issue-52443.rs | 4 +- src/test/ui/never_type/issue-52443.stderr | 42 +++++++----------- .../rfc-2632-const-trait-impl/assoc-type.rs | 2 + .../assoc-type.stderr | 6 +-- .../auxiliary/staged-api.rs | 1 + .../call-const-trait-method-fail.rs | 2 +- .../call-const-trait-method-fail.stderr | 23 ++++------ .../call-const-trait-method-pass.rs | 1 + .../call-generic-in-impl.rs | 1 + .../const-check-fns-in-const-impl.rs | 1 + .../const-check-fns-in-const-impl.stderr | 2 +- .../rfc-2632-const-trait-impl/const-drop.rs | 1 + .../const-impl-recovery.rs | 2 + .../const-impl-recovery.stderr | 4 +- .../feature-gate.gated.stderr | 2 +- .../rfc-2632-const-trait-impl/feature-gate.rs | 1 + .../feature-gate.stock.stderr | 13 +++++- .../hir-const-check.rs | 1 + .../hir-const-check.stderr | 2 +- .../inherent-impl-const-bounds.rs | 2 + .../rfc-2632-const-trait-impl/issue-100222.rs | 10 +++++ .../issue-92230-wf-super-trait-env.rs | 2 + .../non-const-op-in-closure-in-const.rs | 1 + .../super-traits-fail.rs | 2 + .../super-traits-fail.stderr | 6 +-- .../rfc-2632-const-trait-impl/super-traits.rs | 3 ++ .../trait-where-clause-run.rs | 1 + .../missing-const-stability.rs | 1 + .../missing-const-stability.stderr | 2 +- .../ui/suggestions/slice-issue-87994.stderr | 8 ++-- 55 files changed, 241 insertions(+), 176 deletions(-) diff --git a/src/test/ui/const-generics/const_trait_fn-issue-88433.rs b/src/test/ui/const-generics/const_trait_fn-issue-88433.rs index 8724fa69825..6e04cfaec31 100644 --- a/src/test/ui/const-generics/const_trait_fn-issue-88433.rs +++ b/src/test/ui/const-generics/const_trait_fn-issue-88433.rs @@ -2,6 +2,7 @@ #![feature(const_trait_impl)] +#[const_trait] trait Func { type Output; diff --git a/src/test/ui/const-generics/issues/issue-88119.rs b/src/test/ui/const-generics/issues/issue-88119.rs index 70dfa7f708b..647b0eea86d 100644 --- a/src/test/ui/const-generics/issues/issue-88119.rs +++ b/src/test/ui/const-generics/issues/issue-88119.rs @@ -3,6 +3,7 @@ #![allow(incomplete_features)] #![feature(const_trait_impl, generic_const_exprs)] +#[const_trait] trait ConstName { const NAME_BYTES: &'static [u8]; } diff --git a/src/test/ui/const-generics/issues/issue-98629.rs b/src/test/ui/const-generics/issues/issue-98629.rs index fc8666bbcdb..1d2d3012a6e 100644 --- a/src/test/ui/const-generics/issues/issue-98629.rs +++ b/src/test/ui/const-generics/issues/issue-98629.rs @@ -1,5 +1,6 @@ #![feature(const_trait_impl)] +#[const_trait] trait Trait { const N: usize; } diff --git a/src/test/ui/const-generics/issues/issue-98629.stderr b/src/test/ui/const-generics/issues/issue-98629.stderr index 53570220882..4a248be76a9 100644 --- a/src/test/ui/const-generics/issues/issue-98629.stderr +++ b/src/test/ui/const-generics/issues/issue-98629.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `N` - --> $DIR/issue-98629.rs:7:1 + --> $DIR/issue-98629.rs:8:1 | LL | const N: usize; | -------------- `N` from trait diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index 0e6be6d01ed..c685922c456 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -4,13 +4,13 @@ error[E0308]: mismatched types LL | = [0; (i8::MAX + 1u8) as usize]; | ^^^ expected `i8`, found `u8` -error[E0277]: cannot add `u8` to `i8` +error[E0277]: cannot add `u8` to `i8` in const contexts --> $DIR/const-eval-overflow-3b.rs:16:20 | LL | = [0; (i8::MAX + 1u8) as usize]; | ^ no implementation for `i8 + u8` | - = help: the trait `Add` is not implemented for `i8` + = help: the trait `~const Add` is not implemented for `i8` = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr index 4fa017e04e9..b396079240a 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -4,13 +4,13 @@ error[E0308]: mismatched types LL | : [u32; (i8::MAX as i8 + 1u8) as usize] | ^^^ expected `i8`, found `u8` -error[E0277]: cannot add `u8` to `i8` +error[E0277]: cannot add `u8` to `i8` in const contexts --> $DIR/const-eval-overflow-4b.rs:9:28 | LL | : [u32; (i8::MAX as i8 + 1u8) as usize] | ^ no implementation for `i8 + u8` | - = help: the trait `Add` is not implemented for `i8` + = help: the trait `~const Add` is not implemented for `i8` = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> diff --git a/src/test/ui/consts/const-fn-error.rs b/src/test/ui/consts/const-fn-error.rs index abe68c17a0d..5884a893f8b 100644 --- a/src/test/ui/consts/const-fn-error.rs +++ b/src/test/ui/consts/const-fn-error.rs @@ -3,9 +3,7 @@ const X : usize = 2; const fn f(x: usize) -> usize { let mut sum = 0; for i in 0..x { - //~^ ERROR mutable references - //~| ERROR cannot convert - //~| ERROR cannot call non-const fn + //~^ ERROR the trait bound //~| ERROR `for` is not allowed in a `const fn` sum += i; } diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr index e36324f0b3e..040de150659 100644 --- a/src/test/ui/consts/const-fn-error.stderr +++ b/src/test/ui/consts/const-fn-error.stderr @@ -4,8 +4,6 @@ error[E0658]: `for` is not allowed in a `const fn` LL | / for i in 0..x { LL | | LL | | -LL | | -LL | | LL | | sum += i; LL | | } | |_____^ @@ -13,37 +11,25 @@ LL | | } = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error[E0015]: cannot convert `std::ops::Range` into an iterator in constant functions +error[E0277]: the trait bound `std::ops::Range: Iterator` is not satisfied + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ `std::ops::Range` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range` +note: the trait `Iterator` is implemented for `std::ops::Range`, but that implementation is not `const` --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ + = note: required for `std::ops::Range` to implement `~const IntoIterator` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | impl const IntoIterator for I { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | const fn f(x: usize) -> usize where std::ops::Range: ~const Iterator { + | +++++++++++++++++++++++++++++++++++++++++++++ -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/const-fn-error.rs:5:14 - | -LL | for i in 0..x { - | ^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable +error: aborting due to 2 previous errors -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constant functions - --> $DIR/const-fn-error.rs:5:14 - | -LL | for i in 0..x { - | ^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/const-for-feature-gate.rs b/src/test/ui/consts/const-for-feature-gate.rs index bec7b808905..8afc25fe3e5 100644 --- a/src/test/ui/consts/const-for-feature-gate.rs +++ b/src/test/ui/consts/const-for-feature-gate.rs @@ -3,6 +3,7 @@ const _: () = { for _ in 0..5 {} //~^ error: `for` is not allowed in a `const` + //~| error: the trait bound }; fn main() {} diff --git a/src/test/ui/consts/const-for-feature-gate.stderr b/src/test/ui/consts/const-for-feature-gate.stderr index 2ea377e09f6..f0887953891 100644 --- a/src/test/ui/consts/const-for-feature-gate.stderr +++ b/src/test/ui/consts/const-for-feature-gate.stderr @@ -7,6 +7,21 @@ LL | for _ in 0..5 {} = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error: aborting due to previous error +error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ `std::ops::Range<{integer}>` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` +note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` -For more information about this error, try `rustc --explain E0658`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/const-for.rs b/src/test/ui/consts/const-for.rs index 58bcb5f74cc..c6e958a9a95 100644 --- a/src/test/ui/consts/const-for.rs +++ b/src/test/ui/consts/const-for.rs @@ -3,8 +3,7 @@ const _: () = { for _ in 0..5 {} - //~^ error: cannot convert - //~| error: cannot call non-const fn + //~^ error: the trait bound }; fn main() {} diff --git a/src/test/ui/consts/const-for.stderr b/src/test/ui/consts/const-for.stderr index f2e1c8a4991..56637536310 100644 --- a/src/test/ui/consts/const-for.stderr +++ b/src/test/ui/consts/const-for.stderr @@ -1,24 +1,17 @@ -error[E0015]: cannot convert `std::ops::Range` into an iterator in constants +error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied + --> $DIR/const-for.rs:5:14 + | +LL | for _ in 0..5 {} + | ^^^^ `std::ops::Range<{integer}>` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` +note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` --> $DIR/const-for.rs:5:14 | LL | for _ in 0..5 {} | ^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | impl const IntoIterator for I { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants - --> $DIR/const-for.rs:5:14 - | -LL | for _ in 0..5 {} - | ^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants +error: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/control-flow/loop.rs b/src/test/ui/consts/control-flow/loop.rs index 2b8561a2644..36daa685c5a 100644 --- a/src/test/ui/consts/control-flow/loop.rs +++ b/src/test/ui/consts/control-flow/loop.rs @@ -51,10 +51,12 @@ const _: i32 = { let mut x = 0; for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR the trait bound x += i; } for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR the trait bound x += i; } diff --git a/src/test/ui/consts/control-flow/loop.stderr b/src/test/ui/consts/control-flow/loop.stderr index 5f6ad8c105d..747729befde 100644 --- a/src/test/ui/consts/control-flow/loop.stderr +++ b/src/test/ui/consts/control-flow/loop.stderr @@ -2,6 +2,7 @@ error[E0658]: `for` is not allowed in a `const` --> $DIR/loop.rs:53:5 | LL | / for i in 0..4 { +LL | | LL | | x += i; LL | | } | |_____^ @@ -10,9 +11,10 @@ LL | | } = help: add `#![feature(const_for)]` to the crate attributes to enable error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:57:5 + --> $DIR/loop.rs:58:5 | LL | / for i in 0..4 { +LL | | LL | | x += i; LL | | } | |_____^ @@ -20,6 +22,35 @@ LL | | } = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error: aborting due to 2 previous errors +error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ `std::ops::Range<{integer}>` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` +note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` -For more information about this error, try `rustc --explain E0658`. +error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied + --> $DIR/loop.rs:58:14 + | +LL | for i in 0..4 { + | ^^^^ `std::ops::Range<{integer}>` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` +note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` + --> $DIR/loop.rs:58:14 + | +LL | for i in 0..4 { + | ^^^^ + = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/issue-94675.rs b/src/test/ui/consts/issue-94675.rs index 0604aab3bcd..ce21ebdb9ac 100644 --- a/src/test/ui/consts/issue-94675.rs +++ b/src/test/ui/consts/issue-94675.rs @@ -7,9 +7,8 @@ struct Foo<'a> { impl<'a> Foo<'a> { const fn spam(&mut self, baz: &mut Vec) { self.bar[0] = baz.len(); - //~^ ERROR cannot call non-const fn `Vec::::len` in constant functions - //~| ERROR the trait bound `Vec: ~const IndexMut` is not satisfied - //~| ERROR cannot call non-const operator in constant functions + //~^ the trait bound `Vec: ~const Index<_>` is not satisfied + //~| the trait bound `Vec: ~const IndexMut` is not satisfied } } diff --git a/src/test/ui/consts/issue-94675.stderr b/src/test/ui/consts/issue-94675.stderr index 6665e42835b..7ae293ffbf8 100644 --- a/src/test/ui/consts/issue-94675.stderr +++ b/src/test/ui/consts/issue-94675.stderr @@ -1,10 +1,15 @@ -error[E0015]: cannot call non-const fn `Vec::::len` in constant functions - --> $DIR/issue-94675.rs:9:27 +error[E0277]: the trait bound `Vec: ~const Index<_>` is not satisfied + --> $DIR/issue-94675.rs:9:9 | LL | self.bar[0] = baz.len(); - | ^^^^^ + | ^^^^^^^^^^^ vector indices are of type `usize` or ranges of `usize` | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: the trait `~const Index<_>` is not implemented for `Vec` +note: the trait `Index<_>` is implemented for `Vec`, but that implementation is not `const` + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ error[E0277]: the trait bound `Vec: ~const IndexMut` is not satisfied --> $DIR/issue-94675.rs:9:9 @@ -18,21 +23,11 @@ note: the trait `IndexMut` is implemented for `Vec`, but that impl | LL | self.bar[0] = baz.len(); | ^^^^^^^^^^^ - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-94675.rs:9:9 +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -LL | self.bar[0] = baz.len(); - | ^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - | -LL | impl, A: Allocator> IndexMut for Vec { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | impl<'a> Foo<'a> where Vec: ~const IndexMut { + | ++++++++++++++++++++++++++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0277. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index 26986684f0c..81f3f269432 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -15,13 +15,13 @@ help: Unicode character '−' (Minus Sign) looks like '-' (Minus/Hyphen), but it LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e-11; // m³⋅kg⁻¹⋅s⁻² | ~ -error[E0277]: cannot subtract `{integer}` from `{float}` +error[E0277]: cannot subtract `{integer}` from `{float}` in const contexts --> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53 | LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻² | ^ no implementation for `{float} - {integer}` | - = help: the trait `Sub<{integer}>` is not implemented for `{float}` + = help: the trait `~const Sub<{integer}>` is not implemented for `{float}` = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index e1858b63989..c8e1313f573 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `dyn Iterator` cann --> $DIR/issue-20605.rs:2:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` + | ^^^^^^^ the trait `~const IntoIterator` is not implemented for `dyn Iterator` | = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required for `dyn Iterator` to implement `IntoIterator` diff --git a/src/test/ui/issues/issue-25901.rs b/src/test/ui/issues/issue-25901.rs index ba12e1ad021..1f7b341a97e 100644 --- a/src/test/ui/issues/issue-25901.rs +++ b/src/test/ui/issues/issue-25901.rs @@ -2,7 +2,7 @@ struct A; struct B; static S: &'static B = &A; -//~^ ERROR cannot perform deref coercion on `A` in statics +//~^ ERROR the trait bound use std::ops::Deref; diff --git a/src/test/ui/issues/issue-25901.stderr b/src/test/ui/issues/issue-25901.stderr index c6c80e41cf6..b9cac32229a 100644 --- a/src/test/ui/issues/issue-25901.stderr +++ b/src/test/ui/issues/issue-25901.stderr @@ -1,23 +1,15 @@ -error[E0015]: cannot perform deref coercion on `A` in statics +error[E0277]: the trait bound `A: Deref` is not satisfied + --> $DIR/issue-25901.rs:4:24 + | +LL | static S: &'static B = &A; + | ^^ the trait `~const Deref` is not implemented for `A` + | +note: the trait `Deref` is implemented for `A`, but that implementation is not `const` --> $DIR/issue-25901.rs:4:24 | LL | static S: &'static B = &A; | ^^ - | - = note: attempting to deref into `B` -note: deref defined here - --> $DIR/issue-25901.rs:10:5 - | -LL | type Target = B; - | ^^^^^^^^^^^ -note: impl defined here, but it is not `const` - --> $DIR/issue-25901.rs:9:1 - | -LL | impl Deref for A { - | ^^^^^^^^^^^^^^^^ - = note: calls in statics are limited to constant functions, tuple structs and tuple variants - = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index 1d595ca5649..355b110b465 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -7,9 +7,7 @@ LL | Err(5)?; | ^ the trait `From<{integer}>` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the following other types implement trait `FromResidual`: - as FromResidual>> - as FromResidual>> + = help: the trait `FromResidual>` is implemented for `Result` = note: required for `Result` to implement `FromResidual>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50582.rs b/src/test/ui/issues/issue-50582.rs index 2d5c9358752..9848cf0b0b1 100644 --- a/src/test/ui/issues/issue-50582.rs +++ b/src/test/ui/issues/issue-50582.rs @@ -2,4 +2,5 @@ fn main() { Vec::<[(); 1 + for x in 0..1 {}]>::new(); //~^ ERROR cannot add //~| ERROR `for` is not allowed in a `const` + //~| ERROR the trait bound } diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index 3d527eb6b4e..3b1936bb58c 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr @@ -7,13 +7,27 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error[E0277]: cannot add `()` to `{integer}` +error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied + --> $DIR/issue-50582.rs:2:29 + | +LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); + | ^^^^ `std::ops::Range<{integer}>` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` +note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` + --> $DIR/issue-50582.rs:2:29 + | +LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); + | ^^^^ + = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` + +error[E0277]: cannot add `()` to `{integer}` in const contexts --> $DIR/issue-50582.rs:2:18 | LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); | ^ no implementation for `{integer} + ()` | - = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the trait `~const Add<()>` is not implemented for `{integer}` = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> @@ -25,7 +39,7 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); <&'a isize as Add> and 48 others -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-50585.rs b/src/test/ui/issues/issue-50585.rs index a2f11c98d5a..3ec56739d4b 100644 --- a/src/test/ui/issues/issue-50585.rs +++ b/src/test/ui/issues/issue-50585.rs @@ -2,4 +2,5 @@ fn main() { |y: Vec<[(); for x in 0..2 {}]>| {}; //~^ ERROR mismatched types //~| ERROR `for` is not allowed in a `const` + //~| ERROR the trait bound } diff --git a/src/test/ui/issues/issue-50585.stderr b/src/test/ui/issues/issue-50585.stderr index e43cc20cbb5..ecd69f771c3 100644 --- a/src/test/ui/issues/issue-50585.stderr +++ b/src/test/ui/issues/issue-50585.stderr @@ -7,13 +7,27 @@ LL | |y: Vec<[(); for x in 0..2 {}]>| {}; = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable +error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied + --> $DIR/issue-50585.rs:2:27 + | +LL | |y: Vec<[(); for x in 0..2 {}]>| {}; + | ^^^^ `std::ops::Range<{integer}>` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` +note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` + --> $DIR/issue-50585.rs:2:27 + | +LL | |y: Vec<[(); for x in 0..2 {}]>| {}; + | ^^^^ + = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` + error[E0308]: mismatched types --> $DIR/issue-50585.rs:2:18 | LL | |y: Vec<[(); for x in 0..2 {}]>| {}; | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0277, E0308, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/never_type/issue-52443.rs b/src/test/ui/never_type/issue-52443.rs index cebcca944af..1b87e916853 100644 --- a/src/test/ui/never_type/issue-52443.rs +++ b/src/test/ui/never_type/issue-52443.rs @@ -8,7 +8,5 @@ fn main() { [(); { for _ in 0usize.. {}; 0}]; //~^ ERROR `for` is not allowed in a `const` - //~| ERROR cannot convert - //~| ERROR mutable references are not allowed in constants - //~| ERROR cannot call non-const fn + //~| ERROR the trait bound } diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr index 3c0daa4c55f..4a89d4f6d37 100644 --- a/src/test/ui/never_type/issue-52443.stderr +++ b/src/test/ui/never_type/issue-52443.stderr @@ -38,37 +38,25 @@ LL | [(); loop { break }]; | expected `usize`, found `()` | help: give it a value of the expected type: `break 42` -error[E0015]: cannot convert `RangeFrom` into an iterator in constants +error[E0277]: the trait bound `RangeFrom: Iterator` is not satisfied + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ `RangeFrom` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `RangeFrom` +note: the trait `Iterator` is implemented for `RangeFrom`, but that implementation is not `const` --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ + = note: required for `RangeFrom` to implement `~const IntoIterator` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | impl const IntoIterator for I { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: calls in constants are limited to constant functions, tuple structs and tuple variants +LL | fn main() where RangeFrom: ~const Iterator { + | +++++++++++++++++++++++++++++++++++++++ -error[E0658]: mutable references are not allowed in constants - --> $DIR/issue-52443.rs:9:21 - | -LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable +error: aborting due to 4 previous errors; 1 warning emitted -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants - --> $DIR/issue-52443.rs:9:21 - | -LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 6 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0015, E0308, E0658. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0277, E0308, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 99eacaa837f..7d9dae52cf1 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -10,6 +10,7 @@ impl std::ops::Add for NonConstAdd { } } +#[const_trait] trait Foo { type Bar: ~const std::ops::Add; } @@ -19,6 +20,7 @@ impl const Foo for NonConstAdd { //~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts } +#[const_trait] trait Baz { type Qux: std::ops::Add; } diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr index 64501c52374..ce2425010ad 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,17 +1,17 @@ error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts - --> $DIR/assoc-type.rs:18:16 + --> $DIR/assoc-type.rs:19:16 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` | = help: the trait `~const Add` is not implemented for `NonConstAdd` note: the trait `Add` is implemented for `NonConstAdd`, but that implementation is not `const` - --> $DIR/assoc-type.rs:18:16 + --> $DIR/assoc-type.rs:19:16 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:14:15 + --> $DIR/assoc-type.rs:15:15 | LL | type Bar: ~const std::ops::Add; | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs index 19e9006094b..589e3f02420 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -3,6 +3,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait MyTrait { #[stable(feature = "rust1", since = "1.0.0")] fn func(); diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs index 24b9235bb9a..dd993397420 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -1,5 +1,6 @@ #![feature(const_trait_impl)] +#[const_trait] pub trait Plus { fn plus(self, rhs: Self) -> Self; } @@ -23,7 +24,6 @@ pub const fn add_i32(a: i32, b: i32) -> i32 { pub const fn add_u32(a: u32, b: u32) -> u32 { a.plus(b) //~^ ERROR the trait bound - //~| ERROR cannot call non-const fn } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 1fc9db27761..d9ad8043153 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -1,24 +1,19 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied - --> $DIR/call-const-trait-method-fail.rs:24:7 + --> $DIR/call-const-trait-method-fail.rs:25:7 | LL | a.plus(b) - | ^^^^^^^ the trait `~const Plus` is not implemented for `u32` + | ^^^^ the trait `~const Plus` is not implemented for `u32` | note: the trait `Plus` is implemented for `u32`, but that implementation is not `const` - --> $DIR/call-const-trait-method-fail.rs:24:7 + --> $DIR/call-const-trait-method-fail.rs:25:7 | LL | a.plus(b) - | ^^^^^^^ - -error[E0015]: cannot call non-const fn `::plus` in constant functions - --> $DIR/call-const-trait-method-fail.rs:24:7 + | ^^^^ +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -LL | a.plus(b) - | ^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | pub const fn add_u32(a: u32, b: u32) -> u32 where u32: ~const Plus { + | ++++++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0015, E0277. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs index cf38bc3c964..b64161b6aa0 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs @@ -21,6 +21,7 @@ impl const PartialEq for Int { } } +#[const_trait] pub trait Plus { fn plus(self, rhs: Self) -> Self; } diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs index 89dc47aad3d..50c46579086 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs @@ -1,6 +1,7 @@ // check-pass #![feature(const_trait_impl)] +#[const_trait] trait MyPartialEq { fn eq(&self, other: &Self) -> bool; } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs index b3e3dd62be8..52984fb6be4 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs @@ -1,6 +1,7 @@ #![feature(const_trait_impl)] struct S; +#[const_trait] trait T { fn foo(); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr index 9e49785c589..c8783de4c3e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `non_const` in constant functions - --> $DIR/const-check-fns-in-const-impl.rs:11:16 + --> $DIR/const-check-fns-in-const-impl.rs:12:16 | LL | fn foo() { non_const() } | ^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs index 04462c0a11b..8b4c4065815 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs @@ -48,6 +48,7 @@ mod t { pub struct HasConstDrop(pub ConstDrop); pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize); + #[const_trait] pub trait SomeTrait { fn foo(); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs index 470c653dd47..837124db04e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs @@ -1,9 +1,11 @@ #![feature(const_trait_impl)] +#[const_trait] trait Foo {} const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword +#[const_trait] trait Bar {} const impl Bar for T {} //~ ERROR: expected identifier, found keyword diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr index 709084c86e0..7217fc85543 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `impl` - --> $DIR/const-impl-recovery.rs:5:7 + --> $DIR/const-impl-recovery.rs:6:7 | LL | const impl Foo for i32 {} | ^^^^ expected identifier, found keyword @@ -11,7 +11,7 @@ LL + impl const Foo for i32 {} | error: expected identifier, found keyword `impl` - --> $DIR/const-impl-recovery.rs:9:7 + --> $DIR/const-impl-recovery.rs:11:7 | LL | const impl Bar for T {} | ^^^^ expected identifier, found keyword diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr index af4d3909e40..4c630d33c55 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:13:1 + --> $DIR/feature-gate.rs:14:1 | LL | fn main() {} | ^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs index 7bac72e1bb6..0b409fbaac9 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs @@ -5,6 +5,7 @@ #![feature(rustc_attrs)] struct S; +#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder trait T {} impl const T for S {} //[stock]~^ ERROR const trait impls are experimental diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr index 91a8bb578a8..0e938c1c55d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr @@ -1,5 +1,5 @@ error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:9:6 + --> $DIR/feature-gate.rs:10:6 | LL | impl const T for S {} | ^^^^^ @@ -7,6 +7,15 @@ LL | impl const T for S {} = note: see issue #67792 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future. + --> $DIR/feature-gate.rs:8:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs index 80a4442de2c..337c733403b 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs @@ -2,6 +2,7 @@ #![feature(const_trait_impl)] +#[const_trait] pub trait MyTrait { fn method(&self) -> Option<()>; } diff --git a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr index 32df63e449d..6d2be1daa37 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr @@ -1,5 +1,5 @@ error[E0658]: `?` is not allowed in a `const fn` - --> $DIR/hir-const-check.rs:11:9 + --> $DIR/hir-const-check.rs:12:9 | LL | Some(())?; | ^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs index 2cef803a90e..f8ac793e4c1 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs @@ -3,7 +3,9 @@ struct S; +#[const_trait] trait A {} +#[const_trait] trait B {} impl const A for S {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs index 1004bb28c59..9f3f38ad4bc 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs @@ -16,6 +16,7 @@ pub trait IndexMut where Self: Index { impl Index for () { type Output = (); } +#[cfg(not(any(nn, yn)))] impl const IndexMut for <() as Index>::Output { const C: ::Output = (); type Assoc = ::Output; @@ -24,6 +25,15 @@ impl const IndexMut for <() as Index>::Output { {} } +#[cfg(any(nn, yn))] +impl IndexMut for <() as Index>::Output { + const C: ::Output = (); + type Assoc = ::Output; + fn foo(&mut self, x: ::Output) -> ::Output + where ::Output:, + {} +} + const C: <() as Index>::Output = (); fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs index 97c27ce1a1c..4d346965394 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs @@ -4,7 +4,9 @@ #![feature(const_trait_impl)] +#[const_trait] pub trait Super {} +#[const_trait] pub trait Sub: Super {} impl const Super for &A where A: ~const Super {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs index defef9e0409..1a4509b1869 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs @@ -2,6 +2,7 @@ #![feature(const_trait_impl)] +#[const_trait] trait Convert { fn to(self) -> T; } diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs index af465cad3d2..3e2b81368a5 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs @@ -1,8 +1,10 @@ #![feature(const_trait_impl)] +#[const_trait] trait Foo { fn a(&self); } +#[const_trait] trait Bar: ~const Foo {} struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr index 9e8b8f8c6ba..9787792ab13 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr @@ -1,16 +1,16 @@ error[E0277]: the trait bound `S: ~const Foo` is not satisfied - --> $DIR/super-traits-fail.rs:13:12 + --> $DIR/super-traits-fail.rs:15:12 | LL | impl const Bar for S {} | ^^^ the trait `~const Foo` is not implemented for `S` | note: the trait `Foo` is implemented for `S`, but that implementation is not `const` - --> $DIR/super-traits-fail.rs:13:12 + --> $DIR/super-traits-fail.rs:15:12 | LL | impl const Bar for S {} | ^^^ note: required by a bound in `Bar` - --> $DIR/super-traits-fail.rs:6:12 + --> $DIR/super-traits-fail.rs:8:12 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^ required by this bound in `Bar` diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs index aded4ca9a99..df96f6fb4ab 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs @@ -1,9 +1,12 @@ // check-pass #![feature(const_trait_impl)] +#[const_trait] trait Foo { fn a(&self); } + +#[const_trait] trait Bar: ~const Foo {} struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs index b7cf9a13b79..4b8b004069d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -2,6 +2,7 @@ #![feature(const_trait_impl)] +#[const_trait] trait Bar { fn bar() -> u8; } diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs index d89886af314..6eff899bfbf 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.rs +++ b/src/test/ui/stability-attribute/missing-const-stability.rs @@ -19,6 +19,7 @@ impl Foo { } #[stable(feature = "stable", since = "1.0.0")] +#[const_trait] pub trait Bar { #[stable(feature = "stable", since = "1.0.0")] fn fun(); diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr index 10978728fa3..4cfbe152891 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.stderr +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -5,7 +5,7 @@ LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ error: implementation has missing const stability attribute - --> $DIR/missing-const-stability.rs:27:1 + --> $DIR/missing-const-stability.rs:28:1 | LL | / impl const Bar for Foo { LL | | diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr index 84ecd749b0d..c6eb690ba5a 100644 --- a/src/test/ui/suggestions/slice-issue-87994.stderr +++ b/src/test/ui/suggestions/slice-issue-87994.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { - | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]` + | ^^^^^^ the trait `~const IntoIterator` is not implemented for `[i32]` | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required for `[i32]` to implement `IntoIterator` @@ -17,7 +17,7 @@ error[E0277]: `[i32]` is not an iterator --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { - | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]` + | ^^^^^^ the trait `~const IntoIterator` is not implemented for `[i32]` | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required for `[i32]` to implement `IntoIterator` @@ -32,7 +32,7 @@ error[E0277]: the size for values of type `[K]` cannot be known at compilation t --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { - | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]` + | ^^^^^^^ the trait `~const IntoIterator` is not implemented for `[K]` | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required for `[K]` to implement `IntoIterator` @@ -47,7 +47,7 @@ error[E0277]: `[K]` is not an iterator --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { - | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]` + | ^^^^^^^ the trait `~const IntoIterator` is not implemented for `[K]` | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required for `[K]` to implement `IntoIterator` From f8813cf10eea79f7703e716b6c050e818220670a Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 10 Sep 2022 06:37:26 +0000 Subject: [PATCH 13/19] do const trait method bounds check later in rustc_const_eval --- compiler/rustc_borrowck/src/type_check/mod.rs | 19 +++++++ .../src/transform/check_consts/check.rs | 44 +++++++++++++++- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 33 ++++++++---- .../static-const-trait-bound.rs | 18 +++++++ .../trait-where-clause-const.rs | 29 +++++++++++ .../trait-where-clause-const.stderr | 35 +++++++++++++ .../trait-where-clause.rs | 18 +------ .../trait-where-clause.stderr | 52 ++----------------- 8 files changed, 174 insertions(+), 74 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index f41d70d384d..79e7eb0f1cc 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -424,12 +424,31 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() { + // N.B.: When instantiating a trait method as a function item, it does not actually matter + // whether the trait is `const` or not, or whether `where T: ~const Tr` needs to be satisfied + // as `const`. If we were to introduce instantiating trait methods as `const fn`s, we would + // check that after this, either via a bound `where F: ~const FnOnce` or when coercing to a + // `const fn` pointer. + // + // FIXME(fee1-dead) FIXME(const_trait_impl): update this doc when trait methods can satisfy + // `~const FnOnce` or can be coerced to `const fn` pointer. + let const_norm = self.tcx().def_kind(def_id) == hir::def::DefKind::AssocFn + && self.tcx().def_kind(ty::DefIdTree::parent(self.tcx(), def_id)) + == hir::def::DefKind::Trait; + let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); + let prev = self.cx.param_env; + if const_norm { + self.cx.param_env = prev.without_const(); + } self.cx.normalize_and_prove_instantiated_predicates( def_id, instantiated_predicates, locations, ); + if const_norm { + self.cx.param_env = prev; + } } } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 7e15858c8c1..329d1033abf 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -13,8 +13,11 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeVisitable}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; -use rustc_trait_selection::traits::error_reporting::InferCtxtExt; -use rustc_trait_selection::traits::SelectionContext; +use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::{ + self, ObligationCauseCode, SelectionContext, TraitEngine, TraitEngineExt, +}; use std::mem; use std::ops::Deref; @@ -738,6 +741,43 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { selcx.select(&obligation) }); + // do a well-formedness check on the trait method being called. This is because typeck only does a + // "non-const" check. This is required for correctness here. + tcx.infer_ctxt().enter(|infcx| { + let mut fulfill_cx = >::new(infcx.tcx); + let predicates = tcx.predicates_of(callee).instantiate(tcx, substs); + let hir_id = tcx + .hir() + .local_def_id_to_hir_id(self.body.source.def_id().expect_local()); + let cause = || { + ObligationCause::new( + terminator.source_info.span, + hir_id, + ObligationCauseCode::ItemObligation(callee), + ) + }; + let normalized = infcx.partially_normalize_associated_types_in( + cause(), + param_env, + predicates, + ); + + for p in normalized.obligations { + fulfill_cx.register_predicate_obligation(&infcx, p); + } + for obligation in traits::predicates_for_generics( + |_, _| cause(), + self.param_env, + normalized.value, + ) { + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + let errors = fulfill_cx.select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); + } + }); + match implsrc { Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => { debug!( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index a7b4d08cbf3..31eb2b65476 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1410,7 +1410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) } - #[instrument(level = "debug", skip(self, code, span, def_id, substs))] + #[instrument(level = "debug", skip(self, code, span, substs))] fn add_required_obligations_with_code( &self, span: Span, @@ -1418,14 +1418,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs: SubstsRef<'tcx>, code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>, ) { - // Associated consts have `Self: ~const Trait` bounds that should be satisfiable when - // `Self: Trait` is satisfied because it does not matter whether the impl is `const`. - // Therefore we have to remap the param env here to be non-const. - let param_env = if let hir::def::DefKind::AssocConst = self.tcx.def_kind(def_id) { - self.param_env.without_const() - } else { - self.param_env - }; + let mut param_env = self.param_env; + match self.tcx.def_kind(def_id) { + // Associated consts have `Self: ~const Trait` bounds that should be satisfiable when + // `Self: Trait` is satisfied because it does not matter whether the impl is `const`. + // Therefore we have to remap the param env here to be non-const. + hir::def::DefKind::AssocConst => param_env = param_env.without_const(), + hir::def::DefKind::AssocFn + if self.tcx.def_kind(self.tcx.parent(def_id)) == hir::def::DefKind::Trait => + { + // N.B.: All callsites to this function involve checking a path expression. + // + // When instantiating a trait method as a function item, it does not actually matter whether + // the trait is `const` or not, or whether `where T: ~const Tr` needs to be satisfied as + // `const`. If we were to introduce instantiating trait methods as `const fn`s, we would + // check that after this, either via a bound `where F: ~const FnOnce` or when coercing to a + // `const fn` pointer. + // + // FIXME(fee1-dead) FIXME(const_trait_impl): update this doc when trait methods can satisfy + // `~const FnOnce` or can be coerced to `const fn` pointer. + param_env = param_env.without_const(); + } + _ => {} + } let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); for obligation in traits::predicates_for_generics( diff --git a/src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs new file mode 100644 index 00000000000..4520a36960c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs @@ -0,0 +1,18 @@ +// check-pass +pub struct S T = fn() -> T> { + f: F, + x: Option, +} + +impl T> S { + pub const fn new(f: F) -> Self { + Self { f, x: None } + } +} + +#[derive(Default)] +pub struct Foo; + +static LOCKED_CALLSITES: S = S::new(Default::default); + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs new file mode 100644 index 00000000000..7a88ec35c8f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs @@ -0,0 +1,29 @@ +// Like trait-where-clause.rs, but we are calling from a const context. +// Checking the validity of traits' where clauses happen at a later stage. +// (`rustc_const_eval` instead of `rustc_typeck`) Therefore one file as a +// test is not enough. +#![feature(const_trait_impl)] + +trait Bar {} + +trait Foo { + fn a(); + fn b() where Self: ~const Bar; + fn c(); +} + +const fn test1() { + T::a(); + T::b(); + //~^ ERROR the trait bound + T::c::(); + //~^ ERROR the trait bound +} + +const fn test2() { + T::a(); + T::b(); + T::c::(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr new file mode 100644 index 00000000000..13d8639de30 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause-const.rs:17:5 + | +LL | T::b(); + | ^^^^^^ the trait `~const Bar` is not implemented for `T` + | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause-const.rs:17:5 + | +LL | T::b(); + | ^^^^^^ +help: consider further restricting this bound + | +LL | const fn test1() { + | ++++++++++++ + +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause-const.rs:19:5 + | +LL | T::c::(); + | ^^^^^^^^^^^ the trait `~const Bar` is not implemented for `T` + | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause-const.rs:19:5 + | +LL | T::c::(); + | ^^^^^^^^^^^ +help: consider further restricting this bound + | +LL | const fn test1() { + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs index d37ed3bb8dd..5bd23a8cb20 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs @@ -8,7 +8,7 @@ trait Foo { fn c(); } -const fn test1() { +fn test1() { T::a(); T::b(); //~^ ERROR the trait bound @@ -16,21 +16,7 @@ const fn test1() { //~^ ERROR the trait bound } -const fn test2() { - T::a(); - T::b(); - T::c::(); -} - -fn test3() { - T::a(); - T::b(); - //~^ ERROR the trait bound - T::c::(); - //~^ ERROR the trait bound -} - -fn test4() { +fn test2() { T::a(); T::b(); T::c::(); diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr index fd5fe25ddcf..96365d33433 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -1,47 +1,5 @@ -error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause.rs:13:5 - | -LL | T::b(); - | ^^^^ the trait `~const Bar` is not implemented for `T` - | -note: the trait `Bar` is implemented for `T`, but that implementation is not `const` - --> $DIR/trait-where-clause.rs:13:5 - | -LL | T::b(); - | ^^^^ -note: required by a bound in `Foo::b` - --> $DIR/trait-where-clause.rs:7:24 - | -LL | fn b() where Self: ~const Bar; - | ^^^^^^^^^^ required by this bound in `Foo::b` -help: consider further restricting this bound - | -LL | const fn test1() { - | ++++++++++++ - -error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause.rs:15:12 - | -LL | T::c::(); - | ^ the trait `~const Bar` is not implemented for `T` - | -note: the trait `Bar` is implemented for `T`, but that implementation is not `const` - --> $DIR/trait-where-clause.rs:15:12 - | -LL | T::c::(); - | ^ -note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause.rs:8:13 - | -LL | fn c(); - | ^^^^^^^^^^ required by this bound in `Foo::c` -help: consider further restricting this bound - | -LL | const fn test1() { - | ++++++++++++ - error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:27:5 + --> $DIR/trait-where-clause.rs:13:5 | LL | T::b(); | ^^^^ the trait `Bar` is not implemented for `T` @@ -53,11 +11,11 @@ LL | fn b() where Self: ~const Bar; | ^^^^^^^^^^ required by this bound in `Foo::b` help: consider further restricting this bound | -LL | fn test3() { +LL | fn test1() { | +++++ error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:29:12 + --> $DIR/trait-where-clause.rs:15:12 | LL | T::c::(); | ^ the trait `Bar` is not implemented for `T` @@ -69,9 +27,9 @@ LL | fn c(); | ^^^^^^^^^^ required by this bound in `Foo::c` help: consider further restricting this bound | -LL | fn test3() { +LL | fn test1() { | +++++ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. From f937a10c4ef9448abdea6e6d4fa63472723bc779 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 10 Sep 2022 07:07:49 +0000 Subject: [PATCH 14/19] Bless ui tests after typeck code change --- src/test/ui/consts/const-fn-error.rs | 4 +- src/test/ui/consts/const-fn-error.stderr | 44 ++++++++++++------- src/test/ui/consts/const-for-feature-gate.rs | 1 - .../ui/consts/const-for-feature-gate.stderr | 19 +------- src/test/ui/consts/const-for.rs | 3 +- src/test/ui/consts/const-for.stderr | 29 +++++++----- src/test/ui/consts/control-flow/loop.rs | 2 - src/test/ui/consts/control-flow/loop.stderr | 37 ++-------------- src/test/ui/issues/issue-50582.rs | 1 - src/test/ui/issues/issue-50582.stderr | 16 +------ src/test/ui/issues/issue-50585.rs | 1 - src/test/ui/issues/issue-50585.stderr | 20 ++------- src/test/ui/never_type/issue-52443.rs | 4 +- src/test/ui/never_type/issue-52443.stderr | 42 +++++++++++------- src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs | 1 + .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 24 ++++++++-- 16 files changed, 113 insertions(+), 135 deletions(-) diff --git a/src/test/ui/consts/const-fn-error.rs b/src/test/ui/consts/const-fn-error.rs index 5884a893f8b..50b7ce1f8c0 100644 --- a/src/test/ui/consts/const-fn-error.rs +++ b/src/test/ui/consts/const-fn-error.rs @@ -3,8 +3,10 @@ const X : usize = 2; const fn f(x: usize) -> usize { let mut sum = 0; for i in 0..x { - //~^ ERROR the trait bound + //~^ ERROR cannot convert //~| ERROR `for` is not allowed in a `const fn` + //~| ERROR mutable references are not allowed in constant functions + //~| ERROR cannot call non-const fn sum += i; } sum diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr index 040de150659..e36324f0b3e 100644 --- a/src/test/ui/consts/const-fn-error.stderr +++ b/src/test/ui/consts/const-fn-error.stderr @@ -4,6 +4,8 @@ error[E0658]: `for` is not allowed in a `const fn` LL | / for i in 0..x { LL | | LL | | +LL | | +LL | | LL | | sum += i; LL | | } | |_____^ @@ -11,25 +13,37 @@ LL | | } = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error[E0277]: the trait bound `std::ops::Range: Iterator` is not satisfied - --> $DIR/const-fn-error.rs:5:14 - | -LL | for i in 0..x { - | ^^^^ `std::ops::Range` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range` -note: the trait `Iterator` is implemented for `std::ops::Range`, but that implementation is not `const` +error[E0015]: cannot convert `std::ops::Range` into an iterator in constant functions --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ - = note: required for `std::ops::Range` to implement `~const IntoIterator` -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -LL | const fn f(x: usize) -> usize where std::ops::Range: ~const Iterator { - | +++++++++++++++++++++++++++++++++++++++++++++ +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | impl const IntoIterator for I { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 2 previous errors +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constant functions + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/const-for-feature-gate.rs b/src/test/ui/consts/const-for-feature-gate.rs index 8afc25fe3e5..bec7b808905 100644 --- a/src/test/ui/consts/const-for-feature-gate.rs +++ b/src/test/ui/consts/const-for-feature-gate.rs @@ -3,7 +3,6 @@ const _: () = { for _ in 0..5 {} //~^ error: `for` is not allowed in a `const` - //~| error: the trait bound }; fn main() {} diff --git a/src/test/ui/consts/const-for-feature-gate.stderr b/src/test/ui/consts/const-for-feature-gate.stderr index f0887953891..2ea377e09f6 100644 --- a/src/test/ui/consts/const-for-feature-gate.stderr +++ b/src/test/ui/consts/const-for-feature-gate.stderr @@ -7,21 +7,6 @@ LL | for _ in 0..5 {} = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied - --> $DIR/const-for-feature-gate.rs:4:14 - | -LL | for _ in 0..5 {} - | ^^^^ `std::ops::Range<{integer}>` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` -note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` - --> $DIR/const-for-feature-gate.rs:4:14 - | -LL | for _ in 0..5 {} - | ^^^^ - = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` +error: aborting due to previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-for.rs b/src/test/ui/consts/const-for.rs index c6e958a9a95..8db24853558 100644 --- a/src/test/ui/consts/const-for.rs +++ b/src/test/ui/consts/const-for.rs @@ -3,7 +3,8 @@ const _: () = { for _ in 0..5 {} - //~^ error: the trait bound + //~^ error: cannot call + //~| error: cannot convert }; fn main() {} diff --git a/src/test/ui/consts/const-for.stderr b/src/test/ui/consts/const-for.stderr index 56637536310..f2e1c8a4991 100644 --- a/src/test/ui/consts/const-for.stderr +++ b/src/test/ui/consts/const-for.stderr @@ -1,17 +1,24 @@ -error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied - --> $DIR/const-for.rs:5:14 - | -LL | for _ in 0..5 {} - | ^^^^ `std::ops::Range<{integer}>` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` -note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants --> $DIR/const-for.rs:5:14 | LL | for _ in 0..5 {} | ^^^^ - = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | impl const IntoIterator for I { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/const-for.rs:5:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -For more information about this error, try `rustc --explain E0277`. +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/control-flow/loop.rs b/src/test/ui/consts/control-flow/loop.rs index 36daa685c5a..2b8561a2644 100644 --- a/src/test/ui/consts/control-flow/loop.rs +++ b/src/test/ui/consts/control-flow/loop.rs @@ -51,12 +51,10 @@ const _: i32 = { let mut x = 0; for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - //~^ ERROR the trait bound x += i; } for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - //~^ ERROR the trait bound x += i; } diff --git a/src/test/ui/consts/control-flow/loop.stderr b/src/test/ui/consts/control-flow/loop.stderr index 747729befde..5f6ad8c105d 100644 --- a/src/test/ui/consts/control-flow/loop.stderr +++ b/src/test/ui/consts/control-flow/loop.stderr @@ -2,7 +2,6 @@ error[E0658]: `for` is not allowed in a `const` --> $DIR/loop.rs:53:5 | LL | / for i in 0..4 { -LL | | LL | | x += i; LL | | } | |_____^ @@ -11,10 +10,9 @@ LL | | } = help: add `#![feature(const_for)]` to the crate attributes to enable error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:58:5 + --> $DIR/loop.rs:57:5 | LL | / for i in 0..4 { -LL | | LL | | x += i; LL | | } | |_____^ @@ -22,35 +20,6 @@ LL | | } = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied - --> $DIR/loop.rs:53:14 - | -LL | for i in 0..4 { - | ^^^^ `std::ops::Range<{integer}>` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` -note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` - --> $DIR/loop.rs:53:14 - | -LL | for i in 0..4 { - | ^^^^ - = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` +error: aborting due to 2 previous errors -error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied - --> $DIR/loop.rs:58:14 - | -LL | for i in 0..4 { - | ^^^^ `std::ops::Range<{integer}>` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` -note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` - --> $DIR/loop.rs:58:14 - | -LL | for i in 0..4 { - | ^^^^ - = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-50582.rs b/src/test/ui/issues/issue-50582.rs index 9848cf0b0b1..2d5c9358752 100644 --- a/src/test/ui/issues/issue-50582.rs +++ b/src/test/ui/issues/issue-50582.rs @@ -2,5 +2,4 @@ fn main() { Vec::<[(); 1 + for x in 0..1 {}]>::new(); //~^ ERROR cannot add //~| ERROR `for` is not allowed in a `const` - //~| ERROR the trait bound } diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index 3b1936bb58c..53ecc6112ff 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr @@ -7,20 +7,6 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied - --> $DIR/issue-50582.rs:2:29 - | -LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); - | ^^^^ `std::ops::Range<{integer}>` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` -note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` - --> $DIR/issue-50582.rs:2:29 - | -LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); - | ^^^^ - = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` - error[E0277]: cannot add `()` to `{integer}` in const contexts --> $DIR/issue-50582.rs:2:18 | @@ -39,7 +25,7 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); <&'a isize as Add> and 48 others -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-50585.rs b/src/test/ui/issues/issue-50585.rs index 3ec56739d4b..a2f11c98d5a 100644 --- a/src/test/ui/issues/issue-50585.rs +++ b/src/test/ui/issues/issue-50585.rs @@ -2,5 +2,4 @@ fn main() { |y: Vec<[(); for x in 0..2 {}]>| {}; //~^ ERROR mismatched types //~| ERROR `for` is not allowed in a `const` - //~| ERROR the trait bound } diff --git a/src/test/ui/issues/issue-50585.stderr b/src/test/ui/issues/issue-50585.stderr index ecd69f771c3..e43cc20cbb5 100644 --- a/src/test/ui/issues/issue-50585.stderr +++ b/src/test/ui/issues/issue-50585.stderr @@ -7,27 +7,13 @@ LL | |y: Vec<[(); for x in 0..2 {}]>| {}; = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied - --> $DIR/issue-50585.rs:2:27 - | -LL | |y: Vec<[(); for x in 0..2 {}]>| {}; - | ^^^^ `std::ops::Range<{integer}>` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` -note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` - --> $DIR/issue-50585.rs:2:27 - | -LL | |y: Vec<[(); for x in 0..2 {}]>| {}; - | ^^^^ - = note: required for `std::ops::Range<{integer}>` to implement `~const IntoIterator` - error[E0308]: mismatched types --> $DIR/issue-50585.rs:2:18 | LL | |y: Vec<[(); for x in 0..2 {}]>| {}; | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0308, E0658. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/never_type/issue-52443.rs b/src/test/ui/never_type/issue-52443.rs index 1b87e916853..0498a8a1625 100644 --- a/src/test/ui/never_type/issue-52443.rs +++ b/src/test/ui/never_type/issue-52443.rs @@ -8,5 +8,7 @@ fn main() { [(); { for _ in 0usize.. {}; 0}]; //~^ ERROR `for` is not allowed in a `const` - //~| ERROR the trait bound + //~| ERROR cannot convert + //~| ERROR mutable references + //~| ERROR cannot call } diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr index 4a89d4f6d37..3c0daa4c55f 100644 --- a/src/test/ui/never_type/issue-52443.stderr +++ b/src/test/ui/never_type/issue-52443.stderr @@ -38,25 +38,37 @@ LL | [(); loop { break }]; | expected `usize`, found `()` | help: give it a value of the expected type: `break 42` -error[E0277]: the trait bound `RangeFrom: Iterator` is not satisfied - --> $DIR/issue-52443.rs:9:21 - | -LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^ `RangeFrom` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `RangeFrom` -note: the trait `Iterator` is implemented for `RangeFrom`, but that implementation is not `const` +error[E0015]: cannot convert `RangeFrom` into an iterator in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ - = note: required for `RangeFrom` to implement `~const IntoIterator` -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -LL | fn main() where RangeFrom: ~const Iterator { - | +++++++++++++++++++++++++++++++++++++++ +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | impl const IntoIterator for I { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 4 previous errors; 1 warning emitted +error[E0658]: mutable references are not allowed in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -Some errors have detailed explanations: E0277, E0308, E0658. -For more information about an error, try `rustc --explain E0277`. +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0015, E0308, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs index ec86213f862..1a07dc46c5e 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs @@ -4,6 +4,7 @@ fn main() { >::add(1, 2); //~^ ERROR cannot add `u32` to `i32` //~| ERROR cannot add `u32` to `i32` + //~| ERROR cannot add `u32` to `i32` >::add(1u32, 2); //~^ ERROR mismatched types >::add(1, 2u32); diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index eaab6ff3d9a..22647622128 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -18,8 +18,26 @@ LL | >::add(1, 2); <&'a isize as Add> and 48 others +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 + | +LL | >::add(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | + = help: the trait `Add` is not implemented for `i32` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> + and 48 others + error[E0308]: mismatched types - --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 + --> $DIR/ufcs-qpath-self-mismatch.rs:8:28 | LL | >::add(1u32, 2); | ---------------------- ^^^^ expected `i32`, found `u32` @@ -37,7 +55,7 @@ LL | >::add(1i32, 2); | ~~~ error[E0308]: mismatched types - --> $DIR/ufcs-qpath-self-mismatch.rs:9:31 + --> $DIR/ufcs-qpath-self-mismatch.rs:10:31 | LL | >::add(1, 2u32); | ---------------------- ^^^^ expected `i32`, found `u32` @@ -72,7 +90,7 @@ LL | >::add(1, 2); <&'a isize as Add> and 48 others -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. From 31f259ce5a400801daecd76760a7665aaf130643 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 10 Sep 2022 07:44:56 +0000 Subject: [PATCH 15/19] Add `const_trait` to `Allocator` --- library/core/src/alloc/mod.rs | 1 + library/core/src/lib.rs | 1 + library/core/src/ops/function.rs | 3 +++ 3 files changed, 5 insertions(+) diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 94efa76664f..61553157478 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -107,6 +107,7 @@ impl fmt::Display for AllocError { /// /// [*currently allocated*]: #currently-allocated-memory #[unstable(feature = "allocator_api", issue = "32838")] +#[const_trait] pub unsafe trait Allocator { /// Attempts to allocate a block of memory. /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5621d15c1cd..593835c3724 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -140,6 +140,7 @@ #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_swap)] #![feature(const_trait_impl)] +#![feature(const_try)] #![feature(const_type_id)] #![feature(const_type_name)] #![feature(const_default_impls)] diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 8fdf22cf6f2..2e0a752c815 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -71,6 +71,7 @@ )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] +#[cfg_attr(not(bootstrap), const_trait)] pub trait Fn: FnMut { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -158,6 +159,7 @@ pub trait Fn: FnMut { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] +#[cfg_attr(not(bootstrap), const_trait)] pub trait FnMut: FnOnce { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -237,6 +239,7 @@ pub trait FnMut: FnOnce { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] +#[cfg_attr(not(bootstrap), const_trait)] pub trait FnOnce { /// The returned type after the call operator is used. #[lang = "fn_once_output"] From 08aeb1aa9b8baff7025fa4ae9958ce2ca0876c40 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 15 Sep 2022 15:48:35 +0000 Subject: [PATCH 16/19] unconditionally remap to nonconst in borrowck --- compiler/rustc_borrowck/src/type_check/mod.rs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 79e7eb0f1cc..9aea99b6a12 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -424,31 +424,19 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() { - // N.B.: When instantiating a trait method as a function item, it does not actually matter - // whether the trait is `const` or not, or whether `where T: ~const Tr` needs to be satisfied - // as `const`. If we were to introduce instantiating trait methods as `const fn`s, we would - // check that after this, either via a bound `where F: ~const FnOnce` or when coercing to a - // `const fn` pointer. - // - // FIXME(fee1-dead) FIXME(const_trait_impl): update this doc when trait methods can satisfy - // `~const FnOnce` or can be coerced to `const fn` pointer. - let const_norm = self.tcx().def_kind(def_id) == hir::def::DefKind::AssocFn - && self.tcx().def_kind(ty::DefIdTree::parent(self.tcx(), def_id)) - == hir::def::DefKind::Trait; - + // const_trait_impl: use a non-const param env when checking that a FnDef type is well formed. + // this is because the well-formedness of the function does not need to be proved to have `const` + // impls for trait bounds. let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); let prev = self.cx.param_env; - if const_norm { - self.cx.param_env = prev.without_const(); - } + self.cx.param_env = prev.without_const(); self.cx.normalize_and_prove_instantiated_predicates( def_id, instantiated_predicates, locations, ); - if const_norm { - self.cx.param_env = prev; - } + self.cx.param_env = prev; + } } } From 5ead742e18787b669ed33b82530d77b56f5928f5 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 16 Sep 2022 11:38:28 +0800 Subject: [PATCH 17/19] remap ParamEnv with obligation --- compiler/rustc_borrowck/src/type_check/mod.rs | 1 - compiler/rustc_infer/src/traits/mod.rs | 8 ++++++++ compiler/rustc_middle/src/ty/mod.rs | 5 +++++ .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 18 +++++++++++------- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9aea99b6a12..4bdeaccf668 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -436,7 +436,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { locations, ); self.cx.param_env = prev; - } } } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 4df4de21a0f..da3b45a4d6b 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -67,6 +67,14 @@ impl<'tcx> PredicateObligation<'tcx> { recursion_depth: self.recursion_depth, }) } + + pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> { + self.param_env = self.param_env.without_const(); + if let ty::PredicateKind::Trait(trait_pred) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() { + self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Trait(trait_pred.without_const()))); + } + self + } } impl<'tcx> TraitObligation<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e8fe37e7dab..23a3fcd974a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -861,6 +861,11 @@ impl<'tcx> TraitPredicate<'tcx> { (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false, } } + + pub fn without_const(mut self) -> Self { + self.constness = BoundConstness::NotConst; + self + } } impl<'tcx> PolyTraitPredicate<'tcx> { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 31eb2b65476..2de6fcb5c2f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1418,12 +1418,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs: SubstsRef<'tcx>, code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>, ) { - let mut param_env = self.param_env; - match self.tcx.def_kind(def_id) { + let param_env = self.param_env; + + let remap = match self.tcx.def_kind(def_id) { // Associated consts have `Self: ~const Trait` bounds that should be satisfiable when // `Self: Trait` is satisfied because it does not matter whether the impl is `const`. // Therefore we have to remap the param env here to be non-const. - hir::def::DefKind::AssocConst => param_env = param_env.without_const(), + hir::def::DefKind::AssocConst => true, hir::def::DefKind::AssocFn if self.tcx.def_kind(self.tcx.parent(def_id)) == hir::def::DefKind::Trait => { @@ -1437,19 +1438,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // FIXME(fee1-dead) FIXME(const_trait_impl): update this doc when trait methods can satisfy // `~const FnOnce` or can be coerced to `const fn` pointer. - param_env = param_env.without_const(); + true } - _ => {} - } + _ => false, + }; let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); - for obligation in traits::predicates_for_generics( + for mut obligation in traits::predicates_for_generics( |idx, predicate_span| { traits::ObligationCause::new(span, self.body_id, code(idx, predicate_span)) }, param_env, bounds, ) { + if remap { + obligation = obligation.without_const(self.tcx); + } self.register_predicate(obligation); } } From 191d3b76db5ee0f7a05ff79b6d584dde5f6e404f Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 17 Sep 2022 13:31:04 +0000 Subject: [PATCH 18/19] bless tests again --- src/test/ui/const-generics/issue-93647.rs | 2 +- src/test/ui/const-generics/issue-93647.stderr | 15 ++++--- src/test/ui/consts/issue-28113.rs | 2 +- src/test/ui/consts/issue-28113.stderr | 15 ++++--- src/test/ui/consts/issue-56164.rs | 5 +-- src/test/ui/consts/issue-56164.stderr | 44 +++++-------------- .../issue-68542-closure-in-array-len.rs | 2 +- .../issue-68542-closure-in-array-len.stderr | 15 ++++--- .../ui/consts/unstable-const-fn-in-libcore.rs | 6 +-- .../unstable-const-fn-in-libcore.stderr | 29 ++++-------- src/test/ui/issues/issue-20605.stderr | 2 +- src/test/ui/issues/issue-32709.stderr | 4 +- .../ui/suggestions/slice-issue-87994.stderr | 8 ++-- src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs | 1 - .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 24 ++-------- 15 files changed, 67 insertions(+), 107 deletions(-) diff --git a/src/test/ui/const-generics/issue-93647.rs b/src/test/ui/const-generics/issue-93647.rs index c1a6bf6e34d..655d721712e 100644 --- a/src/test/ui/const-generics/issue-93647.rs +++ b/src/test/ui/const-generics/issue-93647.rs @@ -1,6 +1,6 @@ struct X; fn main() {} diff --git a/src/test/ui/const-generics/issue-93647.stderr b/src/test/ui/const-generics/issue-93647.stderr index e2048ecd60f..fc53375ca43 100644 --- a/src/test/ui/const-generics/issue-93647.stderr +++ b/src/test/ui/const-generics/issue-93647.stderr @@ -1,12 +1,17 @@ -error[E0015]: cannot call non-const closure in constants +error[E0277]: the trait bound `[closure@$DIR/issue-93647.rs:2:6: 2:8]: Fn<()>` is not satisfied + --> $DIR/issue-93647.rs:2:5 + | +LL | (||1usize)() + | ^^^^^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-93647.rs:2:6: 2:8]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-93647.rs:2:6: 2:8]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-93647.rs:2:6: 2:8]`, but that implementation is not `const` --> $DIR/issue-93647.rs:2:5 | LL | (||1usize)() | ^^^^^^^^^^^^ - | - = note: closures need an RFC before allowed to be called in constants - = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: wrap the `[closure@$DIR/issue-93647.rs:2:6: 2:8]` in a closure with no arguments: `|| { /* code */ }` error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/issue-28113.rs b/src/test/ui/consts/issue-28113.rs index f8131c9f3b7..9ba8105d141 100644 --- a/src/test/ui/consts/issue-28113.rs +++ b/src/test/ui/consts/issue-28113.rs @@ -2,7 +2,7 @@ const X: u8 = || -> u8 { 5 }() - //~^ ERROR cannot call non-const closure + //~^ ERROR the trait bound ; fn main() {} diff --git a/src/test/ui/consts/issue-28113.stderr b/src/test/ui/consts/issue-28113.stderr index 7ad1f752eb0..45cacab1018 100644 --- a/src/test/ui/consts/issue-28113.stderr +++ b/src/test/ui/consts/issue-28113.stderr @@ -1,12 +1,17 @@ -error[E0015]: cannot call non-const closure in constants +error[E0277]: the trait bound `[closure@$DIR/issue-28113.rs:4:5: 4:13]: Fn<()>` is not satisfied + --> $DIR/issue-28113.rs:4:5 + | +LL | || -> u8 { 5 }() + | ^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-28113.rs:4:5: 4:13]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-28113.rs:4:5: 4:13]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-28113.rs:4:5: 4:13]`, but that implementation is not `const` --> $DIR/issue-28113.rs:4:5 | LL | || -> u8 { 5 }() | ^^^^^^^^^^^^^^^^ - | - = note: closures need an RFC before allowed to be called in constants - = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: wrap the `[closure@$DIR/issue-28113.rs:4:5: 4:13]` in a closure with no arguments: `|| { /* code */ }` error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/issue-56164.rs b/src/test/ui/consts/issue-56164.rs index 094ca377e03..f5bb438a26e 100644 --- a/src/test/ui/consts/issue-56164.rs +++ b/src/test/ui/consts/issue-56164.rs @@ -1,11 +1,8 @@ const fn foo() { (||{})() } -//~^ ERROR cannot call non-const closure -//~| ERROR erroneous constant used [const_err] -//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~^ ERROR the trait bound const fn bad(input: fn()) { input() - //~^ ERROR function pointer } fn main() { diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr index 73a0f8ec0d0..5433a711d97 100644 --- a/src/test/ui/consts/issue-56164.stderr +++ b/src/test/ui/consts/issue-56164.stderr @@ -1,39 +1,17 @@ -error[E0015]: cannot call non-const closure in constant functions +error[E0277]: the trait bound `[closure@$DIR/issue-56164.rs:1:19: 1:21]: Fn<()>` is not satisfied + --> $DIR/issue-56164.rs:1:18 + | +LL | const fn foo() { (||{})() } + | ^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-56164.rs:1:19: 1:21]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-56164.rs:1:19: 1:21]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-56164.rs:1:19: 1:21]`, but that implementation is not `const` --> $DIR/issue-56164.rs:1:18 | LL | const fn foo() { (||{})() } | ^^^^^^^^ - | - = note: closures need an RFC before allowed to be called in constant functions - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: wrap the `[closure@$DIR/issue-56164.rs:1:19: 1:21]` in a closure with no arguments: `|| { /* code */ }` -error: function pointer calls are not allowed in constant functions - --> $DIR/issue-56164.rs:7:5 - | -LL | input() - | ^^^^^^^ - -error: erroneous constant used - --> $DIR/issue-56164.rs:1:18 - | -LL | const fn foo() { (||{})() } - | ^^^^^^ referenced constant has errors - | - = note: `#[deny(const_err)]` 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 #71800 - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0015`. -Future incompatibility report: Future breakage diagnostic: -error: erroneous constant used - --> $DIR/issue-56164.rs:1:18 - | -LL | const fn foo() { (||{})() } - | ^^^^^^ referenced constant has errors - | - = note: `#[deny(const_err)]` 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 #71800 +error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/issue-68542-closure-in-array-len.rs b/src/test/ui/consts/issue-68542-closure-in-array-len.rs index 37958e7919d..68d4c191716 100644 --- a/src/test/ui/consts/issue-68542-closure-in-array-len.rs +++ b/src/test/ui/consts/issue-68542-closure-in-array-len.rs @@ -3,7 +3,7 @@ // in the length part of an array. struct Bug { - a: [(); (|| { 0 })()] //~ ERROR cannot call non-const closure + a: [(); (|| { 0 })()] //~ ERROR the trait bound } fn main() {} diff --git a/src/test/ui/consts/issue-68542-closure-in-array-len.stderr b/src/test/ui/consts/issue-68542-closure-in-array-len.stderr index 74fbbc680f7..d7fe59dc8fe 100644 --- a/src/test/ui/consts/issue-68542-closure-in-array-len.stderr +++ b/src/test/ui/consts/issue-68542-closure-in-array-len.stderr @@ -1,12 +1,17 @@ -error[E0015]: cannot call non-const closure in constants +error[E0277]: the trait bound `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]: Fn<()>` is not satisfied + --> $DIR/issue-68542-closure-in-array-len.rs:6:13 + | +LL | a: [(); (|| { 0 })()] + | ^^^^^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]`, but that implementation is not `const` --> $DIR/issue-68542-closure-in-array-len.rs:6:13 | LL | a: [(); (|| { 0 })()] | ^^^^^^^^^^^^ - | - = note: closures need an RFC before allowed to be called in constants - = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: wrap the `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]` in a closure with no arguments: `|| { /* code */ }` error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs index 16b36c8d56d..b9e7e1405f9 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.rs +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs @@ -4,7 +4,7 @@ // gate was not enabled in libcore. #![stable(feature = "core", since = "1.6.0")] -#![feature(staged_api)] +#![feature(staged_api, const_trait_impl)] enum Opt { Some(T), @@ -14,12 +14,12 @@ enum Opt { impl Opt { #[rustc_const_unstable(feature = "foo", issue = "none")] #[stable(feature = "rust1", since = "1.0.0")] - const fn unwrap_or_else T>(self, f: F) -> T { + const fn unwrap_or_else T>(self, f: F) -> T { //~^ ERROR destructors cannot be evaluated at compile-time //~| ERROR destructors cannot be evaluated at compile-time match self { Opt::Some(t) => t, - Opt::None => f(), //~ ERROR E0015 + Opt::None => f(), } } } diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr index 180f9f10cc6..fee74bd0a6c 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,34 +1,21 @@ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/unstable-const-fn-in-libcore.rs:22:26 - | -LL | Opt::None => f(), - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn unwrap_or_else T + ~const std::ops::FnOnce<()>>(self, f: F) -> T { - | +++++++++++++++++++++++++++++ - error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/unstable-const-fn-in-libcore.rs:17:53 + --> $DIR/unstable-const-fn-in-libcore.rs:17:60 | -LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^ constant functions cannot evaluate destructors +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^ constant functions cannot evaluate destructors ... LL | } | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/unstable-const-fn-in-libcore.rs:17:47 + --> $DIR/unstable-const-fn-in-libcore.rs:17:54 | -LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^^^^ constant functions cannot evaluate destructors +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^^^^ constant functions cannot evaluate destructors ... LL | } | - value is dropped here -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index c8e1313f573..e1858b63989 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `dyn Iterator` cann --> $DIR/issue-20605.rs:2:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ the trait `~const IntoIterator` is not implemented for `dyn Iterator` + | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` | = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required for `dyn Iterator` to implement `IntoIterator` diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index 355b110b465..1d595ca5649 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -7,7 +7,9 @@ LL | Err(5)?; | ^ the trait `From<{integer}>` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the trait `FromResidual>` is implemented for `Result` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual>> = note: required for `Result` to implement `FromResidual>` error: aborting due to previous error diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr index c6eb690ba5a..84ecd749b0d 100644 --- a/src/test/ui/suggestions/slice-issue-87994.stderr +++ b/src/test/ui/suggestions/slice-issue-87994.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { - | ^^^^^^ the trait `~const IntoIterator` is not implemented for `[i32]` + | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]` | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required for `[i32]` to implement `IntoIterator` @@ -17,7 +17,7 @@ error[E0277]: `[i32]` is not an iterator --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { - | ^^^^^^ the trait `~const IntoIterator` is not implemented for `[i32]` + | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]` | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required for `[i32]` to implement `IntoIterator` @@ -32,7 +32,7 @@ error[E0277]: the size for values of type `[K]` cannot be known at compilation t --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { - | ^^^^^^^ the trait `~const IntoIterator` is not implemented for `[K]` + | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]` | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required for `[K]` to implement `IntoIterator` @@ -47,7 +47,7 @@ error[E0277]: `[K]` is not an iterator --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { - | ^^^^^^^ the trait `~const IntoIterator` is not implemented for `[K]` + | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]` | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required for `[K]` to implement `IntoIterator` diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs index 1a07dc46c5e..ec86213f862 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs @@ -4,7 +4,6 @@ fn main() { >::add(1, 2); //~^ ERROR cannot add `u32` to `i32` //~| ERROR cannot add `u32` to `i32` - //~| ERROR cannot add `u32` to `i32` >::add(1u32, 2); //~^ ERROR mismatched types >::add(1, 2u32); diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 22647622128..eaab6ff3d9a 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -18,26 +18,8 @@ LL | >::add(1, 2); <&'a isize as Add> and 48 others -error[E0277]: cannot add `u32` to `i32` - --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 - | -LL | >::add(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` - | - = help: the trait `Add` is not implemented for `i32` - = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others - error[E0308]: mismatched types - --> $DIR/ufcs-qpath-self-mismatch.rs:8:28 + --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 | LL | >::add(1u32, 2); | ---------------------- ^^^^ expected `i32`, found `u32` @@ -55,7 +37,7 @@ LL | >::add(1i32, 2); | ~~~ error[E0308]: mismatched types - --> $DIR/ufcs-qpath-self-mismatch.rs:10:31 + --> $DIR/ufcs-qpath-self-mismatch.rs:9:31 | LL | >::add(1, 2u32); | ---------------------- ^^^^ expected `i32`, found `u32` @@ -90,7 +72,7 @@ LL | >::add(1, 2); <&'a isize as Add> and 48 others -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. From 898c76cd8257ffd91e9de9714215ece477e1065b Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 21 Sep 2022 15:02:15 +0000 Subject: [PATCH 19/19] Make error messages great again (and fix clippy and add test) --- compiler/rustc_typeck/src/check/mod.rs | 6 ++- src/test/ui/const-generics/issue-93647.rs | 2 +- src/test/ui/const-generics/issue-93647.stderr | 15 +++---- src/test/ui/consts/issue-28113.rs | 2 +- src/test/ui/consts/issue-28113.stderr | 15 +++---- src/test/ui/consts/issue-56164.rs | 5 ++- src/test/ui/consts/issue-56164.stderr | 44 ++++++++++++++----- .../issue-68542-closure-in-array-len.rs | 2 +- .../issue-68542-closure-in-array-len.stderr | 15 +++---- .../nested-closure.rs | 12 +++++ 10 files changed, 72 insertions(+), 46 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index cfae63e4a06..bf48f11e7d9 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -366,7 +366,7 @@ fn typeck_with_fallback<'tcx>( let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); - let fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { + let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); >::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None) @@ -459,7 +459,11 @@ fn typeck_with_fallback<'tcx>( // Closure and generator analysis may run after fallback // because they don't constrain other type variables. + // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now) + let prev_constness = fcx.param_env.constness(); + fcx.param_env = fcx.param_env.without_const(); fcx.closure_analyze(body); + fcx.param_env = fcx.param_env.with_constness(prev_constness); assert!(fcx.deferred_call_resolutions.borrow().is_empty()); // Before the generator analysis, temporary scopes shall be marked to provide more // precise information on types to be captured. diff --git a/src/test/ui/const-generics/issue-93647.rs b/src/test/ui/const-generics/issue-93647.rs index 655d721712e..806540e1775 100644 --- a/src/test/ui/const-generics/issue-93647.rs +++ b/src/test/ui/const-generics/issue-93647.rs @@ -1,6 +1,6 @@ struct X; fn main() {} diff --git a/src/test/ui/const-generics/issue-93647.stderr b/src/test/ui/const-generics/issue-93647.stderr index fc53375ca43..e2048ecd60f 100644 --- a/src/test/ui/const-generics/issue-93647.stderr +++ b/src/test/ui/const-generics/issue-93647.stderr @@ -1,17 +1,12 @@ -error[E0277]: the trait bound `[closure@$DIR/issue-93647.rs:2:6: 2:8]: Fn<()>` is not satisfied - --> $DIR/issue-93647.rs:2:5 - | -LL | (||1usize)() - | ^^^^^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-93647.rs:2:6: 2:8]` - | - = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-93647.rs:2:6: 2:8]` -note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-93647.rs:2:6: 2:8]`, but that implementation is not `const` +error[E0015]: cannot call non-const closure in constants --> $DIR/issue-93647.rs:2:5 | LL | (||1usize)() | ^^^^^^^^^^^^ - = note: wrap the `[closure@$DIR/issue-93647.rs:2:6: 2:8]` in a closure with no arguments: `|| { /* code */ }` + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/issue-28113.rs b/src/test/ui/consts/issue-28113.rs index 9ba8105d141..f8131c9f3b7 100644 --- a/src/test/ui/consts/issue-28113.rs +++ b/src/test/ui/consts/issue-28113.rs @@ -2,7 +2,7 @@ const X: u8 = || -> u8 { 5 }() - //~^ ERROR the trait bound + //~^ ERROR cannot call non-const closure ; fn main() {} diff --git a/src/test/ui/consts/issue-28113.stderr b/src/test/ui/consts/issue-28113.stderr index 45cacab1018..7ad1f752eb0 100644 --- a/src/test/ui/consts/issue-28113.stderr +++ b/src/test/ui/consts/issue-28113.stderr @@ -1,17 +1,12 @@ -error[E0277]: the trait bound `[closure@$DIR/issue-28113.rs:4:5: 4:13]: Fn<()>` is not satisfied - --> $DIR/issue-28113.rs:4:5 - | -LL | || -> u8 { 5 }() - | ^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-28113.rs:4:5: 4:13]` - | - = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-28113.rs:4:5: 4:13]` -note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-28113.rs:4:5: 4:13]`, but that implementation is not `const` +error[E0015]: cannot call non-const closure in constants --> $DIR/issue-28113.rs:4:5 | LL | || -> u8 { 5 }() | ^^^^^^^^^^^^^^^^ - = note: wrap the `[closure@$DIR/issue-28113.rs:4:5: 4:13]` in a closure with no arguments: `|| { /* code */ }` + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/issue-56164.rs b/src/test/ui/consts/issue-56164.rs index f5bb438a26e..fd02d215480 100644 --- a/src/test/ui/consts/issue-56164.rs +++ b/src/test/ui/consts/issue-56164.rs @@ -1,8 +1,11 @@ const fn foo() { (||{})() } -//~^ ERROR the trait bound +//~^ ERROR cannot call non-const closure +//~| ERROR erroneous constant +//~| WARN this was previously accepted const fn bad(input: fn()) { input() + //~^ ERROR function pointer calls are not allowed } fn main() { diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr index 5433a711d97..73a0f8ec0d0 100644 --- a/src/test/ui/consts/issue-56164.stderr +++ b/src/test/ui/consts/issue-56164.stderr @@ -1,17 +1,39 @@ -error[E0277]: the trait bound `[closure@$DIR/issue-56164.rs:1:19: 1:21]: Fn<()>` is not satisfied - --> $DIR/issue-56164.rs:1:18 - | -LL | const fn foo() { (||{})() } - | ^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-56164.rs:1:19: 1:21]` - | - = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-56164.rs:1:19: 1:21]` -note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-56164.rs:1:19: 1:21]`, but that implementation is not `const` +error[E0015]: cannot call non-const closure in constant functions --> $DIR/issue-56164.rs:1:18 | LL | const fn foo() { (||{})() } | ^^^^^^^^ - = note: wrap the `[closure@$DIR/issue-56164.rs:1:19: 1:21]` in a closure with no arguments: `|| { /* code */ }` + | + = note: closures need an RFC before allowed to be called in constant functions + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: function pointer calls are not allowed in constant functions + --> $DIR/issue-56164.rs:7:5 + | +LL | input() + | ^^^^^^^ + +error: erroneous constant used + --> $DIR/issue-56164.rs:1:18 + | +LL | const fn foo() { (||{})() } + | ^^^^^^ referenced constant has errors + | + = note: `#[deny(const_err)]` 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 #71800 + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0015`. +Future incompatibility report: Future breakage diagnostic: +error: erroneous constant used + --> $DIR/issue-56164.rs:1:18 + | +LL | const fn foo() { (||{})() } + | ^^^^^^ referenced constant has errors + | + = note: `#[deny(const_err)]` 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 #71800 -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/issue-68542-closure-in-array-len.rs b/src/test/ui/consts/issue-68542-closure-in-array-len.rs index 68d4c191716..37958e7919d 100644 --- a/src/test/ui/consts/issue-68542-closure-in-array-len.rs +++ b/src/test/ui/consts/issue-68542-closure-in-array-len.rs @@ -3,7 +3,7 @@ // in the length part of an array. struct Bug { - a: [(); (|| { 0 })()] //~ ERROR the trait bound + a: [(); (|| { 0 })()] //~ ERROR cannot call non-const closure } fn main() {} diff --git a/src/test/ui/consts/issue-68542-closure-in-array-len.stderr b/src/test/ui/consts/issue-68542-closure-in-array-len.stderr index d7fe59dc8fe..74fbbc680f7 100644 --- a/src/test/ui/consts/issue-68542-closure-in-array-len.stderr +++ b/src/test/ui/consts/issue-68542-closure-in-array-len.stderr @@ -1,17 +1,12 @@ -error[E0277]: the trait bound `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]: Fn<()>` is not satisfied - --> $DIR/issue-68542-closure-in-array-len.rs:6:13 - | -LL | a: [(); (|| { 0 })()] - | ^^^^^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]` - | - = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]` -note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]`, but that implementation is not `const` +error[E0015]: cannot call non-const closure in constants --> $DIR/issue-68542-closure-in-array-len.rs:6:13 | LL | a: [(); (|| { 0 })()] | ^^^^^^^^^^^^ - = note: wrap the `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]` in a closure with no arguments: `|| { /* code */ }` + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs b/src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs new file mode 100644 index 00000000000..a851136009c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(const_trait_impl, once_cell)] + +use std::sync::LazyLock; + +static EXTERN_FLAGS: LazyLock = LazyLock::new(|| { + let x = || String::new(); + x() +}); + +fn main() {}