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.
This commit is contained in:
parent
33a01e2e93
commit
41a9cbeb64
5 changed files with 30 additions and 12 deletions
|
@ -278,9 +278,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let traits::FulfillmentErrorCode::CodeSelectionError(
|
if let traits::FulfillmentErrorCode::CodeSelectionError(
|
||||||
traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
|
traits::SelectionError::OutputTypeParameterMismatch(box traits::SelectionOutputTypeParameterMismatch{
|
||||||
|
expected_trait_ref, ..
|
||||||
|
}),
|
||||||
) = error.code
|
) = 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))
|
&& span.overlaps(self.tcx.def_span(*def_id))
|
||||||
{
|
{
|
||||||
true
|
true
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
#![feature(box_patterns)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
|
|
|
@ -580,11 +580,7 @@ pub enum SelectionError<'tcx> {
|
||||||
/// After a closure impl has selected, its "outputs" were evaluated
|
/// After a closure impl has selected, its "outputs" were evaluated
|
||||||
/// (which for closures includes the "input" type params) and they
|
/// (which for closures includes the "input" type params) and they
|
||||||
/// didn't resolve. See `confirm_poly_trait_refs` for more.
|
/// didn't resolve. See `confirm_poly_trait_refs` for more.
|
||||||
OutputTypeParameterMismatch(
|
OutputTypeParameterMismatch(Box<SelectionOutputTypeParameterMismatch<'tcx>>),
|
||||||
ty::PolyTraitRef<'tcx>,
|
|
||||||
ty::PolyTraitRef<'tcx>,
|
|
||||||
ty::error::TypeError<'tcx>,
|
|
||||||
),
|
|
||||||
/// The trait pointed by `DefId` is not object safe.
|
/// The trait pointed by `DefId` is not object safe.
|
||||||
TraitNotObjectSafe(DefId),
|
TraitNotObjectSafe(DefId),
|
||||||
/// A given constant couldn't be evaluated.
|
/// A given constant couldn't be evaluated.
|
||||||
|
@ -596,6 +592,13 @@ pub enum SelectionError<'tcx> {
|
||||||
ErrorReporting,
|
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
|
/// When performing resolution, it is typically the case that there
|
||||||
/// can be one of three outcomes:
|
/// can be one of three outcomes:
|
||||||
///
|
///
|
||||||
|
|
|
@ -28,6 +28,7 @@ use rustc_hir::{GenericParam, Item, Node};
|
||||||
use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
||||||
use rustc_infer::infer::{InferOk, TypeTrace};
|
use rustc_infer::infer::{InferOk, TypeTrace};
|
||||||
use rustc_middle::traits::select::OverflowError;
|
use rustc_middle::traits::select::OverflowError;
|
||||||
|
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
|
||||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||||
|
@ -1087,17 +1088,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputTypeParameterMismatch(
|
OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
|
||||||
found_trait_ref,
|
found_trait_ref,
|
||||||
expected_trait_ref,
|
expected_trait_ref,
|
||||||
terr @ TypeError::CyclicTy(_),
|
terr: terr @ TypeError::CyclicTy(_),
|
||||||
) => self.report_type_parameter_mismatch_cyclic_type_error(
|
}) => self.report_type_parameter_mismatch_cyclic_type_error(
|
||||||
&obligation,
|
&obligation,
|
||||||
found_trait_ref,
|
found_trait_ref,
|
||||||
expected_trait_ref,
|
expected_trait_ref,
|
||||||
terr,
|
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(
|
match self.report_type_parameter_mismatch_error(
|
||||||
&obligation,
|
&obligation,
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -10,6 +10,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
|
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
|
||||||
|
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
|
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
|
||||||
TraitRef, Ty, TyCtxt, TypeVisitableExt,
|
TraitRef, Ty, TyCtxt, TypeVisitableExt,
|
||||||
|
@ -834,7 +835,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
obligations.extend(nested);
|
obligations.extend(nested);
|
||||||
obligations
|
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(
|
fn confirm_trait_upcasting_unsize_candidate(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue