Rollup merge of #93358 - compiler-errors:is-not-const, r=fee1-dead
Add note suggesting that predicate may be satisfied, but is not `const` Not sure if we should be printing this in addition to, or perhaps _instead_ of the help message: ``` help: the trait `~const Add` is not implemented for `NonConstAdd` ``` Also added `ParamEnv::is_const` and `PolyTraitPredicate::is_const_if_const` and, in a separate commit, used those in other places instead of `== hir::Constness::Const`, etc. r? ````@fee1-dead````
This commit is contained in:
commit
103c3a38a6
@ -7,7 +7,6 @@ use crate::interpret::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
@ -216,7 +215,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
|
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
|
||||||
assert!(key.param_env.constness() == hir::Constness::Const);
|
assert!(key.param_env.is_const());
|
||||||
// see comment in eval_to_allocation_raw_provider for what we're doing here
|
// see comment in eval_to_allocation_raw_provider for what we're doing here
|
||||||
if key.param_env.reveal() == Reveal::All {
|
if key.param_env.reveal() == Reveal::All {
|
||||||
let mut key = key;
|
let mut key = key;
|
||||||
@ -251,7 +250,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
|
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
|
||||||
assert!(key.param_env.constness() == hir::Constness::Const);
|
assert!(key.param_env.is_const());
|
||||||
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
|
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
|
||||||
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
|
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
|
||||||
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
|
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
|
||||||
|
@ -86,7 +86,6 @@ declare_lint_pass!(
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||||
use rustc_middle::ty;
|
|
||||||
use rustc_middle::ty::PredicateKind::*;
|
use rustc_middle::ty::PredicateKind::*;
|
||||||
|
|
||||||
let predicates = cx.tcx.explicit_predicates_of(item.def_id);
|
let predicates = cx.tcx.explicit_predicates_of(item.def_id);
|
||||||
@ -94,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
|||||||
let Trait(trait_predicate) = predicate.kind().skip_binder() else {
|
let Trait(trait_predicate) = predicate.kind().skip_binder() else {
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
if trait_predicate.constness == ty::BoundConstness::ConstIfConst {
|
if trait_predicate.is_const_if_const() {
|
||||||
// `~const Drop` definitely have meanings so avoid linting here.
|
// `~const Drop` definitely have meanings so avoid linting here.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -784,6 +784,11 @@ impl<'tcx> TraitPredicate<'tcx> {
|
|||||||
pub fn self_ty(self) -> Ty<'tcx> {
|
pub fn self_ty(self) -> Ty<'tcx> {
|
||||||
self.trait_ref.self_ty()
|
self.trait_ref.self_ty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_const_if_const(self) -> bool {
|
||||||
|
self.constness == BoundConstness::ConstIfConst
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PolyTraitPredicate<'tcx> {
|
impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||||
@ -803,6 +808,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
|||||||
p
|
p
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_const_if_const(self) -> bool {
|
||||||
|
self.skip_binder().is_const_if_const()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||||
@ -1388,6 +1398,11 @@ impl<'tcx> ParamEnv<'tcx> {
|
|||||||
self.packed.tag().constness
|
self.packed.tag().constness
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_const(self) -> bool {
|
||||||
|
self.packed.tag().constness == hir::Constness::Const
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct a trait environment with no where-clauses in scope
|
/// Construct a trait environment with no where-clauses in scope
|
||||||
/// where the values of all `impl Trait` and other hidden types
|
/// where the values of all `impl Trait` and other hidden types
|
||||||
/// are revealed. This is suitable for monomorphized, post-typeck
|
/// are revealed. This is suitable for monomorphized, post-typeck
|
||||||
@ -1503,6 +1518,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
|
|||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::ImplPolarity::Positive,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn without_const(self) -> PolyTraitPredicate<'tcx> {
|
pub fn without_const(self) -> PolyTraitPredicate<'tcx> {
|
||||||
self.with_constness(BoundConstness::NotConst)
|
self.with_constness(BoundConstness::NotConst)
|
||||||
|
@ -439,6 +439,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
err.span_label(span, explanation);
|
err.span_label(span, explanation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
|
||||||
|
let non_const_predicate = trait_ref.without_const();
|
||||||
|
let non_const_obligation = Obligation {
|
||||||
|
cause: obligation.cause.clone(),
|
||||||
|
param_env: obligation.param_env.without_const(),
|
||||||
|
predicate: non_const_predicate.to_predicate(tcx),
|
||||||
|
recursion_depth: obligation.recursion_depth,
|
||||||
|
};
|
||||||
|
if self.predicate_may_hold(&non_const_obligation) {
|
||||||
|
err.span_note(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"the trait `{}` is implemented for `{}`, \
|
||||||
|
but that implementation is not `const`",
|
||||||
|
non_const_predicate.print_modifiers_and_trait_path(),
|
||||||
|
trait_ref.skip_binder().self_ty(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some((msg, span)) = type_def {
|
if let Some((msg, span)) = type_def {
|
||||||
err.span_label(span, &msg);
|
err.span_label(span, &msg);
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
} else if lang_items.unsize_trait() == Some(def_id) {
|
} else if lang_items.unsize_trait() == Some(def_id) {
|
||||||
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
|
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
|
||||||
} else if lang_items.drop_trait() == Some(def_id)
|
} else if lang_items.drop_trait() == Some(def_id)
|
||||||
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
|
&& obligation.predicate.is_const_if_const()
|
||||||
{
|
{
|
||||||
self.assemble_const_drop_candidates(obligation, &mut candidates);
|
self.assemble_const_drop_candidates(obligation, &mut candidates);
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,9 +72,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
// CheckPredicate(&A: Super)
|
// CheckPredicate(&A: Super)
|
||||||
// CheckPredicate(A: ~const Super) // <- still const env, failure
|
// CheckPredicate(A: ~const Super) // <- still const env, failure
|
||||||
// ```
|
// ```
|
||||||
if obligation.param_env.constness() == Constness::Const
|
if obligation.param_env.is_const() && !obligation.predicate.is_const_if_const() {
|
||||||
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::NotConst
|
|
||||||
{
|
|
||||||
new_obligation = TraitObligation {
|
new_obligation = TraitObligation {
|
||||||
cause: obligation.cause.clone(),
|
cause: obligation.cause.clone(),
|
||||||
param_env: obligation.param_env.without_const(),
|
param_env: obligation.param_env.without_const(),
|
||||||
|
@ -1173,9 +1173,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ImplCandidate(def_id)
|
ImplCandidate(def_id)
|
||||||
if tcx.impl_constness(def_id) == hir::Constness::Const => {}
|
if tcx.impl_constness(def_id) == hir::Constness::Const => {}
|
||||||
// const param
|
// const param
|
||||||
ParamCandidate(trait_pred)
|
ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {}
|
||||||
if trait_pred.skip_binder().constness
|
|
||||||
== ty::BoundConstness::ConstIfConst => {}
|
|
||||||
// auto trait impl
|
// auto trait impl
|
||||||
AutoImplCandidate(..) => {}
|
AutoImplCandidate(..) => {}
|
||||||
// generator, this will raise error in other places
|
// generator, this will raise error in other places
|
||||||
|
@ -7,6 +7,11 @@ LL | const_eval_select((), || {}, || {});
|
|||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
|
= help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
|
||||||
|
note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`, but that implementation is not `const`
|
||||||
|
--> $DIR/const-eval-select-bad.rs:6:27
|
||||||
|
|
|
||||||
|
LL | const_eval_select((), || {}, || {});
|
||||||
|
| ^^^^^
|
||||||
= note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` in a closure with no arguments: `|| { /* code */ }`
|
= note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` in a closure with no arguments: `|| { /* code */ }`
|
||||||
note: required by a bound in `const_eval_select`
|
note: required by a bound in `const_eval_select`
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||||
|
@ -5,6 +5,11 @@ LL | type Bar = NonConstAdd;
|
|||||||
| ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd`
|
| ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd`
|
||||||
|
|
|
|
||||||
= help: the trait `~const Add` is not implemented for `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
|
||||||
|
|
|
||||||
|
LL | type Bar = NonConstAdd;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
note: required by a bound in `Foo::Bar`
|
note: required by a bound in `Foo::Bar`
|
||||||
--> $DIR/assoc-type.rs:14:15
|
--> $DIR/assoc-type.rs:14:15
|
||||||
|
|
|
|
||||||
|
@ -7,6 +7,11 @@ LL | pub const EQ: bool = equals_self(&S);
|
|||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `~const PartialEq` is not implemented for `S`
|
= help: the trait `~const PartialEq` is not implemented for `S`
|
||||||
|
note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const`
|
||||||
|
--> $DIR/call-generic-method-nonconst.rs:19:34
|
||||||
|
|
|
||||||
|
LL | pub const EQ: bool = equals_self(&S);
|
||||||
|
| ^^
|
||||||
note: required by a bound in `equals_self`
|
note: required by a bound in `equals_self`
|
||||||
--> $DIR/call-generic-method-nonconst.rs:12:25
|
--> $DIR/call-generic-method-nonconst.rs:12:25
|
||||||
|
|
|
|
||||||
|
@ -28,6 +28,11 @@ LL | const _: () = check($exp);
|
|||||||
LL | ConstImplWithDropGlue(NonTrivialDrop),
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop`
|
||||||
|
|
|
|
||||||
|
note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||||
|
--> $DIR/const-drop-fail.rs:46:5
|
||||||
|
|
|
||||||
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: required because it appears within the type `ConstImplWithDropGlue`
|
note: required because it appears within the type `ConstImplWithDropGlue`
|
||||||
--> $DIR/const-drop-fail.rs:17:8
|
--> $DIR/const-drop-fail.rs:17:8
|
||||||
|
|
|
|
||||||
|
@ -28,6 +28,11 @@ LL | const _: () = check($exp);
|
|||||||
LL | ConstImplWithDropGlue(NonTrivialDrop),
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop`
|
||||||
|
|
|
|
||||||
|
note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||||
|
--> $DIR/const-drop-fail.rs:46:5
|
||||||
|
|
|
||||||
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: required because it appears within the type `ConstImplWithDropGlue`
|
note: required because it appears within the type `ConstImplWithDropGlue`
|
||||||
--> $DIR/const-drop-fail.rs:17:8
|
--> $DIR/const-drop-fail.rs:17:8
|
||||||
|
|
|
|
||||||
|
@ -4,6 +4,11 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied
|
|||||||
LL | foo::<()>();
|
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
|
||||||
|
|
|
||||||
|
LL | foo::<()>();
|
||||||
|
| ^^
|
||||||
note: required by a bound in `foo`
|
note: required by a bound in `foo`
|
||||||
--> $DIR/default-method-body-is-const-body-checking.rs:7:28
|
--> $DIR/default-method-body-is-const-body-checking.rs:7:28
|
||||||
|
|
|
|
||||||
|
@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied
|
|||||||
LL | T::b();
|
LL | T::b();
|
||||||
| ^^^^ the trait `~const Bar` is not implemented for `T`
|
| ^^^^ 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:14:5
|
||||||
|
|
|
||||||
|
LL | T::b();
|
||||||
|
| ^^^^
|
||||||
note: required by a bound in `Foo::b`
|
note: required by a bound in `Foo::b`
|
||||||
--> $DIR/trait-where-clause.rs:8:24
|
--> $DIR/trait-where-clause.rs:8:24
|
||||||
|
|
|
|
||||||
@ -20,6 +25,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied
|
|||||||
LL | T::c::<T>();
|
LL | T::c::<T>();
|
||||||
| ^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
|
| ^^^^^^^^^ 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:16:5
|
||||||
|
|
|
||||||
|
LL | T::c::<T>();
|
||||||
|
| ^^^^^^^^^
|
||||||
note: required by a bound in `Foo::c`
|
note: required by a bound in `Foo::c`
|
||||||
--> $DIR/trait-where-clause.rs:9:13
|
--> $DIR/trait-where-clause.rs:9:13
|
||||||
|
|
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user