Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use adt_const_params to make simplify_type faster #109127

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,11 @@ impl<'tcx> InherentCollect<'tcx> {
}
}

if let Some(simp) = simplify_type(
self.tcx,
self_ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
if let Some(simp) = simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(self.tcx, self_ty)
{
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected self type: {:?}", self_ty);
Expand Down Expand Up @@ -164,12 +163,11 @@ impl<'tcx> InherentCollect<'tcx> {
}
}

if let Some(simp) = simplify_type(
self.tcx,
ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
if let Some(simp) = simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(self.tcx, ty)
{
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected primitive type: {:?}", ty);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}

fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) else {
let Some(simp) = simplify_type::<{TreatParams::AsCandidateKey}, {TreatProjections::AsCandidateKey}>(self.tcx, self_ty) else {
bug!("unexpected incoherent type: {:?}", self_ty)
};
for &impl_def_id in self.tcx.incoherent_impls(simp) {
Expand Down
37 changes: 18 additions & 19 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1517,13 +1517,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.into_iter()
.any(|info| self.associated_value(info.def_id, item_name).is_some());
let found_assoc = |ty: Ty<'tcx>| {
simplify_type(tcx, ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey)
.and_then(|simp| {
tcx.incoherent_impls(simp)
.iter()
.find_map(|&id| self.associated_value(id, item_name))
})
.is_some()
simplify_type::<{ TreatParams::AsCandidateKey }, { TreatProjections::AsCandidateKey }>(
tcx, ty,
)
.and_then(|simp| {
tcx.incoherent_impls(simp)
.iter()
.find_map(|&id| self.associated_value(id, item_name))
})
.is_some()
};
let found_candidate = found_candidate
|| found_assoc(tcx.types.i8)
Expand Down Expand Up @@ -2646,12 +2648,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME: Even though negative bounds are not implemented, we could maybe handle
// cases where a positive bound implies a negative impl.
(candidates, Vec::new())
} else if let Some(simp_rcvr_ty) = simplify_type(
self.tcx,
rcvr_ty,
TreatParams::ForLookup,
TreatProjections::ForLookup,
) {
} else if let Some(simp_rcvr_ty) = simplify_type::<
{ TreatParams::ForLookup },
{ TreatProjections::ForLookup },
>(self.tcx, rcvr_ty)
{
let mut potential_candidates = Vec::new();
let mut explicitly_negative = Vec::new();
for candidate in candidates {
Expand All @@ -2664,12 +2665,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
.any(|imp_did| {
let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
let imp_simp = simplify_type(
self.tcx,
imp.self_ty(),
TreatParams::ForLookup,
TreatProjections::ForLookup,
);
let imp_simp = simplify_type::<
{ TreatParams::ForLookup },
{ TreatProjections::ForLookup },
>(self.tcx, imp.self_ty());
imp_simp.map_or(false, |s| s == simp_rcvr_ty)
})
{
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1855,12 +1855,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) {
let trait_ref = trait_ref.subst_identity();

let simplified_self_ty = fast_reject::simplify_type(
self.tcx,
trait_ref.self_ty(),
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
);
let simplified_self_ty = fast_reject::simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(self.tcx, trait_ref.self_ty());

fx_hash_map
.entry(trait_ref.def_id)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![allow(incomplete_features)]
#![feature(adt_const_params)]
#![feature(allocator_api)]
#![feature(array_windows)]
#![feature(assert_matches)]
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_middle/src/ty/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@ pub enum TreatProjections {
/// is only correct if they are fully normalized.
///
/// ¹ meaning that if the outermost layers are different, then the whole types are also different.
pub fn simplify_type<'tcx>(
pub fn simplify_type<
'tcx,
const TREAT_PARAMS: TreatParams,
const TREAT_PROJECTIONS: TreatProjections,
>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
treat_params: TreatParams,
treat_projections: TreatProjections,
) -> Option<SimplifiedType> {
match *ty.kind() {
ty::Bool => Some(BoolSimplifiedType),
Expand Down Expand Up @@ -135,11 +137,11 @@ pub fn simplify_type<'tcx>(
ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())),
ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
ty::Placeholder(..) => Some(PlaceholderSimplifiedType),
ty::Param(_) => match treat_params {
ty::Param(_) => match TREAT_PARAMS {
TreatParams::ForLookup => Some(PlaceholderSimplifiedType),
TreatParams::AsCandidateKey => None,
},
ty::Alias(..) => match treat_projections {
ty::Alias(..) => match TREAT_PROJECTIONS {
TreatProjections::ForLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType),
TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType),
TreatProjections::AsCandidateKey | TreatProjections::ForLookup => None,
Expand Down
41 changes: 20 additions & 21 deletions compiler/rustc_middle/src/ty/trait_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,23 +124,23 @@ impl<'tcx> TyCtxt<'tcx> {
self_ty: Ty<'tcx>,
f: impl FnMut(DefId),
) {
self.for_each_relevant_impl_treating_projections(
self.for_each_relevant_impl_treating_projections::<{ TreatProjections::ForLookup }>(
trait_def_id,
self_ty,
TreatProjections::ForLookup,
f,
)
}

pub fn for_each_relevant_impl_treating_projections(
pub fn for_each_relevant_impl_treating_projections<
const TREAT_PROJECTIONS: TreatProjections,
>(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
treat_projections: TreatProjections,
mut f: impl FnMut(DefId),
) {
let _: Option<()> =
self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
self.find_map_relevant_impl::<_, TREAT_PROJECTIONS>(trait_def_id, self_ty, |did| {
f(did);
None
});
Expand All @@ -153,12 +153,11 @@ impl<'tcx> TyCtxt<'tcx> {
self_ty: Ty<'tcx>,
) -> impl Iterator<Item = DefId> + 'tcx {
let impls = self.trait_impls_of(trait_def_id);
if let Some(simp) = fast_reject::simplify_type(
self,
self_ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
if let Some(simp) = fast_reject::simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(self, self_ty)
{
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
return impls.iter().copied();
}
Expand All @@ -171,11 +170,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// the first non-none value.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn find_map_relevant_impl<T>(
pub fn find_map_relevant_impl<T, const TREAT_PROJECTIONS: TreatProjections>(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
treat_projections: TreatProjections,
mut f: impl FnMut(DefId) -> Option<T>,
) -> Option<T> {
// FIXME: This depends on the set of all impls for the trait. That is
Expand All @@ -195,8 +193,10 @@ impl<'tcx> TyCtxt<'tcx> {
// whose outer level is not a parameter or projection. Especially for things like
// `T: Clone` this is incredibly useful as we would otherwise look at all the impls
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
if let Some(simp) =
fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup, treat_projections)
if let Some(simp) = fast_reject::simplify_type::<
{ TreatParams::ForLookup },
TREAT_PROJECTIONS,
>(self, self_ty)
{
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
Expand Down Expand Up @@ -258,12 +258,11 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
continue;
}

if let Some(simplified_self_ty) = fast_reject::simplify_type(
tcx,
impl_self_ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
if let Some(simplified_self_ty) = fast_reject::simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(tcx, impl_self_ty)
{
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
} else {
impls.blanket_impls.push(impl_def_id);
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,10 @@ impl<'tcx> TyCtxt<'tcx> {
self.ensure().coherent_trait(drop_trait);

let ty = self.type_of(adt_did).subst_identity();
let (did, constness) = self.find_map_relevant_impl(
// FIXME: This could also be some other mode, like "unexpected"
let (did, constness) = self.find_map_relevant_impl::<_, { TreatProjections::ForLookup }>(
drop_trait,
ty,
// FIXME: This could also be some other mode, like "unexpected"
TreatProjections::ForLookup,
|impl_did| {
if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
if validate(self, impl_did).is_ok() {
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_trait_selection/src/solve/assembly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
candidates: &mut Vec<Candidate<'tcx>>,
) {
let tcx = self.tcx();
tcx.for_each_relevant_impl_treating_projections(
tcx.for_each_relevant_impl_treating_projections::<{ TreatProjections::NextSolverLookup }>(
goal.predicate.trait_def_id(tcx),
goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
|impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) {
Ok(result) => candidates
.push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// `instantiate_constituent_tys_for_auto_trait` returns nothing for
// projection types anyways. So it doesn't really matter what we do
// here, and this is faster.
if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
goal.predicate.def_id(),
goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
Some,
) {
if let Some(def_id) =
ecx.tcx().find_map_relevant_impl::<_, { TreatProjections::NextSolverLookup }>(
goal.predicate.def_id(),
goal.predicate.self_ty(),
Some,
)
{
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
return Err(NoSolution);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1800,10 +1800,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
})
.and_then(|(trait_assoc_item, id)| {
let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
self.tcx.find_map_relevant_impl(
self.tcx.find_map_relevant_impl::<_, { TreatProjections::ForLookup }>(
id,
proj.projection_ty.self_ty(),
TreatProjections::ForLookup,
|did| {
self.tcx
.associated_items(did)
Expand Down Expand Up @@ -2182,10 +2181,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> bool {
let get_trait_impl = |trait_def_id| {
self.tcx.find_map_relevant_impl(
self.tcx.find_map_relevant_impl::<_, { TreatProjections::ForLookup }>(
trait_def_id,
trait_ref.skip_binder().self_ty(),
TreatProjections::ForLookup,
Some,
)
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,12 +781,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

ty::Adt(..) => {
// Find a custom `impl Drop` impl, if it exists
let relevant_impl = self.tcx().find_map_relevant_impl(
self.tcx().require_lang_item(LangItem::Drop, None),
obligation.predicate.skip_binder().trait_ref.self_ty(),
TreatProjections::ForLookup,
Some,
);
let relevant_impl =
self.tcx().find_map_relevant_impl::<_, { TreatProjections::ForLookup }>(
self.tcx().require_lang_item(LangItem::Drop, None),
obligation.predicate.skip_binder().trait_ref.self_ty(),
Some,
);

if let Some(impl_def_id) = relevant_impl {
// Check that `impl Drop` is actually const, if there is a custom impl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,11 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
/// Insert an impl into this set of children without comparing to any existing impls.
fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
if let Some(st) = fast_reject::simplify_type(
tcx,
trait_ref.self_ty(),
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
if let Some(st) = fast_reject::simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(tcx, trait_ref.self_ty())
{
debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
} else {
Expand All @@ -69,12 +68,11 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
let vec: &mut Vec<DefId>;
if let Some(st) = fast_reject::simplify_type(
tcx,
trait_ref.self_ty(),
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
if let Some(st) = fast_reject::simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(tcx, trait_ref.self_ty())
{
debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
vec = self.non_blanket_impls.get_mut(&st).unwrap();
} else {
Expand Down Expand Up @@ -310,12 +308,10 @@ impl<'tcx> GraphExt<'tcx> for Graph {

let mut parent = trait_def_id;
let mut last_lint = None;
let simplified = fast_reject::simplify_type(
tcx,
trait_ref.self_ty(),
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
);
let simplified = fast_reject::simplify_type::<
{ TreatParams::AsCandidateKey },
{ TreatProjections::AsCandidateKey },
>(tcx, trait_ref.self_ty());

// Descend the specialization tree, where `parent` is the current parent node.
loop {
Expand Down
Loading