Skip to content

Commit eb5e244

Browse files
committed
Auto merge of rust-lang#125864 - compiler-errors:opt-in-error-reporting, r=lcnr
Opt-in to `FulfillmentError` generation to avoid doing extra work in the new solver In the new solver, we do additional trait solving in order to generate fulfillment errors, because all we have is the root obligation. This is problematic because there are many cases where we don't need the full error information, and instead are just calling `ObligationCtxt::select_all_or_error` to probe whether a predicate holds or not. This is also problematic because we use `ObligationCtxt`s within the error reporting machinery itself, and so we can definitely cause stack overflows: https://github.com/rust-lang/rust/blob/a94483a5f2bae907bc898fc7a8d9cc87db47b693/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs#L75-L84 So instead, make `TraitEngine` and `ObligationCtxt` generic over `E: FulfillmentErrorLike<'tcx>`, and introduce a new `ScrubbedTraitError` which only stores whether the failure was due to a "true error" or an ambiguity. Then, introduce `ObligationCtxt::new_with_diagnostics` for the callsites that actually inspect their `FulfillmentError`s. r? `@lcnr` Number-wise, there are: ``` 39 ObligationCtxt::new 32 ObligationCtxt::new_with_diagnostics 1 ObligationCtxt::new_generic ``` calls to each `ObligationCtxt` constructor, which suggests that there are indeed a lot of callsites that don't care about diagnostics.
2 parents 8768db9 + a41c44f commit eb5e244

File tree

49 files changed

+478
-328
lines changed

Some content is hidden

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

49 files changed

+478
-328
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1347,7 +1347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13471347
return;
13481348
};
13491349
// Try to find predicates on *generic params* that would allow copying `ty`
1350-
let ocx = ObligationCtxt::new(self.infcx);
1350+
let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
13511351
let cause = ObligationCause::misc(span, self.mir_def_id());
13521352

13531353
ocx.register_bound(cause, self.param_env, ty, def_id);

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::def::{CtorKind, Namespace};
1111
use rustc_hir::CoroutineKind;
1212
use rustc_index::IndexSlice;
1313
use rustc_infer::infer::BoundRegionConversionTime;
14-
use rustc_infer::traits::{FulfillmentErrorCode, SelectionError};
14+
use rustc_infer::traits::SelectionError;
1515
use rustc_middle::bug;
1616
use rustc_middle::mir::tcx::PlaceTy;
1717
use rustc_middle::mir::{
@@ -29,7 +29,9 @@ use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
2929
use rustc_target::abi::{FieldIdx, VariantIdx};
3030
use rustc_trait_selection::infer::InferCtxtExt;
3131
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
32-
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
32+
use rustc_trait_selection::traits::{
33+
type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,
34+
};
3335

3436
use crate::fluent_generated as fluent;
3537

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use hir::{ExprKind, Param};
66
use rustc_errors::{Applicability, Diag};
77
use rustc_hir::intravisit::Visitor;
88
use rustc_hir::{self as hir, BindingMode, ByRef, Node};
9-
use rustc_infer::traits;
109
use rustc_middle::bug;
1110
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
1211
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, Upcast};
@@ -18,6 +17,7 @@ use rustc_span::symbol::{kw, Symbol};
1817
use rustc_span::{sym, BytePos, DesugaringKind, Span};
1918
use rustc_target::abi::FieldIdx;
2019
use rustc_trait_selection::infer::InferCtxtExt;
20+
use rustc_trait_selection::traits;
2121
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
2222

2323
use crate::diagnostics::BorrowedContentSource;

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ fn check_opaque_type_well_formed<'tcx>(
340340
.with_next_trait_solver(next_trait_solver)
341341
.with_opaque_type_inference(parent_def_id)
342342
.build();
343-
let ocx = ObligationCtxt::new(&infcx);
343+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
344344
let identity_args = GenericArgs::identity_for_item(tcx, def_id);
345345

346346
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use rustc_middle::traits::query::NoSolution;
1010
use rustc_middle::traits::ObligationCause;
1111
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
1212
use rustc_span::Span;
13-
use rustc_trait_selection::solve::deeply_normalize;
1413
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
1514
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
15+
use rustc_trait_selection::traits::ScrubbedTraitError;
1616

1717
use crate::{
1818
constraints::OutlivesConstraint,
@@ -282,11 +282,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
282282
) -> Ty<'tcx> {
283283
let result = CustomTypeOp::new(
284284
|ocx| {
285-
deeply_normalize(
286-
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
285+
ocx.deeply_normalize(
286+
&ObligationCause::dummy_with_span(self.span),
287+
self.param_env,
287288
ty,
288289
)
289-
.map_err(|_| NoSolution)
290+
.map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
290291
},
291292
"normalize type outlives obligation",
292293
)

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
735735
// which path expressions are getting called on and which path expressions are only used
736736
// as function pointers. This is required for correctness.
737737
let infcx = tcx.infer_ctxt().build();
738-
let ocx = ObligationCtxt::new(&infcx);
738+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
739739

740740
let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
741741
let cause = ObligationCause::new(

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ fn check_opaque_meets_bounds<'tcx>(
342342
let param_env = tcx.param_env(defining_use_anchor);
343343

344344
let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
345-
let ocx = ObligationCtxt::new(&infcx);
345+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
346346

347347
let args = match *origin {
348348
hir::OpaqueTyOrigin::FnReturn(parent)
@@ -1727,7 +1727,7 @@ pub(super) fn check_coroutine_obligations(
17271727
.with_opaque_type_inference(def_id)
17281728
.build();
17291729

1730-
let ocx = ObligationCtxt::new(&infcx);
1730+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
17311731
for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
17321732
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
17331733
}

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_hir::intravisit;
1010
use rustc_hir::{GenericParamKind, ImplItemKind};
1111
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1212
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
13-
use rustc_infer::traits::{util, FulfillmentError};
13+
use rustc_infer::traits::util;
1414
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1515
use rustc_middle::ty::fold::BottomUpFolder;
1616
use rustc_middle::ty::util::ExplicitSelf;
@@ -25,7 +25,7 @@ use rustc_trait_selection::regions::InferCtxtRegionExt;
2525
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
2626
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2727
use rustc_trait_selection::traits::{
28-
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
28+
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
2929
};
3030
use std::borrow::Cow;
3131
use std::iter;
@@ -225,7 +225,7 @@ fn compare_method_predicate_entailment<'tcx>(
225225
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
226226

227227
let infcx = &tcx.infer_ctxt().build();
228-
let ocx = ObligationCtxt::new(infcx);
228+
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
229229

230230
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
231231

@@ -493,7 +493,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
493493
);
494494

495495
let infcx = &tcx.infer_ctxt().build();
496-
let ocx = ObligationCtxt::new(infcx);
496+
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
497497

498498
// Normalize the impl signature with fresh variables for lifetime inference.
499499
let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
@@ -764,17 +764,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
764764
Ok(&*tcx.arena.alloc(remapped_types))
765765
}
766766

767-
struct ImplTraitInTraitCollector<'a, 'tcx> {
768-
ocx: &'a ObligationCtxt<'a, 'tcx>,
767+
struct ImplTraitInTraitCollector<'a, 'tcx, E> {
768+
ocx: &'a ObligationCtxt<'a, 'tcx, E>,
769769
types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
770770
span: Span,
771771
param_env: ty::ParamEnv<'tcx>,
772772
body_id: LocalDefId,
773773
}
774774

775-
impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
775+
impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
776+
where
777+
E: 'tcx,
778+
{
776779
fn new(
777-
ocx: &'a ObligationCtxt<'a, 'tcx>,
780+
ocx: &'a ObligationCtxt<'a, 'tcx, E>,
778781
span: Span,
779782
param_env: ty::ParamEnv<'tcx>,
780783
body_id: LocalDefId,
@@ -783,7 +786,10 @@ impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
783786
}
784787
}
785788

786-
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
789+
impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
790+
where
791+
E: 'tcx,
792+
{
787793
fn interner(&self) -> TyCtxt<'tcx> {
788794
self.ocx.infcx.tcx
789795
}
@@ -1777,7 +1783,7 @@ fn compare_const_predicate_entailment<'tcx>(
17771783
);
17781784

17791785
let infcx = tcx.infer_ctxt().build();
1780-
let ocx = ObligationCtxt::new(&infcx);
1786+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
17811787

17821788
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
17831789
for (predicate, span) in impl_ct_own_bounds {
@@ -1910,7 +1916,7 @@ fn compare_type_predicate_entailment<'tcx>(
19101916
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
19111917
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
19121918
let infcx = tcx.infer_ctxt().build();
1913-
let ocx = ObligationCtxt::new(&infcx);
1919+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
19141920

19151921
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
19161922

@@ -1977,7 +1983,7 @@ pub(super) fn check_type_bounds<'tcx>(
19771983
let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
19781984

19791985
let infcx = tcx.infer_ctxt().build();
1980-
let ocx = ObligationCtxt::new(&infcx);
1986+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
19811987

19821988
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
19831989
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized

compiler/rustc_hir_analysis/src/check/dropck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
123123
adt_to_impl_args: GenericArgsRef<'tcx>,
124124
) -> Result<(), ErrorGuaranteed> {
125125
let infcx = tcx.infer_ctxt().build();
126-
let ocx = ObligationCtxt::new(&infcx);
126+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
127127

128128
// Take the param-env of the adt and instantiate the args that show up in
129129
// the implementation's self type. This gives us the assumptions that the

compiler/rustc_hir_analysis/src/check/entry.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
133133
main_diagnostics_def_id,
134134
ObligationCauseCode::MainFunctionType,
135135
);
136-
let ocx = traits::ObligationCtxt::new(&infcx);
136+
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
137137
let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
138138
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
139139
let errors = ocx.select_all_or_error();

0 commit comments

Comments
 (0)