Skip to content

Commit

Permalink
address review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
fee1-dead committed Jun 28, 2024
1 parent 8b2fac9 commit 65a0bee
Show file tree
Hide file tree
Showing 18 changed files with 113 additions and 124 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,8 @@ language_item_table! {
EffectsRuntime, sym::EffectsRuntime, effects_runtime, Target::Struct, GenericRequirement::None;
EffectsNoRuntime, sym::EffectsNoRuntime, effects_no_runtime, Target::Struct, GenericRequirement::None;
EffectsMaybe, sym::EffectsMaybe, effects_maybe, Target::Struct, GenericRequirement::None;
EffectsMin, sym::EffectsMin, effects_min, Target::Trait, GenericRequirement::None;
EffectsMinOutput, sym::EffectsMinOutput, effects_min_output, Target::AssocTy, GenericRequirement::None;
EffectsIntersection, sym::EffectsIntersection, effects_intersection, Target::Trait, GenericRequirement::None;
EffectsIntersectionOutput, sym::EffectsIntersectionOutput, effects_intersection_output, Target::AssocTy, GenericRequirement::None;
EffectsCompat, sym::EffectsCompat, effects_compat, Target::Trait, GenericRequirement::Exact(1);
EffectsTyCompat, sym::EffectsTyCompat, effects_ty_compat, Target::Trait, GenericRequirement::Exact(1);
}
Expand Down
52 changes: 29 additions & 23 deletions compiler/rustc_hir_analysis/src/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,19 @@ impl<'tcx> Bounds<'tcx> {
}
// For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
// associated type of `<T as Tr>` and make sure that the effect is compatible.
if let Some(compat_val) = match (tcx.def_kind(defining_def_id), constness) {
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
// FIXME(effects): revisit the correctness of this
(_, ty::BoundConstness::Const) => Some(tcx.consts.false_),
(_, ty::BoundConstness::Const) => tcx.consts.false_,
// body owners that can have trait bounds
(DefKind::Const | DefKind::Fn | DefKind::AssocFn, ty::BoundConstness::ConstIfConst) => {
Some(tcx.expected_host_effect_param_for_body(defining_def_id))
tcx.expected_host_effect_param_for_body(defining_def_id)
}

(_, ty::BoundConstness::NotConst) => {
tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait).then_some(tcx.consts.true_)
if !tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait) {
return;
}
tcx.consts.true_
}

(
Expand All @@ -97,8 +100,12 @@ impl<'tcx> Bounds<'tcx> {
let ty = bound_trait_ref
.map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));

// Replace the binder with dummy types/lifetimes. This should work for any
// binder as long as they don't have any bounds e.g. `for<T: Trait>`.
// When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the
// binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in
// the `Min` associated type properly (which doesn't allow using `for<>`)
// This should work for any bound variables as long as they don't have any
// bounds e.g. `for<T: Trait>`.
// FIXME(effects) reconsider this approach to allow compatibility with `for<T: Tr>`
let ty = tcx.replace_bound_vars_uncached(
ty,
FnMutDelegate {
Expand Down Expand Up @@ -128,24 +135,23 @@ impl<'tcx> Bounds<'tcx> {
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
return;
}
} {
// create a new projection type `<T as Tr>::Effects`
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
tcx.dcx().span_delayed_bug(
span,
"`~const` trait bound has no effect assoc yet no errors encountered?",
);
return;
};
let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
// make `<T as Tr>::Effects: Compat<runtime>`
let new_trait_ref = ty::TraitRef::new(
tcx,
tcx.require_lang_item(LangItem::EffectsCompat, Some(span)),
[ty::GenericArg::from(self_ty), compat_val.into()],
};
// create a new projection type `<T as Tr>::Effects`
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
tcx.dcx().span_delayed_bug(
span,
"`~const` trait bound has no effect assoc yet no errors encountered?",
);
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
}
return;
};
let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
// make `<T as Tr>::Effects: Compat<runtime>`
let new_trait_ref = ty::TraitRef::new(
tcx,
tcx.require_lang_item(LangItem::EffectsCompat, Some(span)),
[ty::GenericArg::from(self_ty), compat_val.into()],
);
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
}

pub fn push_projection_bound(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ pub(super) fn explicit_item_bounds_with_filter(
let tup = Ty::new(tcx, ty::Tuple(preds.effects_min_tys));
// FIXME(effects) span
let span = tcx.def_span(def_id);
let assoc = tcx.require_lang_item(hir::LangItem::EffectsMinOutput, Some(span));
let assoc = tcx.require_lang_item(hir::LangItem::EffectsIntersectionOutput, Some(span));
let proj = Ty::new_projection(tcx, assoc, [tup]);
let self_proj = Ty::new_projection(
tcx,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,8 +599,8 @@ fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem {
TraitSolverLangItem::DiscriminantKind => LangItem::DiscriminantKind,
TraitSolverLangItem::DynMetadata => LangItem::DynMetadata,
TraitSolverLangItem::EffectsMaybe => LangItem::EffectsMaybe,
TraitSolverLangItem::EffectsMin => LangItem::EffectsMin,
TraitSolverLangItem::EffectsMinOutput => LangItem::EffectsMinOutput,
TraitSolverLangItem::EffectsIntersection => LangItem::EffectsIntersection,
TraitSolverLangItem::EffectsIntersectionOutput => LangItem::EffectsIntersectionOutput,
TraitSolverLangItem::EffectsNoRuntime => LangItem::EffectsNoRuntime,
TraitSolverLangItem::EffectsRuntime => LangItem::EffectsRuntime,
TraitSolverLangItem::FnPtrTrait => LangItem::FnPtrTrait,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ where
goal: Goal<I, Self>,
) -> Vec<Candidate<I>>;

fn consider_builtin_effects_min_candidate(
fn consider_builtin_effects_intersection_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution>;
Expand Down Expand Up @@ -425,8 +425,8 @@ where
G::consider_builtin_destruct_candidate(self, goal)
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) {
G::consider_builtin_transmute_candidate(self, goal)
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::EffectsMin) {
G::consider_builtin_effects_min_candidate(self, goal)
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::EffectsIntersection) {
G::consider_builtin_effects_intersection_candidate(self, goal)
} else {
Err(NoSolution)
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ where
panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
}

fn consider_builtin_effects_min_candidate(
fn consider_builtin_effects_intersection_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
Expand Down Expand Up @@ -903,11 +903,15 @@ where
let mut min = ty::EffectKind::Maybe;

for ty in types.iter() {
// We can't find the intersection if the types used are generic.
//
// FIXME(effects) do we want to look at where clauses to get some
// clue for the case where generic types are being used?
let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else {
return Err(NoSolution);
};

let Some(result) = ty::EffectKind::min(min, kind) else {
let Some(result) = ty::EffectKind::intersection(min, kind) else {
return Err(NoSolution);
};

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ where
})
}

fn consider_builtin_effects_min_candidate(
fn consider_builtin_effects_intersection_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
Expand Down Expand Up @@ -732,7 +732,7 @@ where
return Err(NoSolution);
};

let Some(result) = ty::EffectKind::min(min, kind) else {
let Some(result) = ty::EffectKind::intersection(min, kind) else {
return Err(NoSolution);
};

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ symbols! {
DoubleEndedIterator,
Duration,
EffectsCompat,
EffectsIntersection,
EffectsIntersectionOutput,
EffectsMaybe,
EffectsMin,
EffectsMinOutput,
EffectsNoRuntime,
EffectsRuntime,
EffectsTyCompat,
Expand Down
99 changes: 34 additions & 65 deletions compiler/rustc_ty_utils/src/assoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,21 +184,17 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
if !tcx.features().effects {
return None;
}
match tcx.def_kind(def_id) {
let (feed, parent_did) = match tcx.def_kind(def_id) {
DefKind::Trait => {
let trait_def_id = def_id;
let Some(attr) = tcx.get_attr(def_id, sym::const_trait) else {
return None;
};
let attr = tcx.get_attr(def_id, sym::const_trait)?;

let span = attr.span;
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);

let local_def_id = trait_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();

trait_assoc_ty.feed_hir();

// Copy span of the attribute.
trait_assoc_ty.def_ident_span(Some(span));

Expand All @@ -213,47 +209,20 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
is_effects_desugaring: true,
});

// visibility is public.
trait_assoc_ty.visibility(ty::Visibility::Public);

// No default type
trait_assoc_ty.defaultness(hir::Defaultness::Default { has_value: false });

trait_assoc_ty.is_type_alias_impl_trait(false);

// Copy generics_of of the trait, making the trait as parent.
trait_assoc_ty.generics_of({
let parent_generics = tcx.generics_of(trait_def_id);
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();

ty::Generics {
parent: Some(trait_def_id.to_def_id()),
parent_count,
own_params: vec![],
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
has_self: false,
has_late_bound_regions: None,
host_effect_index: parent_generics.host_effect_index,
}
});

trait_assoc_ty.explicit_item_bounds(ty::EarlyBinder::bind(&[]));
trait_assoc_ty.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));

// There are no inferred outlives for the synthesized associated type.
trait_assoc_ty.inferred_outlives_of(&[]);

Some(def_id)
(trait_assoc_ty, trait_def_id)
}
DefKind::Impl { .. } => {
let impl_def_id = def_id;
let Some(trait_id) = tcx.trait_id_of_impl(def_id.to_def_id()) else { return None };
let trait_id = tcx.trait_id_of_impl(def_id.to_def_id())?;

// first get the DefId of the assoc type on the trait, if there is not,
// then we don't need to generate it on the impl.
let Some(trait_assoc_id) = tcx.associated_type_for_effects(trait_id) else {
return None;
};
let trait_assoc_id = tcx.associated_type_for_effects(trait_id)?;

// FIXME(effects): span
let span = tcx.def_ident_span(def_id).unwrap();
Expand All @@ -263,8 +232,6 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
let local_def_id = impl_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();

impl_assoc_ty.feed_hir();

impl_assoc_ty.def_ident_span(Some(span));

impl_assoc_ty.associated_item(ty::AssocItem {
Expand All @@ -278,9 +245,6 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
is_effects_desugaring: true,
});

// visibility is public.
impl_assoc_ty.visibility(ty::Visibility::Public);

// no default value.
impl_assoc_ty.defaultness(hir::Defaultness::Final);

Expand All @@ -298,36 +262,41 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
ty::GenericArgs::empty(),
)));

// Copy generics_of of the impl, making the impl as parent.
impl_assoc_ty.generics_of({
let parent_generics = tcx.generics_of(impl_def_id);
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();

ty::Generics {
parent: Some(impl_def_id.to_def_id()),
parent_count,
own_params: vec![],
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
has_self: false,
has_late_bound_regions: None,
host_effect_index: parent_generics.host_effect_index,
}
});

// impl_assoc_ty.explicit_item_bounds(ty::EarlyBinder::bind(&[]));
impl_assoc_ty.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));

// There are no inferred outlives for the synthesized associated type.
impl_assoc_ty.inferred_outlives_of(&[]);

Some(def_id)
(impl_assoc_ty, impl_def_id)
}
def_kind => bug!(
"associated_type_for_effects: {:?} should be Trait or Impl but is {:?}",
def_id,
def_kind
),
}
};

feed.feed_hir();

// visibility is public.
feed.visibility(ty::Visibility::Public);

// Copy generics_of of the trait/impl, making the trait/impl as parent.
feed.generics_of({
let parent_generics = tcx.generics_of(parent_did);
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();

ty::Generics {
parent: Some(parent_did.to_def_id()),
parent_count,
own_params: vec![],
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
has_self: false,
has_late_bound_regions: None,
host_effect_index: parent_generics.host_effect_index,
}
});
feed.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));

// There are no inferred outlives for the synthesized associated type.
feed.inferred_outlives_of(&[]);

Some(feed.def_id().to_def_id())
}

/// Given an `fn_def_id` of a trait or a trait implementation:
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_type_ir/src/effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ impl EffectKind {
I::Ty::new_adt(tcx, tcx.adt_def(self.to_def_id(tcx)), Default::default())
}

pub fn min(a: Self, b: Self) -> Option<Self> {
/// Returns an intersection between two effect kinds. If one effect kind
/// is more permissive than the other (e.g. `Maybe` vs `Runtime`), this
/// returns the less permissive effect kind (`Runtime`).
pub fn intersection(a: Self, b: Self) -> Option<Self> {
use EffectKind::*;
match (a, b) {
(Maybe, x) | (x, Maybe) => Some(x),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_type_ir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ pub enum TraitSolverLangItem {
Destruct,
DiscriminantKind,
DynMetadata,
EffectsIntersection,
EffectsIntersectionOutput,
EffectsMaybe,
EffectsMin,
EffectsMinOutput,
EffectsNoRuntime,
EffectsRuntime,
FnPtrTrait,
Expand Down
11 changes: 8 additions & 3 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1062,9 +1062,14 @@ pub mod effects {
impl<T: ?Sized> TyCompat<T> for Maybe {}
impl<T: ?Sized> TyCompat<Maybe> for T {}

#[lang = "EffectsMin"]
pub trait Min {
#[lang = "EffectsMinOutput"]
#[lang = "EffectsIntersection"]
pub trait Intersection {
#[lang = "EffectsIntersectionOutput"]
type Output: ?Sized;
}

// FIXME(effects): remove this after next trait solver lands
impl Intersection for () {
type Output = Maybe;
}
}
Loading

0 comments on commit 65a0bee

Please sign in to comment.