Skip to content

Commit df3a6ab

Browse files
committed
init
1 parent ea37e80 commit df3a6ab

File tree

32 files changed

+470
-108
lines changed

32 files changed

+470
-108
lines changed

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ declare_features! (
197197
(internal, compiler_builtins, "1.13.0", None),
198198
/// Allows writing custom MIR
199199
(internal, custom_mir, "1.65.0", None),
200+
/// Allows using bunch of default auto traits
201+
(unstable, default_auto_traits, "CURRENT_RUSTC_VERSION", None),
200202
/// Outputs useful `assert!` messages
201203
(unstable, generic_assert, "1.63.0", None),
202204
/// Allows using the `rust-intrinsic`'s "ABI".

compiler/rustc_hir/src/lang_items.rs

+12
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ impl LanguageItems {
4747
.enumerate()
4848
.filter_map(|(i, id)| id.map(|id| (LangItem::from_u32(i as u32).unwrap(), id)))
4949
}
50+
51+
pub fn is_default_trait(&self, def_id: DefId) -> bool {
52+
DEFAULT_TRAITS
53+
.iter()
54+
.find(|&&default_trait| self.get(default_trait) == Some(def_id))
55+
.is_some()
56+
}
5057
}
5158

5259
// The actual lang items defined come at the end of this file in one handy table.
@@ -139,6 +146,8 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
139146

140147
language_item_table! {
141148
// Variant name, Name, Getter method name, Target Generic requirements;
149+
SyncDrop, sym::sync_drop, sync_drop_trait, Target::Trait, GenericRequirement::None;
150+
Leak, sym::leak, leak_trait, Target::Trait, GenericRequirement::None;
142151
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
143152
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
144153
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
@@ -349,6 +358,9 @@ pub enum GenericRequirement {
349358
Exact(usize),
350359
}
351360

361+
pub static DEFAULT_TRAITS: &'static [LangItem] =
362+
&[LangItem::Sized, LangItem::Leak, LangItem::SyncDrop];
363+
352364
pub static FN_TRAITS: &'static [LangItem] = &[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
353365

354366
pub static OPERATORS: &'static [LangItem] = &[

compiler/rustc_hir/src/weak_lang_items.rs

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ macro_rules! weak_lang_items {
2424
}
2525

2626
weak_lang_items! {
27+
SyncDrop, sync_drop;
28+
Leak, leak;
2729
PanicImpl, rust_begin_unwind;
2830
EhPersonality, rust_eh_personality;
2931
EhCatchTypeinfo, rust_eh_catch_typeinfo;

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+69-39
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,60 @@ use crate::bounds::Bounds;
1616
use crate::errors;
1717

1818
impl<'tcx> dyn AstConv<'tcx> + '_ {
19-
/// Sets `implicitly_sized` to true on `Bounds` if necessary
20-
pub(crate) fn add_implicitly_sized(
19+
/// Sets Sized or default_auto_traits to true on `Bounds` if necessary
20+
pub(crate) fn add_implicit_traits(
2121
&self,
2222
bounds: &mut Bounds<'tcx>,
2323
self_ty: Ty<'tcx>,
2424
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
2525
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
2626
span: Span,
27+
) {
28+
hir::lang_items::DEFAULT_TRAITS.iter().for_each(|default_trait| {
29+
self.add_implicit_trait(
30+
*default_trait,
31+
bounds,
32+
self_ty,
33+
ast_bounds,
34+
self_ty_where_predicates,
35+
span,
36+
);
37+
});
38+
}
39+
40+
pub(crate) fn add_implicit_trait(
41+
&self,
42+
trait_: hir::LangItem,
43+
bounds: &mut Bounds<'tcx>,
44+
self_ty: Ty<'tcx>,
45+
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
46+
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
47+
span: Span,
2748
) {
2849
let tcx = self.tcx();
29-
let sized_def_id = tcx.lang_items().sized_trait();
30-
let mut seen_negative_sized_bound = false;
31-
let mut seen_positive_sized_bound = false;
50+
let trait_id = tcx.lang_items().get(trait_);
51+
52+
if self.check_for_implicit_trait(trait_id, ast_bounds, self_ty_where_predicates)
53+
&& (trait_ == hir::LangItem::Sized || tcx.features().default_auto_traits)
54+
{
55+
// There was no `?Trait` or `!Trait` bound;
56+
// add `Trait` if it's available.
57+
bounds.push_lang_item_trait(tcx, self_ty, trait_, span);
58+
}
59+
}
60+
61+
fn check_for_implicit_trait(
62+
&self,
63+
trait_def_id: Option<DefId>,
64+
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
65+
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
66+
) -> bool {
67+
let Some(trait_def_id) = trait_def_id else {
68+
return false;
69+
};
70+
let tcx = self.tcx();
71+
let mut seen_negative_bound = false;
72+
let mut seen_positive_bound = false;
3273

3374
// Try to find an unbound in bounds.
3475
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
@@ -40,17 +81,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
4081
match modifier {
4182
hir::TraitBoundModifier::Maybe => unbounds.push(ptr),
4283
hir::TraitBoundModifier::Negative => {
43-
if let Some(sized_def_id) = sized_def_id
44-
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
45-
{
46-
seen_negative_sized_bound = true;
84+
if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
85+
seen_negative_bound = true;
4786
}
4887
}
4988
hir::TraitBoundModifier::None => {
50-
if let Some(sized_def_id) = sized_def_id
51-
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
52-
{
53-
seen_positive_sized_bound = true;
89+
if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
90+
seen_positive_bound = true;
5491
}
5592
}
5693
_ => {}
@@ -68,36 +105,29 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
68105
}
69106
}
70107

71-
if unbounds.len() > 1 {
72-
tcx.dcx().emit_err(errors::MultipleRelaxedDefaultBounds {
73-
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
74-
});
75-
}
76-
77-
let mut seen_sized_unbound = false;
108+
let mut seen_unbound = false;
78109
for unbound in unbounds {
79-
if let Some(sized_def_id) = sized_def_id
80-
&& unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
81-
{
82-
seen_sized_unbound = true;
83-
continue;
110+
let unbound_def_id = unbound.trait_ref.trait_def_id();
111+
if unbound_def_id == Some(trait_def_id) {
112+
seen_unbound = true;
84113
}
85-
// There was a `?Trait` bound, but it was not `?Sized`; warn.
86-
tcx.dcx().span_warn(
87-
unbound.span,
88-
"relaxing a default bound only does something for `?Sized`; \
89-
all other traits are not bound by default",
90-
);
91-
}
92114

93-
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
94-
// There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
95-
// we don't need to do anything.
96-
} else if sized_def_id.is_some() {
97-
// There was no `?Sized`, `!Sized` or explicit `Sized` bound;
98-
// add `Sized` if it's available.
99-
bounds.push_sized(tcx, self_ty, span);
115+
let emit_relax_err = || {
116+
tcx.dcx().span_warn(
117+
unbound.span,
118+
"relaxing a default bound only does something for `?Sized` and `default_auto_traits`; \
119+
all other traits are not bound by default",
120+
);
121+
};
122+
123+
match unbound_def_id {
124+
Some(def_id) if !tcx.lang_items().is_default_trait(def_id) => emit_relax_err(),
125+
None => emit_relax_err(),
126+
_ => {}
127+
}
100128
}
129+
130+
!(seen_unbound || seen_negative_bound || seen_positive_bound)
101131
}
102132

103133
/// This helper takes a *converted* parameter type (`param_ty`)

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
5353
potential_assoc_types.extend(cur_potential_assoc_types);
5454
}
5555
}
56+
// FIXME: support polarity for trait objects
57+
if tcx.features().default_auto_traits {
58+
hir::lang_items::DEFAULT_TRAITS.iter().for_each(|default_trait| {
59+
if *default_trait != hir::LangItem::Sized {
60+
bounds.push_lang_item_trait(tcx, dummy_self, *default_trait, span);
61+
}
62+
});
63+
}
5664

5765
let mut trait_bounds = vec![];
5866
let mut projection_bounds = vec![];

compiler/rustc_hir_analysis/src/bounds.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,24 @@ impl<'tcx> Bounds<'tcx> {
7676
));
7777
}
7878

79-
pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
80-
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
81-
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
82-
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
83-
self.clauses.insert(0, (trait_ref.to_predicate(tcx), span));
79+
pub fn push_lang_item_trait(
80+
&mut self,
81+
tcx: TyCtxt<'tcx>,
82+
ty: Ty<'tcx>,
83+
lang_item: LangItem,
84+
span: Span,
85+
) {
86+
assert_eq!(lang_item.target(), rustc_hir::Target::Trait);
87+
let Some(trait_def_id) = tcx.lang_items().get(lang_item) else {
88+
return;
89+
};
90+
let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]);
91+
if lang_item == LangItem::Sized {
92+
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
93+
self.clauses.insert(0, (trait_ref.to_predicate(tcx), span));
94+
} else {
95+
self.clauses.push((trait_ref.to_predicate(tcx), span));
96+
}
8497
}
8598

8699
pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {

compiler/rustc_hir_analysis/src/check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,8 @@ fn bounds_from_generic_predicates<'tcx>(
316316
ty::ClauseKind::Trait(trait_predicate) => {
317317
let entry = types.entry(trait_predicate.self_ty()).or_default();
318318
let def_id = trait_predicate.def_id();
319-
if Some(def_id) != tcx.lang_items().sized_trait() {
320-
// Type params are `Sized` by default, do not add that restriction to the list
319+
if !tcx.lang_items().is_default_trait(def_id) {
320+
// Do not add that restriction to the list
321321
// if it is a positive requirement.
322322
entry.push(trait_predicate.def_id());
323323
}

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn associated_type_bounds<'tcx>(
2929
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
3030
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
3131
// Associated types are implicitly sized unless a `?Sized` bound is found
32-
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
32+
icx.astconv().add_implicit_traits(&mut bounds, item_ty, ast_bounds, None, span);
3333

3434
let trait_def_id = tcx.local_parent(assoc_item_def_id);
3535
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
@@ -68,7 +68,7 @@ fn opaque_type_bounds<'tcx>(
6868
let icx = ItemCtxt::new(tcx, opaque_def_id);
6969
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
7070
// Opaque types are implicitly sized unless a `?Sized` bound is found
71-
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
71+
icx.astconv().add_implicit_traits(&mut bounds, item_ty, ast_bounds, None, span);
7272
debug!(?bounds);
7373

7474
tcx.arena.alloc_from_iter(bounds.clauses())

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
146146

147147
ItemKind::Trait(_, _, generics, self_bounds, ..)
148148
| ItemKind::TraitAlias(generics, self_bounds) => {
149-
is_trait = Some(self_bounds);
149+
is_trait = Some((self_bounds, item.span));
150150
generics
151151
}
152152
ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
@@ -169,11 +169,27 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
169169
// on a trait we must also consider the bounds that follow the trait's name,
170170
// like `trait Foo: A + B + C`.
171171
if let Some(self_bounds) = is_trait {
172-
predicates.extend(
173-
icx.astconv()
174-
.compute_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
175-
.clauses(),
176-
);
172+
let mut bounds =
173+
icx.astconv().compute_bounds(tcx.types.self_param, self_bounds.0, PredicateFilter::All);
174+
175+
let sized_trait = tcx.lang_items().sized_trait();
176+
let trait_def_id = def_id.to_def_id();
177+
hir::lang_items::DEFAULT_TRAITS.iter().for_each(|default_trait| {
178+
if *default_trait != hir::LangItem::Sized
179+
&& (Some(trait_def_id) == sized_trait
180+
|| !tcx.lang_items().is_default_trait(def_id.to_def_id()))
181+
{
182+
icx.astconv().add_implicit_trait(
183+
*default_trait,
184+
&mut bounds,
185+
tcx.types.self_param,
186+
self_bounds.0,
187+
None,
188+
self_bounds.1,
189+
);
190+
}
191+
});
192+
predicates.extend(bounds.clauses());
177193
}
178194

179195
// In default impls, we can assume that the self type implements
@@ -199,7 +215,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
199215
let param_ty = icx.astconv().hir_id_to_bound_ty(param.hir_id);
200216
let mut bounds = Bounds::default();
201217
// Params are implicitly sized unless a `?Sized` bound is found
202-
icx.astconv().add_implicitly_sized(
218+
icx.astconv().add_implicit_traits(
203219
&mut bounds,
204220
param_ty,
205221
&[],

0 commit comments

Comments
 (0)