Skip to content

Commit

Permalink
Initial support for auto traits with default bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
Bryanskiy committed Mar 7, 2025
1 parent 30f168e commit 6c33a56
Show file tree
Hide file tree
Showing 26 changed files with 872 additions and 88 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 @@ -430,6 +430,12 @@ language_item_table! {
// Experimental lang items for implementing contract pre- and post-condition checking.
ContractBuildCheckEnsures, sym::contract_build_check_ensures, contract_build_check_ensures_fn, Target::Fn, GenericRequirement::None;
ContractCheckRequires, sym::contract_check_requires, contract_check_requires_fn, Target::Fn, GenericRequirement::None;

// 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;
}

/// The requirement imposed on the generics of a lang item
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 @@ -344,9 +344,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
9 changes: 4 additions & 5 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ fn associated_type_bounds<'tcx>(
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
let mut bounds = Vec::new();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Associated types are implicitly sized unless a `?Sized` bound is found
// Implicit bounds are added to associated types unless a `?Trait` bound is found
match filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => {
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
icx.lowerer().add_implicit_traits(&mut bounds, item_ty, hir_bounds, None, span);
}
// `ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
Expand Down Expand Up @@ -328,14 +328,13 @@ fn opaque_type_bounds<'tcx>(
let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = Vec::new();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Opaque types are implicitly sized unless a `?Sized` bound is found
// Implicit bounds are added to opaque types unless a `?Trait` bound is found
match filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => {
// Associated types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
icx.lowerer().add_implicit_traits(&mut bounds, item_ty, hir_bounds, None, span);
}
//`ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
Expand Down
60 changes: 56 additions & 4 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,41 @@ 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));
}
_ => {}
}
};

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 = Vec::new();
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);
}
}

let generics = tcx.generics_of(def_id);

// Below we'll consider the bounds on the type parameters (including `Self`)
Expand All @@ -180,11 +209,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
let mut bounds = Vec::new();
icx.lowerer().lower_bounds(
tcx.types.self_param,
self_bounds,
self_bounds.0,
&mut bounds,
ty::List::empty(),
PredicateFilter::All,
);
icx.lowerer().add_implicit_super_traits(
def_id,
&mut bounds,
self_bounds.0,
hir_generics,
self_bounds.1,
);
predicates.extend(bounds);
}

Expand All @@ -209,8 +245,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 = Vec::new();
// 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 @@ -624,6 +660,22 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
let self_param_ty = tcx.types.self_param;
let mut bounds = Vec::new();
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
match filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => {
icx.lowerer().add_implicit_super_traits(
trait_def_id,
&mut bounds,
superbounds,
generics,
item.span,
);
}
//`ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
}

let where_bounds_that_match =
icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
Expand Down
Loading

0 comments on commit 6c33a56

Please sign in to comment.