Move const trait bounds checks to MIR constck

Fixes #109543. When checking paths in HIR typeck, we don't want to check
for const predicates since all we want might just be a function pointer.
Therefore we move this to MIR constck and check that bounds are met
during MIR constck.
This commit is contained in:
Deadbeef 2023-03-24 09:17:51 +00:00
parent cbc064b341
commit b17e6680d6
27 changed files with 438 additions and 323 deletions

View File

@ -722,6 +722,32 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
};
// Check that all trait bounds that are marked as `~const` can be satisfied.
//
// Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
// which path expressions are getting called on and which path expressions are only used
// as function pointers. This is required for correctness.
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
let cause = ObligationCause::new(
terminator.source_info.span,
self.body.source.def_id().expect_local(),
ObligationCauseCode::ItemObligation(callee),
);
let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
ocx.register_obligations(traits::predicates_for_generics(
|_, _| cause.clone(),
self.param_env,
normalized_predicates,
));
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
}
// Attempting to call a trait method?
if let Some(trait_id) = tcx.trait_of_item(callee) {
trace!("attempting to call a trait method");
@ -749,31 +775,6 @@ 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.
{
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
let cause = ObligationCause::new(
terminator.source_info.span,
self.body.source.def_id().expect_local(),
ObligationCauseCode::ItemObligation(callee),
);
let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
ocx.register_obligations(traits::predicates_for_generics(
|_, _| cause.clone(),
self.param_env,
normalized_predicates,
));
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
}
}
match implsrc {
Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
debug!(

View File

@ -1416,41 +1416,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
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 => true,
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.
true
}
_ => false,
};
let bounds = self.instantiate_bounds(span, def_id, &substs);
for mut obligation in traits::predicates_for_generics(
for 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);
// N.B. We are remapping all predicates to non-const since we don't know if we just
// want them as function pointers or we are calling them from a const-context. The
// actual checking will occur in `rustc_const_eval::transform::check_consts`.
self.register_predicate(obligation.without_const(self.tcx));
}
}

View File

@ -1,6 +1,7 @@
struct X<const N: usize = {
(||1usize)()
//~^ ERROR cannot call non-const closure
//~| ERROR the trait bound
}>;
fn main() {}

View File

@ -1,3 +1,17 @@
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: wrap the `[closure@$DIR/issue-93647.rs:2:6: 2:8]` in a closure with no arguments: `|| { /* code */ }`
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-93647.rs:2:5
|
@ -8,6 +22,7 @@ LL | (||1usize)()
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,43 +1,29 @@
error[E0277]: can't drop `UnconstDrop` in const contexts
--> $DIR/const-block-const-bound.rs:20:11
--> $DIR/const-block-const-bound.rs:20:9
|
LL | f(UnconstDrop);
| - ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop`
| |
| required by a bound introduced by this call
| ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop`
|
= note: the trait bound `UnconstDrop: ~const Destruct` is not satisfied
note: required by a bound in `f`
--> $DIR/const-block-const-bound.rs:6:15
|
LL | const fn f<T: ~const Destruct>(x: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `f`
help: consider borrowing here
|
LL | f(&UnconstDrop);
LL | &f(UnconstDrop);
| +
LL | f(&mut UnconstDrop);
LL | &mut f(UnconstDrop);
| ++++
error[E0277]: can't drop `NonDrop` in const contexts
--> $DIR/const-block-const-bound.rs:22:11
--> $DIR/const-block-const-bound.rs:22:9
|
LL | f(NonDrop);
| - ^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop`
| |
| required by a bound introduced by this call
| ^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop`
|
= note: the trait bound `NonDrop: ~const Destruct` is not satisfied
note: required by a bound in `f`
--> $DIR/const-block-const-bound.rs:6:15
|
LL | const fn f<T: ~const Destruct>(x: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `f`
help: consider borrowing here
|
LL | f(&NonDrop);
LL | &f(NonDrop);
| +
LL | f(&mut NonDrop);
LL | &mut f(NonDrop);
| ++++
error: aborting due to 2 previous errors

View File

@ -5,5 +5,6 @@ fn main() {
match () {
const { (|| {})() } => {}
//~^ ERROR cannot call non-const closure in constants
//~| ERROR the trait bound
}
}

View File

@ -1,3 +1,17 @@
error[E0277]: the trait bound `[closure@$DIR/invalid-inline-const-in-match-arm.rs:6:18: 6:20]: Fn<()>` is not satisfied
--> $DIR/invalid-inline-const-in-match-arm.rs:6:17
|
LL | const { (|| {})() } => {}
| ^^^^^^^^^ expected an `Fn<()>` closure, found `[closure@$DIR/invalid-inline-const-in-match-arm.rs:6:18: 6:20]`
|
= help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/invalid-inline-const-in-match-arm.rs:6:18: 6:20]`
note: the trait `Fn<()>` is implemented for `[closure@$DIR/invalid-inline-const-in-match-arm.rs:6:18: 6:20]`, but that implementation is not `const`
--> $DIR/invalid-inline-const-in-match-arm.rs:6:17
|
LL | const { (|| {})() } => {}
| ^^^^^^^^^
= note: wrap the `[closure@$DIR/invalid-inline-const-in-match-arm.rs:6:18: 6:20]` in a closure with no arguments: `|| { /* code */ }`
error[E0015]: cannot call non-const closure in constants
--> $DIR/invalid-inline-const-in-match-arm.rs:6:17
|
@ -8,6 +22,7 @@ LL | const { (|| {})() } => {}
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -3,6 +3,7 @@
const X: u8 =
|| -> u8 { 5 }()
//~^ ERROR cannot call non-const closure
//~| ERROR the trait bound
;
fn main() {}

View File

@ -1,3 +1,17 @@
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: wrap the `[closure@$DIR/issue-28113.rs:4:5: 4:13]` in a closure with no arguments: `|| { /* code */ }`
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-28113.rs:4:5
|
@ -8,6 +22,7 @@ LL | || -> u8 { 5 }()
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,5 +1,6 @@
const fn foo() { (||{})() }
//~^ ERROR cannot call non-const closure
//~| ERROR the trait bound
const fn bad(input: fn()) {
input()

View File

@ -1,3 +1,17 @@
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: wrap the `[closure@$DIR/issue-56164.rs:1:19: 1:21]` in a closure with no arguments: `|| { /* code */ }`
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/issue-56164.rs:1:18
|
@ -9,7 +23,7 @@ LL | const fn foo() { (||{})() }
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
error: function pointer calls are not allowed in constant functions
--> $DIR/issue-56164.rs:5:5
--> $DIR/issue-56164.rs:6:5
|
LL | input()
| ^^^^^^^
@ -26,6 +40,7 @@ note: erroneous constant used
LL | const fn foo() { (||{})() }
| ^^^^^^
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -4,6 +4,7 @@
struct Bug {
a: [(); (|| { 0 })()] //~ ERROR cannot call non-const closure
//~^ ERROR the trait bound
}
fn main() {}

View File

@ -1,3 +1,17 @@
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: wrap the `[closure@$DIR/issue-68542-closure-in-array-len.rs:6:14: 6:16]` in a closure with no arguments: `|| { /* code */ }`
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-68542-closure-in-array-len.rs:6:13
|
@ -8,6 +22,7 @@ LL | a: [(); (|| { 0 })()]
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -11,4 +11,5 @@ fn main() {
//~| ERROR cannot convert
//~| ERROR mutable references
//~| ERROR cannot call
//~| ERROR the trait bound
}

View File

@ -58,6 +58,19 @@ LL | [(); { for _ in 0usize.. {}; 0}];
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0277]: the trait bound `RangeFrom<usize>: Iterator` is not satisfied
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
| ^^^^^^^^ `RangeFrom<usize>` is not an iterator
|
= help: the trait `~const Iterator` is not implemented for `RangeFrom<usize>`
note: the trait `Iterator` is implemented for `RangeFrom<usize>`, but that implementation is not `const`
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
| ^^^^^^^^
error[E0015]: cannot call non-const fn `<RangeFrom<usize> as Iterator>::next` in constants
--> $DIR/issue-52443.rs:9:21
|
@ -67,7 +80,7 @@ LL | [(); { for _ in 0usize.. {}; 0}];
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
error: aborting due to 6 previous errors; 1 warning emitted
error: aborting due to 7 previous errors; 1 warning emitted
Some errors have detailed explanations: E0015, E0308, E0658.
Some errors have detailed explanations: E0015, E0277, E0308, E0658.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,21 +1,14 @@
error[E0277]: the trait bound `S: ~const Foo` is not satisfied
--> $DIR/call-generic-method-nonconst.rs:23:34
--> $DIR/call-generic-method-nonconst.rs:23:22
|
LL | pub const EQ: bool = equals_self(&S);
| ----------- ^^ the trait `~const Foo` is not implemented for `S`
| |
| required by a bound introduced by this call
| ^^^^^^^^^^^^^^^ the trait `~const Foo` is not implemented for `S`
|
note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
--> $DIR/call-generic-method-nonconst.rs:23:34
--> $DIR/call-generic-method-nonconst.rs:23:22
|
LL | pub const EQ: bool = equals_self(&S);
| ^^
note: required by a bound in `equals_self`
--> $DIR/call-generic-method-nonconst.rs:16:25
|
LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
| ^^^^^^^^^^ required by this bound in `equals_self`
| ^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -1,22 +1,15 @@
error[E0277]: the trait bound `(): ~const Tr` is not satisfied in `fn(()) -> i32 {<() as Tr>::a}`
--> $DIR/const-closure-trait-method-fail.rs:16:42
--> $DIR/const-closure-trait-method-fail.rs:16:23
|
LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
| ------------------ ^^^^^ within `fn(()) -> i32 {<() as Tr>::a}`, the trait `~const Tr` is not implemented for `()`
| |
| required by a bound introduced by this call
| ^^^^^^^^^^^^^^^^^^^^^^^^^ within `fn(()) -> i32 {<() as Tr>::a}`, the trait `~const Tr` is not implemented for `()`
|
note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
--> $DIR/const-closure-trait-method-fail.rs:16:42
--> $DIR/const-closure-trait-method-fail.rs:16:23
|
LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
| ^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it appears within the type `fn(()) -> i32 {<() as Tr>::a}`
note: required by a bound in `need_const_closure`
--> $DIR/const-closure-trait-method-fail.rs:12:32
|
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `need_const_closure`
error: aborting due to previous error

View File

@ -0,0 +1,50 @@
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail-2.rs:31:23
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail-2.rs:31:23
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail-2.rs:21:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail-2.rs:31:64
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail-2.rs:31:64
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail-2.rs:21:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
--> $DIR/const-drop-fail-2.rs:37:9
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
| ^^^^^^^^
|
note: the implementor must specify the same requirement
--> $DIR/const-drop-fail-2.rs:35:1
|
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0367.
For more information about an error, try `rustc --explain E0277`.

View File

@ -0,0 +1,44 @@
// revisions: stock precise
#![feature(const_trait_impl)]
#![feature(const_mut_refs)]
#![cfg_attr(precise, feature(const_precise_live_drops))]
use std::marker::{Destruct, PhantomData};
struct NonTrivialDrop;
impl Drop for NonTrivialDrop {
fn drop(&mut self) {
println!("Non trivial drop");
}
}
#[const_trait]
trait A { fn a() { } }
impl A for NonTrivialDrop {}
struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
fn drop(&mut self) {
T::a();
}
}
const fn check<T: ~const Destruct>(_: T) {}
const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
//~^ ERROR the trait bound
//~| ERROR the trait bound
struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
//~^ ERROR `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
fn drop(&mut self) {
T::a();
}
}
fn main() {}

View File

@ -0,0 +1,50 @@
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail-2.rs:31:23
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail-2.rs:31:23
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail-2.rs:21:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail-2.rs:31:64
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail-2.rs:31:64
|
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(ConstDropImplWithBounds(PhantomData));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail-2.rs:21:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
--> $DIR/const-drop-fail-2.rs:37:9
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
| ^^^^^^^^
|
note: the implementor must specify the same requirement
--> $DIR/const-drop-fail-2.rs:35:1
|
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0367.
For more information about an error, try `rustc --explain E0277`.

View File

@ -1,99 +1,58 @@
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:44:5
--> $DIR/const-drop-fail.rs:26:23
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
| ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
...
LL | NonTrivialDrop,
| ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
|
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
|
LL | &NonTrivialDrop,
| +
LL | &mut NonTrivialDrop,
| ++++
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:46:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
...
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:46:5
--> $DIR/const-drop-fail.rs:26:23
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | const _: () = check($exp);
| ^^^^^^^^^^^
...
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
= note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:26:23
|
LL | const _: () = check($exp);
| ^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
...
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:26:23
|
LL | const _: () = check($exp);
| ^^^^^^^^^^^
...
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
note: required because it appears within the type `ConstImplWithDropGlue`
--> $DIR/const-drop-fail.rs:16:8
|
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
= note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail.rs:48:47
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
| |
| required by a bound introduced by this call
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:48:47
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail.rs:27:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error: aborting due to 2 previous errors
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail.rs:48:5
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:48:5
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail.rs:27:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
--> $DIR/const-drop-fail.rs:55:9
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
| ^^^^^^^^
|
note: the implementor must specify the same requirement
--> $DIR/const-drop-fail.rs:53:1
|
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0367.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0277`.

View File

@ -19,44 +19,19 @@ impl const Drop for ConstImplWithDropGlue {
fn drop(&mut self) {}
}
#[const_trait]
trait A { fn a() { } }
impl A for NonTrivialDrop {}
struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
fn drop(&mut self) {
T::a();
}
}
const fn check<T: ~const Destruct>(_: T) {}
macro_rules! check_all {
($($exp:expr),*$(,)?) => {$(
const _: () = check($exp);
//~^ ERROR can't drop
//~| ERROR can't drop
)*};
}
check_all! {
NonTrivialDrop,
//~^ ERROR can't drop
ConstImplWithDropGlue(NonTrivialDrop),
//~^ ERROR can't drop
ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
//~^ ERROR the trait bound
//~| ERROR the trait bound
}
struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
//~^ ERROR `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
fn drop(&mut self) {
T::a();
}
}
fn main() {}

View File

@ -1,99 +1,58 @@
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:44:5
--> $DIR/const-drop-fail.rs:26:23
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
| ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
...
LL | NonTrivialDrop,
| ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
|
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
|
LL | &NonTrivialDrop,
| +
LL | &mut NonTrivialDrop,
| ++++
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:46:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
...
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:46:5
--> $DIR/const-drop-fail.rs:26:23
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | const _: () = check($exp);
| ^^^^^^^^^^^
...
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
= note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:26:23
|
LL | const _: () = check($exp);
| ^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
...
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:26:23
|
LL | const _: () = check($exp);
| ^^^^^^^^^^^
...
LL | / check_all! {
LL | | NonTrivialDrop,
LL | | ConstImplWithDropGlue(NonTrivialDrop),
LL | | }
| |_- in this macro invocation
note: required because it appears within the type `ConstImplWithDropGlue`
--> $DIR/const-drop-fail.rs:16:8
|
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
= note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail.rs:48:47
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
| |
| required by a bound introduced by this call
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:48:47
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail.rs:27:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error: aborting due to 2 previous errors
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
--> $DIR/const-drop-fail.rs:48:5
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:48:5
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail.rs:27:35
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
--> $DIR/const-drop-fail.rs:55:9
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
| ^^^^^^^^
|
note: the implementor must specify the same requirement
--> $DIR/const-drop-fail.rs:53:1
|
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0367.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0277`.

View File

@ -9,5 +9,6 @@ impl Default for A {
#[derive_const(Default)]
pub struct S(A);
//~^ cannot call non-const fn
//~| the trait bound
fn main() {}

View File

@ -1,3 +1,24 @@
error[E0277]: the trait bound `A: Default` is not satisfied
--> $DIR/derive-const-non-const-type.rs:10:14
|
LL | #[derive_const(Default)]
| ------- in this derive macro expansion
LL | pub struct S(A);
| ^ the trait `~const Default` is not implemented for `A`
|
note: the trait `Default` is implemented for `A`, but that implementation is not `const`
--> $DIR/derive-const-non-const-type.rs:10:14
|
LL | #[derive_const(Default)]
| ------- in this derive macro expansion
LL | pub struct S(A);
| ^
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `A` with `#[derive(Default)]`
|
LL | #[derive(Default)]
|
error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions
--> $DIR/derive-const-non-const-type.rs:10:14
|
@ -10,6 +31,7 @@ LL | pub struct S(A);
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,19 +1,14 @@
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
--> $DIR/default-method-body-is-const-body-checking.rs:12:15
--> $DIR/default-method-body-is-const-body-checking.rs:12:9
|
LL | foo::<()>();
| ^^ the trait `~const Tr` is not implemented for `()`
| ^^^^^^^^^^^ the trait `~const Tr` is not implemented for `()`
|
note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
--> $DIR/default-method-body-is-const-body-checking.rs:12:15
--> $DIR/default-method-body-is-const-body-checking.rs:12:9
|
LL | foo::<()>();
| ^^
note: required by a bound in `foo`
--> $DIR/default-method-body-is-const-body-checking.rs:7:28
|
LL | const fn foo<T>() where T: ~const Tr {}
| ^^^^^^^^^ required by this bound in `foo`
| ^^^^^^^^^^^
error: aborting due to previous error

View File

@ -0,0 +1,15 @@
// check-pass
#![feature(const_trait_impl)]
#[const_trait]
pub trait Test {}
impl Test for () {}
pub const fn test<T: ~const Test>() {}
pub const fn min_by_i32() -> fn() {
test::<()>
}
fn main() {}