Skip to content

Commit

Permalink
Auto merge of #111029 - Nilstrieb:when-the-errs-are-too-big, r=petroc…
Browse files Browse the repository at this point in the history
…henkov

Shrink `SelectionError` a lot

`SelectionError` used to be 80 bytes (on 64 bit). That's quite big. Especially because the selection cache contained `Result<_, SelectionError>. The Ok type is only 32 bytes, so the 80 bytes significantly inflate the size of the cache.

Most variants of the `SelectionError` seem to be hard errors, only `Unimplemented` shows up in practice (for cranelift-codegen, it occupies 23.4% of all cache entries). We can just box away the biggest variant, `OutputTypeParameterMismatch`, to get the size down to 16 bytes, well within the size of the Ok type inside the cache.
  • Loading branch information
bors committed May 11, 2023
2 parents 4d941cd + e8ab648 commit f8d8ffa
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
) -> bool {
if let traits::FulfillmentErrorCode::CodeSelectionError(
traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
traits::SelectionError::OutputTypeParameterMismatch(box traits::SelectionOutputTypeParameterMismatch{
expected_trait_ref, ..
}),
) = error.code
&& let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
&& let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected_trait_ref.skip_binder().self_ty().kind()
&& span.overlaps(self.tcx.def_span(*def_id))
{
true
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![feature(let_chains)]
#![feature(try_blocks)]
#![feature(never_type)]
#![feature(box_patterns)]
#![feature(min_specialization)]
#![feature(control_flow_enum)]
#![feature(drain_filter)]
Expand Down
13 changes: 8 additions & 5 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,11 +580,7 @@ pub enum SelectionError<'tcx> {
/// After a closure impl has selected, its "outputs" were evaluated
/// (which for closures includes the "input" type params) and they
/// didn't resolve. See `confirm_poly_trait_refs` for more.
OutputTypeParameterMismatch(
ty::PolyTraitRef<'tcx>,
ty::PolyTraitRef<'tcx>,
ty::error::TypeError<'tcx>,
),
OutputTypeParameterMismatch(Box<SelectionOutputTypeParameterMismatch<'tcx>>),
/// The trait pointed by `DefId` is not object safe.
TraitNotObjectSafe(DefId),
/// A given constant couldn't be evaluated.
Expand All @@ -596,6 +592,13 @@ pub enum SelectionError<'tcx> {
ErrorReporting,
}

#[derive(Clone, Debug, TypeVisitable, Lift)]
pub struct SelectionOutputTypeParameterMismatch<'tcx> {
pub found_trait_ref: ty::PolyTraitRef<'tcx>,
pub expected_trait_ref: ty::PolyTraitRef<'tcx>,
pub terr: ty::error::TypeError<'tcx>,
}

/// When performing resolution, it is typically the case that there
/// can be one of three outcomes:
///
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use rustc_hir::{GenericParam, Item, Node};
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::{InferOk, TypeTrace};
use rustc_middle::traits::select::OverflowError;
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
Expand Down Expand Up @@ -1087,17 +1088,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}

OutputTypeParameterMismatch(
OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
found_trait_ref,
expected_trait_ref,
terr @ TypeError::CyclicTy(_),
) => self.report_type_parameter_mismatch_cyclic_type_error(
terr: terr @ TypeError::CyclicTy(_),
}) => self.report_type_parameter_mismatch_cyclic_type_error(
&obligation,
found_trait_ref,
expected_trait_ref,
terr,
),
OutputTypeParameterMismatch(found_trait_ref, expected_trait_ref, _) => {
OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
found_trait_ref,
expected_trait_ref,
terr: _,
}) => {
match self.report_type_parameter_mismatch_error(
&obligation,
span,
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
use rustc_middle::ty::{
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
TraitRef, Ty, TyCtxt, TypeVisitableExt,
Expand Down Expand Up @@ -811,7 +812,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_poly_trait_refs(
&mut self,
obligation: &TraitObligation<'tcx>,
expected_trait_ref: ty::PolyTraitRef<'tcx>,
self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let obligation_trait_ref = obligation.predicate.to_poly_trait_ref();
// Normalize the obligation and expected trait refs together, because why not
Expand All @@ -822,7 +823,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
(obligation_trait_ref, expected_trait_ref),
(obligation_trait_ref, self_ty_trait_ref),
)
});

Expand All @@ -834,7 +835,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligations.extend(nested);
obligations
})
.map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
.map_err(|terr| {
OutputTypeParameterMismatch(Box::new(SelectionOutputTypeParameterMismatch {
expected_trait_ref: obligation_trait_ref,
found_trait_ref: expected_trait_ref,
terr,
}))
})
}

fn confirm_trait_upcasting_unsize_candidate(
Expand Down

0 comments on commit f8d8ffa

Please sign in to comment.