Skip to content

Commit 4fcd53a

Browse files
Instead of representing trait errors as Vec<Error>, use a special type
This has multiple advantages: - Performance. The new type is 1/3 the size of `Vec` (being equivalent in layout to `Option<ThinVec>`) and can be kept in a register. - Type safety. We mark the type `#[must_use]`, and thinks requiring errors take `ThinVec`, which requires unwrapping the type and verifying there is indeed an error. We still provide conversions to slices, `ThinVec`, and iteration, because some code needs this and I saw no benefit in changing it, but we deliberately do not provide `Deref<Target = [E]>` or things like that.
1 parent 5051639 commit 4fcd53a

69 files changed

Lines changed: 350 additions & 219 deletions

File tree

Some content is hidden

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

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::{
1616
CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField, find_attr,
1717
};
1818
use rustc_index::bit_set::DenseBitSet;
19+
use rustc_infer::traits::TraitErrors;
1920
use rustc_middle::bug;
2021
use rustc_middle::hir::nested_filter::OnlyBodies;
2122
use rustc_middle::mir::{
@@ -1462,7 +1463,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
14621463
let cause = ObligationCause::misc(expr.span, self.mir_def_id());
14631464
ocx.register_bound(cause, self.infcx.param_env, ty, clone_trait);
14641465
let errors = ocx.evaluate_obligations_error_on_ambiguity();
1465-
if !errors.is_empty()
1466+
if let TraitErrors::HasErrors(errors) = errors
14661467
&& errors.iter().all(|error| {
14671468
match error.obligation.predicate.as_clause().and_then(|c| c.as_trait_clause()) {
14681469
Some(clause) => match clause.self_ty().skip_binder().kind() {

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,9 +1534,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
15341534
) && !has_sugg
15351535
{
15361536
let skip_for_simple_clone =
1537-
has_deref && !has_overloaded_deref && errors.is_empty();
1537+
has_deref && !has_overloaded_deref && errors.no_errors();
15381538
if !skip_for_simple_clone {
1539-
let msg = match &errors[..] {
1539+
let msg = match errors.as_slice() {
15401540
[] => "you can `clone` the value and consume it, but \
15411541
this might not be your desired behavior"
15421542
.to_string(),
@@ -1553,7 +1553,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
15531553
the following trait bounds could be satisfied: \
15541554
{}",
15551555
listify(
1556-
&errors,
1556+
errors.as_slice(),
15571557
|e: &FulfillmentError<'tcx>| format!(
15581558
"`{}`",
15591559
e.obligation.predicate
@@ -1569,7 +1569,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
15691569
Applicability::MaybeIncorrect,
15701570
);
15711571

1572-
suggested_cloning = errors.is_empty();
1572+
suggested_cloning = errors.no_errors();
15731573

15741574
for error in errors {
15751575
if let FulfillmentErrorCode::Select(

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
716716
return CloneSuggestion::NotEmitted;
717717
};
718718

719-
if !errors.is_empty() {
719+
if errors.has_errors() {
720720
return CloneSuggestion::NotEmitted;
721721
}
722722
let sugg = vec![

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
16161616
match self
16171617
.infcx
16181618
.type_implements_trait_shallow(clone_trait, ty.peel_refs(), self.infcx.param_env)
1619-
.as_deref()
1619+
.as_ref()
1620+
.map(|it| it.as_slice())
16201621
{
16211622
Some([]) => {
16221623
// FIXME: This error message isn't useful, since we're just

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1181,7 +1181,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
11811181
)
11821182
}));
11831183

1184-
if ocx.evaluate_obligations_error_on_ambiguity().is_empty() && count > 0 {
1184+
if ocx.evaluate_obligations_error_on_ambiguity().no_errors() && count > 0 {
11851185
diag.span_suggestion_verbose(
11861186
tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(),
11871187
msg!("dereference the return value"),

compiler/rustc_borrowck/src/type_check/liveness/trace.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
22
use rustc_index::bit_set::DenseBitSet;
33
use rustc_index::interval::IntervalSet;
44
use rustc_infer::infer::canonical::QueryRegionConstraints;
5+
use rustc_infer::traits::TraitErrors;
56
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
67
use rustc_middle::traits::query::DropckOutlivesResult;
78
use rustc_middle::ty::relate::Relate;
@@ -660,12 +661,12 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
660661
span,
661662
) {
662663
Ok(_) => ocx.evaluate_obligations_error_on_ambiguity(),
663-
Err(e) => e,
664+
Err(e) => TraitErrors::HasErrors(e),
664665
};
665666

666667
// Could have no errors if a type lowering error, say, caused the query
667668
// to fail.
668-
if !errors.is_empty() {
669+
if let TraitErrors::HasErrors(errors) = errors {
669670
typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
670671
}
671672
});

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ pub fn validate_trivial_unsize<'tcx>(
143143
) else {
144144
return false;
145145
};
146-
if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
146+
if !ocx.evaluate_obligations_error_on_ambiguity().no_errors() {
147147
return false;
148148
}
149149
infcx.leak_check(universe, None).is_ok()

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
416416
}));
417417

418418
let errors = ocx.evaluate_obligations_error_on_ambiguity();
419-
if errors.is_empty() {
419+
if errors.no_errors() {
420420
Some(ConstConditionsHold::Yes)
421421
} else {
422422
tcx.dcx()

compiler/rustc_const_eval/src/check_consts/qualifs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl Qualif for HasMutInterior {
118118
);
119119
ocx.register_obligation(obligation);
120120
let errors = ocx.evaluate_obligations_error_on_ambiguity();
121-
!errors.is_empty()
121+
!errors.no_errors()
122122
}
123123

124124
fn is_structural_in_adt_value<'tcx>(_cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
@@ -195,7 +195,7 @@ impl Qualif for NeedsNonConstDrop {
195195
},
196196
),
197197
));
198-
!ocx.evaluate_obligations_error_on_ambiguity().is_empty()
198+
!ocx.evaluate_obligations_error_on_ambiguity().no_errors()
199199
}
200200

201201
fn is_structural_in_adt_value<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {

compiler/rustc_const_eval/src/interpret/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub(crate) fn type_implements_dyn_trait<'tcx, M: Machine<'tcx>>(
4343
});
4444
Obligation::new(ecx.tcx.tcx, ObligationCause::dummy(), param_env, pred)
4545
}));
46-
let type_impls_trait = ocx.evaluate_obligations_error_on_ambiguity().is_empty();
46+
let type_impls_trait = ocx.evaluate_obligations_error_on_ambiguity().no_errors();
4747
// Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default"
4848
let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty();
4949

0 commit comments

Comments
 (0)