Skip to content

Commit 74b2918

Browse files
committed
update trait selection
1 parent 8acef87 commit 74b2918

File tree

7 files changed

+125
-20
lines changed

7 files changed

+125
-20
lines changed

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,14 @@ impl<'tcx> Const<'tcx> {
257257
self.try_eval_usize(tcx, param_env)
258258
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
259259
}
260+
261+
#[inline]
262+
pub fn try_get_unevaluated(self) -> Option<Unevaluated<'tcx>> {
263+
match self.val {
264+
ConstKind::Unevaluated(uv) => Some(uv),
265+
_ => None,
266+
}
267+
}
260268
}
261269

262270
pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> {

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ use std::cmp;
2626
use std::iter;
2727
use std::ops::ControlFlow;
2828

29+
pub enum UseRevealSelection {
30+
Yes,
31+
No,
32+
}
33+
2934
/// Check if a given constant can be evaluated.
3035
pub fn is_const_evaluatable<'cx, 'tcx>(
3136
infcx: &InferCtxt<'cx, 'tcx>,
3237
uv: ty::Unevaluated<'tcx, ()>,
3338
param_env: ty::ParamEnv<'tcx>,
3439
span: Span,
40+
use_reveal_sel: UseRevealSelection,
3541
) -> Result<(), NotConstEvaluatable> {
3642
debug!("is_const_evaluatable({:?})", uv);
3743
if infcx.tcx.features().generic_const_exprs {
@@ -147,8 +153,12 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
147153
// and hopefully soon change this to an error.
148154
//
149155
// See #74595 for more details about this.
150-
let concrete =
151-
infcx.const_eval_resolve(param_env.with_reveal_selection(), uv.expand(), Some(span));
156+
let param_env_resolve = match use_reveal_sel {
157+
UseRevealSelection::Yes => param_env.with_reveal_selection(),
158+
UseRevealSelection::No => param_env,
159+
};
160+
161+
let concrete = infcx.const_eval_resolve(param_env_resolve, uv.expand(), Some(span));
152162

153163
if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) {
154164
match infcx.tcx.def_kind(uv.def.did) {
@@ -174,6 +184,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
174184
Err(NotConstEvaluatable::Error(ErrorReported))
175185
}
176186
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
187+
Err(ErrorHandled::Silent) => Err(NotConstEvaluatable::Silent),
177188
Ok(_) => Ok(()),
178189
}
179190
}

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ pub mod on_unimplemented;
22
pub mod suggestions;
33

44
use super::{
5-
EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
6-
Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective,
7-
OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation,
8-
SelectionContext, SelectionError, TraitNotObjectSafe,
5+
const_evaluatable, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
6+
MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
7+
OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
8+
PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
99
};
1010

1111
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
@@ -86,6 +86,14 @@ pub trait InferCtxtExt<'tcx> {
8686
found_args: Vec<ArgKind>,
8787
is_closure: bool,
8888
) -> DiagnosticBuilder<'tcx>;
89+
90+
fn report_const_eval_failure(
91+
&self,
92+
uv: ty::Unevaluated<'tcx, ()>,
93+
obligation: PredicateObligation<'tcx>,
94+
root_obligation: &PredicateObligation<'tcx>,
95+
fallback_has_occurred: bool,
96+
);
8997
}
9098

9199
impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
@@ -238,6 +246,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
238246
error: &SelectionError<'tcx>,
239247
fallback_has_occurred: bool,
240248
) {
249+
debug!("report_selection_error(error: {:?})", error);
241250
let tcx = self.tcx;
242251
let mut span = obligation.cause.span;
243252

@@ -799,7 +808,42 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
799808
bug!(
800809
"MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"
801810
)
802-
ConstEvalFailure(ErrorHandled::Silent) => {
811+
}
812+
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Silent) => {
813+
let pred = obligation.predicate.clone();
814+
815+
// Try to prove the obligation again without Reveal::Selection for
816+
// better diagnostics
817+
match pred.kind().skip_binder() {
818+
ty::PredicateKind::ConstEvaluatable(uv) => {
819+
self.report_const_eval_failure(
820+
uv,
821+
obligation.clone(),
822+
root_obligation,
823+
fallback_has_occurred,
824+
);
825+
}
826+
ty::PredicateKind::ConstEquate(c1, c2) => {
827+
if let Some(uv1) = c1.try_get_unevaluated() {
828+
self.report_const_eval_failure(
829+
uv1.shrink(),
830+
obligation.clone(),
831+
root_obligation,
832+
fallback_has_occurred,
833+
);
834+
}
835+
836+
if let Some(uv2) = c2.try_get_unevaluated() {
837+
self.report_const_eval_failure(
838+
uv2.shrink(),
839+
obligation.clone(),
840+
root_obligation,
841+
fallback_has_occurred,
842+
);
843+
}
844+
}
845+
_ => {}
846+
}
803847
tcx.sess.struct_span_err(span, "failed to evaluate the given constant")
804848
}
805849
SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {
@@ -1063,6 +1107,45 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
10631107

10641108
err
10651109
}
1110+
1111+
#[instrument(skip(self, obligation, root_obligation, fallback_has_occurred), level = "debug")]
1112+
fn report_const_eval_failure(
1113+
&self,
1114+
uv: ty::Unevaluated<'tcx, ()>,
1115+
obligation: PredicateObligation<'tcx>,
1116+
root_obligation: &PredicateObligation<'tcx>,
1117+
fallback_has_occurred: bool,
1118+
) {
1119+
let res = const_evaluatable::is_const_evaluatable(
1120+
self,
1121+
uv,
1122+
obligation.param_env.with_user_facing(),
1123+
obligation.cause.span,
1124+
const_evaluatable::UseRevealSelection::No,
1125+
);
1126+
debug!(?res);
1127+
1128+
match res {
1129+
Err(NotConstEvaluatable::Silent) => {
1130+
bug!("called with Reveal::UserFacing, but Silent error returned")
1131+
}
1132+
Err(e @ NotConstEvaluatable::MentionsParam | e @ NotConstEvaluatable::Error(_)) => {
1133+
let err = SelectionError::NotConstEvaluatable(e);
1134+
1135+
self.report_selection_error(
1136+
obligation,
1137+
root_obligation,
1138+
&err,
1139+
fallback_has_occurred,
1140+
);
1141+
}
1142+
Ok(()) => bug!(
1143+
"ConstEvaluatable predicate of {:?} failed with Reveal::Selection but succeeded with Reveal::UserFacing?",
1144+
uv
1145+
),
1146+
_ => {}
1147+
}
1148+
}
10661149
}
10671150

10681151
trait InferCtxtPrivExt<'hir, 'tcx> {

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -528,12 +528,15 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
528528
}
529529

530530
ty::PredicateKind::ConstEvaluatable(uv) => {
531-
match const_evaluatable::is_const_evaluatable(
531+
let res = const_evaluatable::is_const_evaluatable(
532532
self.selcx.infcx(),
533533
uv,
534-
obligation.param_env,
534+
obligation.param_env.with_reveal_selection(),
535535
obligation.cause.span,
536-
) {
536+
const_evaluatable::UseRevealSelection::Yes,
537+
);
538+
539+
match res {
537540
Ok(()) => ProcessResult::Changed(vec![]),
538541
Err(NotConstEvaluatable::MentionsInfer) => {
539542
pending_obligation.stalled_on.clear();
@@ -546,7 +549,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
546549
}
547550
Err(
548551
e @ NotConstEvaluatable::MentionsParam
549-
| e @ NotConstEvaluatable::Error(_),
552+
| e @ NotConstEvaluatable::Error(_)
553+
| e @ NotConstEvaluatable::Silent,
550554
) => ProcessResult::Error(CodeSelectionError(
551555
SelectionError::NotConstEvaluatable(e),
552556
)),
@@ -626,9 +630,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
626630
)
627631
}
628632
(Err(ErrorHandled::Silent), _) | (_, Err(ErrorHandled::Silent)) => {
629-
ProcessResult::Error(CodeSelectionError(ConstEvalFailure(
630-
ErrorHandled::Silent,
631-
)))
633+
ProcessResult::Error(CodeSelectionError(
634+
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Silent),
635+
))
632636
}
633637
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
634638
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ fn do_normalize_predicates<'tcx>(
273273

274274
// FIXME: this is gonna need to be removed ...
275275
/// Normalizes the parameter environment, reporting errors if they occur.
276+
#[instrument(skip(tcx), level = "debug")]
276277
pub fn normalize_param_env_or_error<'tcx>(
277278
tcx: TyCtxt<'tcx>,
278279
region_context: DefId,

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rustc_hir::def_id::DefId;
2626
use rustc_hir::lang_items::LangItem;
2727
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
2828
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
29+
2930
use rustc_middle::ty::subst::Subst;
3031
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
3132
use rustc_span::symbol::sym;
@@ -296,7 +297,7 @@ where
296297

297298
pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool {
298299
match reveal {
299-
Reveal::UserFacing => value
300+
Reveal::Selection | Reveal::UserFacing => value
300301
.has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION),
301302
Reveal::All => value.has_type_flags(
302303
ty::TypeFlags::HAS_TY_PROJECTION

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
625625
uv,
626626
obligation.param_env,
627627
obligation.cause.span,
628+
const_evaluatable::UseRevealSelection::Yes,
628629
) {
629630
Ok(()) => Ok(EvaluatedToOk),
630631
Err(NotConstEvaluatable::MentionsInfer) => Ok(EvaluatedToAmbig),
@@ -2659,11 +2660,7 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
26592660
}
26602661

26612662
fn depth(&self) -> usize {
2662-
if let Some(head) = self.head {
2663-
head.depth
2664-
} else {
2665-
0
2666-
}
2663+
if let Some(head) = self.head { head.depth } else { 0 }
26672664
}
26682665
}
26692666

0 commit comments

Comments
 (0)