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

Initial support for auto traits with default bounds #120706

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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 @@ -434,6 +434,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;
Comment on lines +438 to +442
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not make it so that the compiler collects these traits on-demand, rather than having to be hard-coded in the compiler? Having 4 dummy lang items is kinda annoying, and it seems like something that can be an attr on a trait.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can. This would require partially copying the logic for lang items collection, as new traits can be defined in another crate. Using lang items is just easier.

}

/// 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 @@ -341,9 +341,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 @@ -38,13 +38,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_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
}
// `ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
Expand Down Expand Up @@ -327,14 +327,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_default_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 @@ -165,12 +165,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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not put this in gather_explicit_predicates_of. This is for predicates written by the user. Push this one level out to the caller

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me. From what I see Sized bounds are added in gather_explicit_predicates_of, but they aren't explicit in the ordinary sense. Do they considered explicit because of the user written T: ?Sized bounds? For default_auto_traits we have the same situation, except that T: ?Trait bounds can be used in more contexts, and here is one such context.

Perhaps you were confused by the implicit word in new methods from bounds.rs. Renamed them.

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: DefaultAutoTrait` clauses on trait associated items.
// See comment on `requires_default_supertraits` for more details.
if !icx.lowerer().requires_default_supertraits(trait_bounds, trait_generics) {
let mut bounds = Vec::new();
let self_ty_where_predicates = (parent, item.generics.predicates);
icx.lowerer().add_default_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 @@ -181,11 +210,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_default_super_traits(
def_id,
&mut bounds,
self_bounds.0,
hir_generics,
self_bounds.1,
);
predicates.extend(bounds);
}

Expand All @@ -210,8 +246,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_default_traits(
&mut bounds,
param_ty,
&[],
Expand Down Expand Up @@ -625,6 +661,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_default_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
Loading