Skip to content

Commit c639bce

Browse files
committed
Auto merge of #125864 - compiler-errors:opt-in-error-reporting, r=<try>
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`
2 parents a94483a + dee3d9a commit c639bce

File tree

50 files changed

+506
-322
lines changed

Some content is hidden

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

50 files changed

+506
-322
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_span::Span;
1313
use rustc_trait_selection::solve::deeply_normalize;
1414
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
1515
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
16+
use rustc_trait_selection::traits::ScrubbedTraitError;
1617

1718
use crate::{
1819
constraints::OutlivesConstraint,
@@ -286,7 +287,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
286287
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
287288
ty,
288289
)
289-
.map_err(|_| NoSolution)
290+
.map_err(|_: Vec<ScrubbedTraitError>| 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: 21 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, FulfillmentErrorLike};
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,23 @@ 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+
where
769+
E: FulfillmentErrorLike<'tcx>,
770+
{
771+
ocx: &'a ObligationCtxt<'a, 'tcx, E>,
769772
types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
770773
span: Span,
771774
param_env: ty::ParamEnv<'tcx>,
772775
body_id: LocalDefId,
773776
}
774777

775-
impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
778+
impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
779+
where
780+
E: FulfillmentErrorLike<'tcx>,
781+
{
776782
fn new(
777-
ocx: &'a ObligationCtxt<'a, 'tcx>,
783+
ocx: &'a ObligationCtxt<'a, 'tcx, E>,
778784
span: Span,
779785
param_env: ty::ParamEnv<'tcx>,
780786
body_id: LocalDefId,
@@ -783,7 +789,10 @@ impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
783789
}
784790
}
785791

786-
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
792+
impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
793+
where
794+
E: FulfillmentErrorLike<'tcx>,
795+
{
787796
fn interner(&self) -> TyCtxt<'tcx> {
788797
self.ocx.infcx.tcx
789798
}
@@ -1777,7 +1786,7 @@ fn compare_const_predicate_entailment<'tcx>(
17771786
);
17781787

17791788
let infcx = tcx.infer_ctxt().build();
1780-
let ocx = ObligationCtxt::new(&infcx);
1789+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
17811790

17821791
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
17831792
for (predicate, span) in impl_ct_own_bounds {
@@ -1910,7 +1919,7 @@ fn compare_type_predicate_entailment<'tcx>(
19101919
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
19111920
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
19121921
let infcx = tcx.infer_ctxt().build();
1913-
let ocx = ObligationCtxt::new(&infcx);
1922+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
19141923

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

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

19791988
let infcx = tcx.infer_ctxt().build();
1980-
let ocx = ObligationCtxt::new(&infcx);
1989+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
19811990

19821991
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
19831992
// 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)