Skip to content

Commit 39165e3

Browse files
committed
non-fatal overflow
1 parent 36db030 commit 39165e3

File tree

43 files changed

+995
-995
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+995
-995
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,19 +1745,23 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
17451745

17461746
match in_elem.kind() {
17471747
ty::RawPtr(p) => {
1748-
let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
1749-
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
1750-
});
1748+
let (metadata, check_sized) =
1749+
p.ty.ptr_metadata_ty(bx.tcx, |ty| {
1750+
Ok(bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty))
1751+
})
1752+
.unwrap();
17511753
assert!(!check_sized); // we are in codegen, so we shouldn't see these types
17521754
require!(metadata.is_unit(), "cannot cast fat pointer `{}`", in_elem)
17531755
}
17541756
_ => return_error!("expected pointer, got `{}`", in_elem),
17551757
}
17561758
match out_elem.kind() {
17571759
ty::RawPtr(p) => {
1758-
let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
1759-
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
1760-
});
1760+
let (metadata, check_sized) =
1761+
p.ty.ptr_metadata_ty(bx.tcx, |ty| {
1762+
Ok(bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty))
1763+
})
1764+
.unwrap();
17611765
assert!(!check_sized); // we are in codegen, so we shouldn't see these types
17621766
require!(metadata.is_unit(), "cannot cast to fat pointer `{}`", out_elem)
17631767
}

compiler/rustc_const_eval/src/const_eval/valtrees.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,17 @@ fn get_info_on_unsized_field<'tcx>(
177177
tcx: TyCtxt<'tcx>,
178178
) -> (Ty<'tcx>, usize) {
179179
let mut last_valtree = valtree;
180-
let tail = tcx.struct_tail_with_normalize(
181-
ty,
182-
|ty| ty,
183-
|| {
184-
let branches = last_valtree.unwrap_branch();
185-
last_valtree = branches[branches.len() - 1];
186-
debug!(?branches, ?last_valtree);
187-
},
188-
);
180+
let tail = tcx
181+
.struct_tail_with_normalize(
182+
ty,
183+
|ty| Ok(ty),
184+
|| {
185+
let branches = last_valtree.unwrap_branch();
186+
last_valtree = branches[branches.len() - 1];
187+
debug!(?branches, ?last_valtree);
188+
},
189+
)
190+
.unwrap();
189191
let unsized_inner_ty = match tail.kind() {
190192
ty::Slice(t) => *t,
191193
ty::Str => tail,

compiler/rustc_const_eval/src/transform/check_consts/check.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,14 +770,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
770770
}
771771

772772
match implsrc {
773-
Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
773+
Ok(Ok(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
774774
debug!(
775775
"const_trait_impl: provided {:?} via where-clause in {:?}",
776776
trait_ref, param_env
777777
);
778778
return;
779779
}
780-
Ok(Some(ImplSource::UserDefined(data))) => {
780+
Ok(Ok(ImplSource::UserDefined(data))) => {
781781
let callee_name = tcx.item_name(callee);
782782
if let Some(&did) = tcx
783783
.associated_item_def_ids(data.impl_def_id)

compiler/rustc_const_eval/src/transform/check_consts/ops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
160160
let mut selcx = SelectionContext::new(&infcx);
161161
let implsrc = selcx.select(&obligation);
162162

163-
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
163+
if let Ok(Ok(ImplSource::UserDefined(data))) = implsrc {
164164
let span = tcx.def_span(data.impl_def_id);
165165
err.span_note(span, "impl defined here, but it is not `const`");
166166
}

compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl Qualif for NeedsNonConstDrop {
170170

171171
let infcx = cx.tcx.infer_ctxt().build();
172172
let mut selcx = SelectionContext::new(&infcx);
173-
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
173+
let Ok(Ok(impl_src)) = selcx.select(&obligation) else {
174174
// If we couldn't select a const destruct candidate, then it's bad
175175
return true;
176176
};

compiler/rustc_data_structures/src/obligation_forest/mod.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ pub trait ObligationProcessor {
107107
obligation: &mut Self::Obligation,
108108
) -> ProcessResult<Self::Obligation, Self::Error>;
109109

110+
fn update_obligation_depth(
111+
&mut self,
112+
obligation: &Self::Obligation,
113+
child: &mut Self::Obligation,
114+
);
115+
110116
/// As we do the cycle check, we invoke this callback when we
111117
/// encounter an actual cycle. `cycle` is an iterator that starts
112118
/// at the start of the cycle in the stack and walks **toward the
@@ -375,13 +381,16 @@ impl<O: ForestObligation> ObligationForest<O> {
375381
}
376382

377383
/// Converts all remaining obligations to the given error.
378-
pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
384+
pub fn to_errors<E>(&mut self, mut mk_error: impl FnMut(&O) -> E) -> Vec<Error<O, E>> {
379385
let errors = self
380386
.nodes
381387
.iter()
382388
.enumerate()
383389
.filter(|(_index, node)| node.state.get() == NodeState::Pending)
384-
.map(|(index, _node)| Error { error: error.clone(), backtrace: self.error_at(index) })
390+
.map(|(index, node)| Error {
391+
error: mk_error(&node.obligation),
392+
backtrace: self.error_at(index),
393+
})
385394
.collect();
386395

387396
self.compress(|_| assert!(false));
@@ -447,11 +456,15 @@ impl<O: ForestObligation> ObligationForest<O> {
447456
ProcessResult::Unchanged => {
448457
// No change in state.
449458
}
450-
ProcessResult::Changed(children) => {
459+
ProcessResult::Changed(mut children) => {
451460
// We are not (yet) stalled.
452461
has_changed = true;
453462
node.state.set(NodeState::Success);
454463

464+
for child in &mut children {
465+
processor.update_obligation_depth(&node.obligation, child);
466+
}
467+
455468
for child in children {
456469
let st = self.register_obligation_at(child, Some(index));
457470
if let Err(()) = st {

compiler/rustc_data_structures/src/obligation_forest/tests.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ where
7070
true
7171
}
7272

73+
fn update_obligation_depth(&mut self, _: &Self::Obligation, _: &mut Self::Obligation) {}
74+
7375
fn process_obligation(
7476
&mut self,
7577
obligation: &mut Self::Obligation,
@@ -256,7 +258,7 @@ fn to_errors_no_throw() {
256258
));
257259
assert_eq!(ok.len(), 0);
258260
assert_eq!(err.len(), 0);
259-
let errors = forest.to_errors(());
261+
let errors = forest.to_errors(|_| ());
260262
assert_eq!(errors[0].backtrace, vec!["A.1", "A"]);
261263
assert_eq!(errors[1].backtrace, vec!["A.2", "A"]);
262264
assert_eq!(errors[2].backtrace, vec!["A.3", "A"]);
@@ -308,7 +310,7 @@ fn diamond() {
308310
assert_eq!(ok, vec!["A", "A.1", "A.2", "D"]);
309311
assert_eq!(err.len(), 0);
310312

311-
let errors = forest.to_errors(());
313+
let errors = forest.to_errors(|_| ());
312314
assert_eq!(errors.len(), 0);
313315

314316
forest.register_obligation("A'");
@@ -353,7 +355,7 @@ fn diamond() {
353355
vec![super::Error { error: "operation failed", backtrace: vec!["D'", "A'.1", "A'"] }]
354356
);
355357

356-
let errors = forest.to_errors(());
358+
let errors = forest.to_errors(|_| ());
357359
assert_eq!(errors.len(), 0);
358360
}
359361

@@ -446,7 +448,7 @@ fn orphan() {
446448
assert_eq!(ok.len(), 0);
447449
assert_eq!(err, vec![super::Error { error: "D is dead", backtrace: vec!["D"] }]);
448450

449-
let errors = forest.to_errors(());
451+
let errors = forest.to_errors(|_| ());
450452
assert_eq!(errors.len(), 0);
451453
}
452454

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
7474
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
7575
use rustc_infer::infer::TyCtxtInferExt;
7676
use rustc_infer::traits::specialization_graph::Node;
77+
use rustc_infer::traits::Overflow;
7778
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
7879
use rustc_middle::ty::trait_def::TraitSpecializationKind;
7980
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
@@ -377,7 +378,9 @@ fn check_predicates<'tcx>(
377378
0,
378379
arg,
379380
span,
381+
true,
380382
)
383+
.unwrap_or_else(|Overflow| bug!("impossible non-fatal overflow"))
381384
.unwrap();
382385

383386
assert!(!obligations.needs_infer());

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
671671
};
672672
match selcx.select(&obligation.with(trait_pred)) {
673673
// Uncertain or unimplemented.
674-
Ok(None) => {
674+
Ok(Err(true)) => self.err_ctxt().report_overflow_error(&obligation, true),
675+
Ok(Err(false)) => {
675676
if trait_pred.def_id() == unsize_did {
676677
let trait_pred = self.resolve_vars_if_possible(trait_pred);
677678
let self_ty = trait_pred.skip_binder().self_ty();
@@ -712,7 +713,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
712713
// be silent, as it causes a type mismatch later.
713714
}
714715

715-
Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()),
716+
Ok(Ok(impl_source)) => queue.extend(impl_source.nested_obligations()),
716717
}
717718
}
718719

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2159,7 +2159,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21592159
}),
21602160
);
21612161
match SelectionContext::new(&self).select(&obligation) {
2162-
Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
2162+
Ok(Ok(traits::ImplSource::UserDefined(impl_source))) => {
21632163
Some(impl_source.impl_def_id)
21642164
}
21652165
_ => None,

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14471447
.define_opaque_types(false)
14481448
.sup(candidate.xform_self_ty, self_ty);
14491449
match self.select_trait_candidate(trait_ref) {
1450-
Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
1450+
Ok(Ok(traits::ImplSource::UserDefined(ref impl_data))) => {
14511451
// If only a single impl matches, make the error message point
14521452
// to that impl.
14531453
CandidateSource::Impl(impl_data.impl_def_id)
@@ -1566,7 +1566,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
15661566
if self.probe(|_| {
15671567
match self.select_trait_candidate(trait_ref) {
15681568
Err(_) => return true,
1569-
Ok(Some(impl_source))
1569+
Ok(Ok(impl_source))
15701570
if !impl_source.borrow_nested_obligations().is_empty() =>
15711571
{
15721572
for obligation in impl_source.borrow_nested_obligations() {

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@ use super::FulfillmentError;
88
use super::{ObligationCause, PredicateObligation};
99

1010
pub trait TraitEngine<'tcx>: 'tcx {
11-
fn normalize_projection_type(
12-
&mut self,
13-
infcx: &InferCtxt<'tcx>,
14-
param_env: ty::ParamEnv<'tcx>,
15-
projection_ty: ty::ProjectionTy<'tcx>,
16-
cause: ObligationCause<'tcx>,
17-
) -> Ty<'tcx>;
18-
1911
/// Requires that `ty` must implement the trait with `def_id` in
2012
/// the given environment. This trait must not have any type
2113
/// parameters (except for `Self`).

compiler/rustc_infer/src/traits/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub struct FulfillmentError<'tcx> {
111111
pub root_obligation: PredicateObligation<'tcx>,
112112
}
113113

114-
#[derive(Clone)]
114+
#[derive(Debug, Clone)]
115115
pub enum FulfillmentErrorCode<'tcx> {
116116
/// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented.
117117
CodeCycle(Vec<Obligation<'tcx, ty::Predicate<'tcx>>>),
@@ -120,6 +120,7 @@ pub enum FulfillmentErrorCode<'tcx> {
120120
CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
121121
CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
122122
CodeAmbiguity,
123+
CodeOverflow,
123124
}
124125

125126
impl<'tcx, O> Obligation<'tcx, O> {

compiler/rustc_infer/src/traits/project.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl<'tcx> ProjectionCacheKey<'tcx> {
9090
pub enum ProjectionCacheEntry<'tcx> {
9191
InProgress,
9292
Ambiguous,
93+
Overflow,
9394
Recur,
9495
Error,
9596
NormalizedTy {
@@ -184,7 +185,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
184185
key, value
185186
);
186187
let mut map = self.map();
187-
if let Some(ProjectionCacheEntry::Recur) = map.get(&key) {
188+
if let Some(ProjectionCacheEntry::Recur | ProjectionCacheEntry::Overflow) = map.get(&key) {
188189
debug!("Not overwriting Recur");
189190
return;
190191
}
@@ -223,6 +224,11 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
223224
})
224225
}
225226

227+
pub fn overflow(&mut self, key: ProjectionCacheKey<'tcx>) {
228+
let fresh = self.map().insert(key, ProjectionCacheEntry::Overflow);
229+
assert!(!fresh, "never started projecting `{:?}", key);
230+
}
231+
226232
/// Indicates that trying to normalize `key` resulted in
227233
/// ambiguity. No point in trying it again then until we gain more
228234
/// type information (in which case, the "fully resolved" key will

compiler/rustc_infer/src/traits/structural_impls.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,6 @@ impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
3535
}
3636
}
3737

38-
impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
39-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40-
match *self {
41-
super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
42-
super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
43-
super::CodeSubtypeError(ref a, ref b) => {
44-
write!(f, "CodeSubtypeError({:?}, {:?})", a, b)
45-
}
46-
super::CodeConstEquateError(ref a, ref b) => {
47-
write!(f, "CodeConstEquateError({:?}, {:?})", a, b)
48-
}
49-
super::CodeAmbiguity => write!(f, "Ambiguity"),
50-
super::CodeCycle(ref cycle) => write!(f, "Cycle({:?})", cycle),
51-
}
52-
}
53-
}
54-
5538
impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
5639
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5740
write!(f, "MismatchedProjectionTypes({:?})", self.err)

compiler/rustc_middle/src/infer/canonical.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -237,30 +237,18 @@ pub enum Certainty {
237237
/// canonical form will be different, making this a distinct
238238
/// query.
239239
Ambiguous,
240-
}
241-
242-
impl Certainty {
243-
pub fn is_proven(&self) -> bool {
244-
match self {
245-
Certainty::Proven => true,
246-
Certainty::Ambiguous => false,
247-
}
248-
}
240+
Overflow,
249241
}
250242

251243
impl<'tcx, R> QueryResponse<'tcx, R> {
252-
pub fn is_proven(&self) -> bool {
253-
self.certainty.is_proven()
244+
pub fn certainty(&self) -> Certainty {
245+
self.certainty
254246
}
255247
}
256248

257249
impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
258-
pub fn is_proven(&self) -> bool {
259-
self.value.is_proven()
260-
}
261-
262-
pub fn is_ambiguous(&self) -> bool {
263-
!self.is_proven()
250+
pub fn certainty(&self) -> Certainty {
251+
self.value.certainty()
264252
}
265253
}
266254

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,7 @@ rustc_queries! {
19071907
/// `infcx.predicate_must_hold()` instead.
19081908
query evaluate_obligation(
19091909
goal: CanonicalPredicateGoal<'tcx>
1910-
) -> Result<traits::EvaluationResult, traits::OverflowError> {
1910+
) -> traits::EvaluationResult {
19111911
desc { "evaluating trait selection obligation `{}`", goal.value.value }
19121912
}
19131913

0 commit comments

Comments
 (0)