diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-01-30 00:04:11 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-30 00:04:11 +0100 |
| commit | 103c3a38a669a481cf2ae0c1e89a8fc0642de50c (patch) | |
| tree | 5b740cc1d21f689247749df5e0f9683949769c70 /compiler | |
| parent | 6e2593d3430ea6675b23387288043524d693fe8f (diff) | |
| parent | c6de4d55aab6d06f040202cbe39dc5c32809aac2 (diff) | |
| download | rust-103c3a38a669a481cf2ae0c1e89a8fc0642de50c.tar.gz rust-103c3a38a669a481cf2ae0c1e89a8fc0642de50c.zip | |
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````
Diffstat (limited to 'compiler')
7 files changed, 44 insertions, 12 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 3ec9f3ca3b8..9dc34260de7 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -7,7 +7,6 @@ use crate::interpret::{ }; use rustc_errors::ErrorReported; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; @@ -216,7 +215,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'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 if key.param_env.reveal() == Reveal::All { let mut key = key; @@ -251,7 +250,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'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 // 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 diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index dafff640b36..4c7f3482776 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -86,7 +86,6 @@ declare_lint_pass!( impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - use rustc_middle::ty; use rustc_middle::ty::PredicateKind::*; 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 { continue }; - if trait_predicate.constness == ty::BoundConstness::ConstIfConst { + if trait_predicate.is_const_if_const() { // `~const Drop` definitely have meanings so avoid linting here. continue; } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6174c922e2d..e7a8e71ce71 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -784,6 +784,11 @@ impl<'tcx> TraitPredicate<'tcx> { pub fn self_ty(self) -> Ty<'tcx> { self.trait_ref.self_ty() } + + #[inline] + pub fn is_const_if_const(self) -> bool { + self.constness == BoundConstness::ConstIfConst + } } impl<'tcx> PolyTraitPredicate<'tcx> { @@ -803,6 +808,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> { 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)] @@ -1388,6 +1398,11 @@ impl<'tcx> ParamEnv<'tcx> { 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 /// where the values of all `impl Trait` and other hidden types /// are revealed. This is suitable for monomorphized, post-typeck @@ -1503,6 +1518,7 @@ impl<'tcx> PolyTraitRef<'tcx> { polarity: ty::ImplPolarity::Positive, }) } + #[inline] pub fn without_const(self) -> PolyTraitPredicate<'tcx> { self.with_constness(BoundConstness::NotConst) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 37cf41a0ec2..687bd16ba30 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -439,6 +439,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } else { 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 { err.span_label(span, &msg); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 0099fba9200..db86041f618 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -305,7 +305,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.unsize_trait() == Some(def_id) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } 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); } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2e20ea34e10..639884844b2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -72,9 +72,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // CheckPredicate(&A: Super) // CheckPredicate(A: ~const Super) // <- still const env, failure // ``` - if obligation.param_env.constness() == Constness::Const - && obligation.predicate.skip_binder().constness == ty::BoundConstness::NotConst - { + if obligation.param_env.is_const() && !obligation.predicate.is_const_if_const() { new_obligation = TraitObligation { cause: obligation.cause.clone(), param_env: obligation.param_env.without_const(), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ae536905483..47427395b93 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1173,9 +1173,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {} // const param - ParamCandidate(trait_pred) - if trait_pred.skip_binder().constness - == ty::BoundConstness::ConstIfConst => {} + ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {} // auto trait impl AutoImplCandidate(..) => {} // generator, this will raise error in other places |
