Skip to content

Commit

Permalink
initial implementation for default auto traits
Browse files Browse the repository at this point in the history
  • Loading branch information
Bryanskiy committed Aug 20, 2024
1 parent fdf61d4 commit 5bb36db
Show file tree
Hide file tree
Showing 28 changed files with 931 additions and 113 deletions.
6 changes: 6 additions & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,12 @@ language_item_table! {
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);

// Experimental lang items for `MCP: Low level components for async drop`(https://github.com/rust-lang/compiler-team/issues/727)
DefaultTrait4, sym::default_trait4, default_trait4_trait, Target::Trait, GenericRequirement::None;
DefaultTrait3, sym::default_trait3, default_trait3_trait, Target::Trait, GenericRequirement::None;
DefaultTrait2, sym::default_trait2, default_trait2_trait, Target::Trait, GenericRequirement::None;
DefaultTrait1, sym::default_trait1, default_trait1_trait, Target::Trait, GenericRequirement::None;
}

pub enum GenericRequirement {
Expand Down
26 changes: 21 additions & 5 deletions compiler/rustc_hir_analysis/src/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,27 @@ impl<'tcx> Bounds<'tcx> {
));
}

pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
pub fn push_lang_item_trait(
&mut self,
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
lang_item: LangItem,
span: Span,
) {
assert_eq!(lang_item.target(), rustc_hir::Target::Trait);
if lang_item == LangItem::Sized {
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
} else {
// Do not generate default bounds if lang item was not defined
let Some(trait_def_id) = tcx.lang_items().get(lang_item) else {
return;
};
let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]);
self.clauses.push((trait_ref.upcast(tcx), span));
}
}

pub fn clauses(
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,8 @@ fn bounds_from_generic_predicates<'tcx>(
ty::ClauseKind::Trait(trait_predicate) => {
let entry = types.entry(trait_predicate.self_ty()).or_default();
let def_id = trait_predicate.def_id();
if Some(def_id) != tcx.lang_items().sized_trait() {
// Type params are `Sized` by default, do not add that restriction to the list
// if it is a positive requirement.
if !tcx.is_default_trait(def_id) {
// Do not add that restriction to the list if it is a positive requirement.
entry.push(trait_predicate.def_id());
}
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ fn associated_type_bounds<'tcx>(

let icx = ItemCtxt::new(tcx, assoc_item_def_id);
let mut bounds = icx.lowerer().lower_mono_bounds(item_ty, hir_bounds, filter);
// Associated types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
// Implicit bounds are added to associated types unless a `?Trait` bound is found
icx.lowerer().add_implicit_traits(&mut bounds, item_ty, hir_bounds, None, span);

let trait_def_id = tcx.local_parent(assoc_item_def_id);
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
Expand Down Expand Up @@ -74,8 +74,8 @@ fn opaque_type_bounds<'tcx>(
ty::print::with_reduced_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = icx.lowerer().lower_mono_bounds(item_ty, hir_bounds, filter);
// Opaque types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
// Implicit bounds are added to opaque types unless a `?Trait` bound is found
icx.lowerer().add_implicit_traits(&mut bounds, item_ty, hir_bounds, None, span);
debug!(?bounds);

tcx.arena.alloc_from_iter(bounds.clauses(tcx))
Expand Down
54 changes: 48 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}

ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
is_trait = Some(self_bounds);
is_trait = Some((self_bounds, item.span));
}

ItemKind::Fn(sig, _, _) => {
Expand All @@ -159,6 +159,34 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
_ => {}
}
};
if let Node::TraitItem(item) = node {
let parent = tcx.local_parent(item.hir_id().owner.def_id);
let Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
unreachable!();
};

let (trait_generics, trait_bounds) = match parent_trait.kind {
hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
_ => unreachable!(),
};

// Implicitly add `Self: Trait` clauses on trait associated items.
// See comment on `add_implicit_super_traits` for more details.
if !icx.lowerer().requires_implicit_supertraits(parent, trait_bounds, trait_generics) {
let mut bounds = Bounds::default();
let self_ty_where_predicates = (parent, item.generics.predicates);
icx.lowerer().add_implicit_traits_with_filter(
&mut bounds,
tcx.types.self_param,
&[],
Some(self_ty_where_predicates),
item.span,
|tr| tr != hir::LangItem::Sized,
);
predicates.extend(bounds.clauses(tcx));
}
}

let generics = tcx.generics_of(def_id);

Expand All @@ -167,11 +195,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// on a trait we must also consider the bounds that follow the trait's name,
// like `trait Foo: A + B + C`.
if let Some(self_bounds) = is_trait {
let bounds = icx.lowerer().lower_mono_bounds(
let mut bounds = icx.lowerer().lower_mono_bounds(
tcx.types.self_param,
self_bounds,
self_bounds.0,
PredicateFilter::All,
);
icx.lowerer().add_implicit_super_traits(
def_id,
&mut bounds,
self_bounds.0,
hir_generics,
self_bounds.1,
);
predicates.extend(bounds.clauses(tcx));
effects_min_tys.extend(bounds.effects_min_tys());
}
Expand All @@ -197,8 +232,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
GenericParamKind::Type { .. } => {
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
let mut bounds = Bounds::default();
// Params are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(
// Implicit bounds are added to type params unless a `?Trait` bound is found
icx.lowerer().add_implicit_traits(
&mut bounds,
param_ty,
&[],
Expand Down Expand Up @@ -620,7 +655,14 @@ pub(super) fn implied_predicates_with_filter(
let icx = ItemCtxt::new(tcx, trait_def_id);

let self_param_ty = tcx.types.self_param;
let superbounds = icx.lowerer().lower_mono_bounds(self_param_ty, bounds, filter);
let mut superbounds = icx.lowerer().lower_mono_bounds(self_param_ty, bounds, filter);
icx.lowerer().add_implicit_super_traits(
trait_def_id,
&mut superbounds,
bounds,
generics,
item.span,
);

let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics(
generics,
Expand Down
Loading

0 comments on commit 5bb36db

Please sign in to comment.