Skip to content

Commit c7d27a1

Browse files
committed
Implement Min trait in new solver
1 parent 72e8244 commit c7d27a1

File tree

10 files changed

+182
-5
lines changed

10 files changed

+182
-5
lines changed

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
122122

123123
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
124124
let preds = tcx.explicit_predicates_of(parent);
125-
predicates.extend(preds.instantiate_own(tcx, identity_args));
125+
126126
if let ty::AssocItemContainer::TraitContainer = tcx.associated_item(def_id).container {
127127
// for traits, emit `type Effects: TyCompat<<(T1::Effects, ..) as Min>::Output>`
128128
// TODO do the same for impls

compiler/rustc_middle/src/ty/context.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,11 @@ fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem {
598598
TraitSolverLangItem::Destruct => LangItem::Destruct,
599599
TraitSolverLangItem::DiscriminantKind => LangItem::DiscriminantKind,
600600
TraitSolverLangItem::DynMetadata => LangItem::DynMetadata,
601+
TraitSolverLangItem::EffectsMaybe => LangItem::EffectsMaybe,
602+
TraitSolverLangItem::EffectsMin => LangItem::EffectsMin,
603+
TraitSolverLangItem::EffectsMinOutput => LangItem::EffectsMinOutput,
604+
TraitSolverLangItem::EffectsNoRuntime => LangItem::EffectsNoRuntime,
605+
TraitSolverLangItem::EffectsRuntime => LangItem::EffectsRuntime,
601606
TraitSolverLangItem::FnPtrTrait => LangItem::FnPtrTrait,
602607
TraitSolverLangItem::FusedIterator => LangItem::FusedIterator,
603608
TraitSolverLangItem::Future => LangItem::Future,

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ where
269269
ecx: &mut EvalCtxt<'_, D>,
270270
goal: Goal<I, Self>,
271271
) -> Vec<Candidate<I>>;
272+
273+
fn consider_builtin_effects_min_candidate(
274+
ecx: &mut EvalCtxt<'_, D>,
275+
goal: Goal<I, Self>,
276+
) -> Result<Candidate<I>, NoSolution>;
272277
}
273278

274279
impl<D, I> EvalCtxt<'_, D>
@@ -420,6 +425,8 @@ where
420425
G::consider_builtin_destruct_candidate(self, goal)
421426
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) {
422427
G::consider_builtin_transmute_candidate(self, goal)
428+
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::EffectsMin) {
429+
G::consider_builtin_effects_min_candidate(self, goal)
423430
} else {
424431
Err(NoSolution)
425432
};

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,65 @@ where
864864
) -> Result<Candidate<I>, NoSolution> {
865865
panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
866866
}
867+
868+
fn consider_builtin_effects_min_candidate(
869+
ecx: &mut EvalCtxt<'_, D>,
870+
goal: Goal<I, Self>,
871+
) -> Result<Candidate<I>, NoSolution> {
872+
let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
873+
return Err(NoSolution);
874+
};
875+
876+
877+
let cx = ecx.cx();
878+
879+
let mut first_non_maybe = None;
880+
let mut non_maybe_count = 0;
881+
for ty in types {
882+
if !matches!(ty::EffectKind::try_from_ty(cx, ty), Some(ty::EffectKind::Maybe)) {
883+
first_non_maybe.get_or_insert(ty);
884+
non_maybe_count += 1;
885+
}
886+
}
887+
888+
match non_maybe_count {
889+
0 => {
890+
let ty = ty::EffectKind::Maybe.to_ty(cx);
891+
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
892+
ecx.instantiate_normalizes_to_term(goal, ty.into());
893+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
894+
})
895+
}
896+
1 => {
897+
let ty = first_non_maybe.unwrap();
898+
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
899+
ecx.instantiate_normalizes_to_term(goal, ty.into());
900+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
901+
})
902+
}
903+
_ => {
904+
let mut min = ty::EffectKind::Maybe;
905+
906+
for ty in types {
907+
let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else {
908+
return Err(NoSolution);
909+
};
910+
911+
let Some(result) = ty::EffectKind::min(min, kind) else {
912+
return Err(NoSolution);
913+
};
914+
915+
min = result;
916+
}
917+
918+
let ty = min.to_ty(cx);
919+
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
920+
ecx.instantiate_normalizes_to_term(goal, ty.into());
921+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
922+
})
923+
}
924+
}
925+
}
867926
}
868927

869928
impl<D, I> EvalCtxt<'_, D>

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,47 @@ where
702702
}
703703
})
704704
}
705+
706+
fn consider_builtin_effects_min_candidate(
707+
ecx: &mut EvalCtxt<'_, D>,
708+
goal: Goal<I, Self>,
709+
) -> Result<Candidate<I>, NoSolution> {
710+
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
711+
return Err(NoSolution);
712+
}
713+
714+
let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
715+
return Err(NoSolution);
716+
};
717+
718+
let cx = ecx.cx();
719+
let maybe_count = types
720+
.into_iter()
721+
.filter_map(|ty| ty::EffectKind::try_from_ty(cx, ty))
722+
.filter(|&ty| ty == ty::EffectKind::Maybe)
723+
.count();
724+
725+
// Don't do concrete type check unless there are more than one type that will influence the result.
726+
// This would allow `(Maybe, T): Min` pass even if we know nothing about `T`.
727+
if types.len() - maybe_count > 1 {
728+
let mut min = ty::EffectKind::Maybe;
729+
730+
for ty in types {
731+
let Some(kind) = ty::EffectKind::try_from_ty(ecx.cx(), ty) else {
732+
return Err(NoSolution);
733+
};
734+
735+
let Some(result) = ty::EffectKind::min(min, kind) else {
736+
return Err(NoSolution);
737+
};
738+
739+
min = result;
740+
}
741+
}
742+
743+
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
744+
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
745+
}
705746
}
706747

707748
impl<D, I> EvalCtxt<'_, D>

compiler/rustc_type_ir/src/effects.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsRuntime, EffectsNoRuntime};
2+
use crate::Interner;
3+
use crate::inherent::{AdtDef, IntoKind, Ty};
4+
5+
#[derive(Clone, Copy, PartialEq, Eq)]
6+
pub enum EffectKind {
7+
Maybe,
8+
Runtime,
9+
NoRuntime,
10+
}
11+
12+
impl EffectKind {
13+
pub fn try_from_def_id<I: Interner>(tcx: I, def_id: I::DefId) -> Option<EffectKind> {
14+
if tcx.is_lang_item(def_id, EffectsMaybe) {
15+
Some(EffectKind::Maybe)
16+
} else if tcx.is_lang_item(def_id, EffectsRuntime) {
17+
Some(EffectKind::Runtime)
18+
} else if tcx.is_lang_item(def_id, EffectsNoRuntime) {
19+
Some(EffectKind::NoRuntime)
20+
} else {
21+
None
22+
}
23+
}
24+
25+
pub fn to_def_id<I: Interner>(self, tcx: I) -> I::DefId {
26+
let lang_item = match self {
27+
EffectKind::Maybe => EffectsMaybe,
28+
EffectKind::NoRuntime => EffectsNoRuntime,
29+
EffectKind::Runtime => EffectsRuntime,
30+
};
31+
32+
tcx.require_lang_item(lang_item)
33+
}
34+
35+
pub fn try_from_ty<I: Interner>(tcx: I, ty: I::Ty) -> Option<EffectKind> {
36+
if let crate::Adt(def, _) = ty.kind() {
37+
Self::try_from_def_id(tcx, def.def_id())
38+
} else {
39+
None
40+
}
41+
}
42+
43+
pub fn to_ty<I: Interner>(self, tcx: I) -> I::Ty {
44+
I::Ty::new_adt(tcx, tcx.adt_def(self.to_def_id(tcx)), Default::default())
45+
}
46+
47+
pub fn min(a: Self, b: Self) -> Option<Self> {
48+
use EffectKind::*;
49+
match (a, b) {
50+
(Maybe, x) | (x, Maybe) => Some(x),
51+
(Runtime, Runtime) => Some(Runtime),
52+
(NoRuntime, NoRuntime) => Some(NoRuntime),
53+
(Runtime, NoRuntime) | (NoRuntime, Runtime) => None,
54+
}
55+
}
56+
}

compiler/rustc_type_ir/src/lang_items.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ pub enum TraitSolverLangItem {
1717
Destruct,
1818
DiscriminantKind,
1919
DynMetadata,
20+
EffectsMaybe,
21+
EffectsMin,
22+
EffectsMinOutput,
23+
EffectsNoRuntime,
24+
EffectsRuntime,
2025
FnPtrTrait,
2126
FusedIterator,
2227
Future,

compiler/rustc_type_ir/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ mod macros;
3535
mod binder;
3636
mod canonical;
3737
mod const_kind;
38+
mod effects;
3839
mod flags;
3940
mod generic_arg;
4041
mod interner;
@@ -51,6 +52,7 @@ pub use canonical::*;
5152
#[cfg(feature = "nightly")]
5253
pub use codec::*;
5354
pub use const_kind::*;
55+
pub use effects::*;
5456
pub use flags::*;
5557
pub use generic_arg::*;
5658
pub use interner::*;

library/core/src/marker.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,14 +1054,15 @@ pub mod effects {
10541054

10551055
#[lang = "EffectsTyCompat"]
10561056
#[marker]
1057-
pub trait TyCompat<T> {}
1057+
pub trait TyCompat<T: ?Sized> {}
10581058

1059-
impl<T> TyCompat<T> for T {}
1060-
impl<T> TyCompat<T> for Maybe {}
1059+
impl<T: ?Sized> TyCompat<T> for T {}
1060+
impl<T: ?Sized> TyCompat<T> for Maybe {}
1061+
impl<T: ?Sized> TyCompat<Maybe> for T {}
10611062

10621063
#[lang = "EffectsMin"]
10631064
pub trait Min {
10641065
#[lang = "EffectsMinOutput"]
1065-
type Output;
1066+
type Output: ?Sized;
10661067
}
10671068
}

tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ run-pass
2+
//@ compile-flags: -Znext-solver
23

34
#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
45

0 commit comments

Comments
 (0)