Skip to content

Commit 6a540bd

Browse files
committed
Auto merge of #86502 - JohnTitor:rollup-wge0f3x, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #83739 (Account for bad placeholder errors on consts/statics with trait objects) - #85637 (document PartialEq, PartialOrd, Ord requirements more explicitly) - #86152 (Lazify is_really_default condition in the RustdocGUI bootstrap step) - #86156 (Fix a bug in the linkchecker) - #86427 (Updated release note) - #86452 (fix panic-safety in specialized Zip::next_back) - #86484 (Do not set depth to 0 in fully_expand_fragment) - #86491 (expand: Move some more derive logic to rustc_builtin_macros) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 03b845a + 8b9e138 commit 6a540bd

File tree

26 files changed

+291
-107
lines changed

26 files changed

+291
-107
lines changed

Diff for: Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ dependencies = [
179179
"libc",
180180
"merge",
181181
"num_cpus",
182+
"once_cell",
182183
"opener",
183184
"pretty_assertions",
184185
"serde",

Diff for: RELEASES.md

+2
Original file line numberDiff line numberDiff line change
@@ -1749,6 +1749,7 @@ Language
17491749
- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
17501750
that you can create an enum that has the exact layout and ABI of the type
17511751
it contains.
1752+
- [You can now use outer attribute procedural macros on inline modules.][64273]
17521753
- [There are some *syntax-only* changes:][67131]
17531754
- `default` is syntactically allowed before items in `trait` definitions.
17541755
- Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
@@ -1810,6 +1811,7 @@ Compatibility Notes
18101811
[67935]: https://github.com/rust-lang/rust/pull/67935/
18111812
[68339]: https://github.com/rust-lang/rust/pull/68339/
18121813
[68122]: https://github.com/rust-lang/rust/pull/68122/
1814+
[64273]: https://github.com/rust-lang/rust/pull/64273/
18131815
[67712]: https://github.com/rust-lang/rust/pull/67712/
18141816
[67887]: https://github.com/rust-lang/rust/pull/67887/
18151817
[67131]: https://github.com/rust-lang/rust/pull/67131/

Diff for: compiler/rustc_builtin_macros/src/cfg_eval.rs

+29-30
Original file line numberDiff line numberDiff line change
@@ -24,61 +24,60 @@ crate fn expand(
2424
annotatable: Annotatable,
2525
) -> Vec<Annotatable> {
2626
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
27-
cfg_eval(ecx, annotatable)
27+
vec![cfg_eval(ecx, annotatable)]
2828
}
2929

30-
crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> {
31-
let mut visitor = CfgEval {
30+
crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable {
31+
CfgEval {
3232
cfg: &mut StripUnconfigured {
3333
sess: ecx.sess,
3434
features: ecx.ecfg.features,
3535
config_tokens: true,
3636
},
37-
};
38-
let annotatable = visitor.configure_annotatable(annotatable);
39-
vec![annotatable]
37+
}
38+
.configure_annotatable(annotatable)
39+
// Since the item itself has already been configured by the `InvocationCollector`,
40+
// we know that fold result vector will contain exactly one element.
41+
.unwrap()
4042
}
4143

4244
struct CfgEval<'a, 'b> {
4345
cfg: &'a mut StripUnconfigured<'b>,
4446
}
4547

46-
fn flat_map_annotatable(vis: &mut impl MutVisitor, annotatable: Annotatable) -> Annotatable {
47-
// Since the item itself has already been configured by the InvocationCollector,
48-
// we know that fold result vector will contain exactly one element
48+
fn flat_map_annotatable(
49+
vis: &mut impl MutVisitor,
50+
annotatable: Annotatable,
51+
) -> Option<Annotatable> {
4952
match annotatable {
50-
Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()),
53+
Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item),
5154
Annotatable::TraitItem(item) => {
52-
Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap())
55+
vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem)
5356
}
5457
Annotatable::ImplItem(item) => {
55-
Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap())
58+
vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem)
5659
}
5760
Annotatable::ForeignItem(item) => {
58-
Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap())
61+
vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem)
5962
}
6063
Annotatable::Stmt(stmt) => {
61-
Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap()))
64+
vis.flat_map_stmt(stmt.into_inner()).pop().map(P).map(Annotatable::Stmt)
6265
}
63-
Annotatable::Expr(mut expr) => Annotatable::Expr({
66+
Annotatable::Expr(mut expr) => {
6467
vis.visit_expr(&mut expr);
65-
expr
66-
}),
67-
Annotatable::Arm(arm) => Annotatable::Arm(vis.flat_map_arm(arm).pop().unwrap()),
68-
Annotatable::ExprField(field) => {
69-
Annotatable::ExprField(vis.flat_map_expr_field(field).pop().unwrap())
68+
Some(Annotatable::Expr(expr))
7069
}
71-
Annotatable::PatField(fp) => {
72-
Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap())
70+
Annotatable::Arm(arm) => vis.flat_map_arm(arm).pop().map(Annotatable::Arm),
71+
Annotatable::ExprField(field) => {
72+
vis.flat_map_expr_field(field).pop().map(Annotatable::ExprField)
7373
}
74+
Annotatable::PatField(fp) => vis.flat_map_pat_field(fp).pop().map(Annotatable::PatField),
7475
Annotatable::GenericParam(param) => {
75-
Annotatable::GenericParam(vis.flat_map_generic_param(param).pop().unwrap())
76-
}
77-
Annotatable::Param(param) => Annotatable::Param(vis.flat_map_param(param).pop().unwrap()),
78-
Annotatable::FieldDef(sf) => {
79-
Annotatable::FieldDef(vis.flat_map_field_def(sf).pop().unwrap())
76+
vis.flat_map_generic_param(param).pop().map(Annotatable::GenericParam)
8077
}
81-
Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()),
78+
Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
79+
Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
80+
Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
8281
}
8382
}
8483

@@ -123,11 +122,11 @@ impl CfgEval<'_, '_> {
123122
self.cfg.configure(node)
124123
}
125124

126-
pub fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Annotatable {
125+
fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Annotatable> {
127126
// Tokenizing and re-parsing the `Annotatable` can have a significant
128127
// performance impact, so try to avoid it if possible
129128
if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) {
130-
return annotatable;
129+
return Some(annotatable);
131130
}
132131

133132
// The majority of parsed attribute targets will never need to have early cfg-expansion

Diff for: compiler/rustc_builtin_macros/src/derive.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ impl MultiItemModifier for Expander {
2626
return ExpandResult::Ready(vec![item]);
2727
}
2828

29+
let item = cfg_eval(ecx, item);
30+
2931
let result =
3032
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
3133
let template =
@@ -54,12 +56,12 @@ impl MultiItemModifier for Expander {
5456
report_path_args(sess, &meta);
5557
meta.path
5658
})
57-
.map(|path| (path, None))
59+
.map(|path| (path, item.clone(), None))
5860
.collect()
5961
});
6062

6163
match result {
62-
Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
64+
Ok(()) => ExpandResult::Ready(vec![item]),
6365
Err(Indeterminate) => ExpandResult::Retry(item),
6466
}
6567
}

Diff for: compiler/rustc_expand/src/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ impl SyntaxExtension {
835835
/// Error type that denotes indeterminacy.
836836
pub struct Indeterminate;
837837

838-
pub type DeriveResolutions = Vec<(ast::Path, Option<Lrc<SyntaxExtension>>)>;
838+
pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>;
839839

840840
pub trait ResolverExpand {
841841
fn next_node_id(&mut self) -> NodeId;

Diff for: compiler/rustc_expand/src/expand.rs

+3-29
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
427427
pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
428428
let orig_expansion_data = self.cx.current_expansion.clone();
429429
let orig_force_mode = self.cx.force_mode;
430-
self.cx.current_expansion.depth = 0;
431430

432431
// Collect all macro invocations and replace them with placeholders.
433432
let (mut fragment_with_placeholders, mut invocations) =
@@ -488,6 +487,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
488487
};
489488

490489
let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
490+
let depth = depth - orig_expansion_data.depth;
491491
self.cx.current_expansion = invoc.expansion_data.clone();
492492
self.cx.force_mode = force;
493493

@@ -500,42 +500,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
500500
.resolver
501501
.take_derive_resolutions(expn_id)
502502
.map(|derives| {
503-
enum AnnotatableRef<'a> {
504-
Item(&'a P<ast::Item>),
505-
Stmt(&'a ast::Stmt),
506-
}
507-
let item = match &fragment {
508-
AstFragment::Items(items) => match &items[..] {
509-
[item] => AnnotatableRef::Item(item),
510-
_ => unreachable!(),
511-
},
512-
AstFragment::Stmts(stmts) => match &stmts[..] {
513-
[stmt] => AnnotatableRef::Stmt(stmt),
514-
_ => unreachable!(),
515-
},
516-
_ => unreachable!(),
517-
};
518-
519503
derive_invocations.reserve(derives.len());
520504
derives
521505
.into_iter()
522-
.map(|(path, _exts)| {
506+
.map(|(path, item, _exts)| {
523507
// FIXME: Consider using the derive resolutions (`_exts`)
524508
// instead of enqueuing the derives to be resolved again later.
525509
let expn_id = ExpnId::fresh(None);
526510
derive_invocations.push((
527511
Invocation {
528-
kind: InvocationKind::Derive {
529-
path,
530-
item: match item {
531-
AnnotatableRef::Item(item) => {
532-
Annotatable::Item(item.clone())
533-
}
534-
AnnotatableRef::Stmt(stmt) => {
535-
Annotatable::Stmt(P(stmt.clone()))
536-
}
537-
},
538-
},
512+
kind: InvocationKind::Derive { path, item },
539513
fragment_kind,
540514
expansion_data: ExpansionData {
541515
id: expn_id,

Diff for: compiler/rustc_resolve/src/macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
380380
has_derive_copy: false,
381381
});
382382
let parent_scope = self.invocation_parent_scopes[&expn_id];
383-
for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
383+
for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
384384
if opt_ext.is_none() {
385385
*opt_ext = Some(
386386
match self.resolve_macro_path(

Diff for: compiler/rustc_typeck/src/collect.rs

+8
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,14 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
813813
match it.kind {
814814
hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
815815
hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
816+
hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
817+
// (#75889): Account for `const C: dyn Fn() -> _ = "";`
818+
if let hir::TyKind::TraitObject(..) = ty.kind {
819+
let mut visitor = PlaceholderHirTyCollector::default();
820+
visitor.visit_item(it);
821+
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
822+
}
823+
}
816824
_ => (),
817825
}
818826
}

Diff for: library/core/src/cmp.rs

+64-25
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,25 @@ use self::Ordering::*;
2727
/// Trait for equality comparisons which are [partial equivalence
2828
/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
2929
///
30+
/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
31+
/// We use the easier-to-read infix notation in the remainder of this documentation.
32+
///
3033
/// This trait allows for partial equality, for types that do not have a full
3134
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
3235
/// so floating point types implement `PartialEq` but not [`trait@Eq`].
3336
///
34-
/// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
35-
/// `C`):
37+
/// Implementations must ensure that `eq` and `ne` are consistent with each other:
38+
///
39+
/// - `a != b` if and only if `!(a == b)`
40+
/// (ensured by the default implementation).
41+
///
42+
/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
43+
/// be consistent with `PartialEq` (see the documentation of those traits for the exact
44+
/// requirememts). It's easy to accidentally make them disagree by deriving some of the traits and
45+
/// manually implementing others.
46+
///
47+
/// The equality relation `==` must satisfy the following conditions
48+
/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
3649
///
3750
/// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
3851
/// implies `b == a`**; and
@@ -53,15 +66,6 @@ use self::Ordering::*;
5366
///
5467
/// ## How can I implement `PartialEq`?
5568
///
56-
/// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined
57-
/// in terms of it by default. Any manual implementation of [`ne`] *must* respect
58-
/// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and
59-
/// only if `a != b`.
60-
///
61-
/// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with
62-
/// each other. It's easy to accidentally make them disagree by deriving some
63-
/// of the traits and manually implementing others.
64-
///
6569
/// An example implementation for a domain in which two books are considered
6670
/// the same book if their ISBN matches, even if the formats differ:
6771
///
@@ -631,10 +635,25 @@ impl<T: Clone> Clone for Reverse<T> {
631635

632636
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
633637
///
634-
/// An order is a total order if it is (for all `a`, `b` and `c`):
638+
/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
639+
/// `max`, `min`, and `clamp` are consistent with `cmp`:
640+
///
641+
/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
642+
/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
643+
/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
644+
/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
645+
/// (ensured by the default implementation).
646+
///
647+
/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
648+
/// deriving some of the traits and manually implementing others.
649+
///
650+
/// ## Corollaries
651+
///
652+
/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
653+
/// This means that for all `a`, `b` and `c`:
635654
///
636-
/// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
637-
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
655+
/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
656+
/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
638657
///
639658
/// ## Derivable
640659
///
@@ -659,12 +678,6 @@ impl<T: Clone> Clone for Reverse<T> {
659678
/// Then you must define an implementation for [`cmp`]. You may find it useful to use
660679
/// [`cmp`] on your type's fields.
661680
///
662-
/// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must*
663-
/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if
664-
/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for
665-
/// all `a` and `b`. It's easy to accidentally make them disagree by
666-
/// deriving some of the traits and manually implementing others.
667-
///
668681
/// Here's an example where you want to sort people by height only, disregarding `id`
669682
/// and `name`:
670683
///
@@ -824,15 +837,45 @@ impl PartialOrd for Ordering {
824837

825838
/// Trait for values that can be compared for a sort-order.
826839
///
840+
/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
841+
/// the `<`, `<=`, `>`, and `>=` operators, respectively.
842+
///
843+
/// The methods of this trait must be consistent with each other and with those of `PartialEq` in
844+
/// the following sense:
845+
///
846+
/// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
847+
/// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
848+
/// (ensured by the default implementation).
849+
/// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
850+
/// (ensured by the default implementation).
851+
/// - `a <= b` if and only if `a < b || a == b`
852+
/// (ensured by the default implementation).
853+
/// - `a >= b` if and only if `a > b || a == b`
854+
/// (ensured by the default implementation).
855+
/// - `a != b` if and only if `!(a == b)` (already part of `PartialEq`).
856+
///
857+
/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
858+
/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
859+
/// easy to accidentally make them disagree by deriving some of the traits and manually
860+
/// implementing others.
861+
///
827862
/// The comparison must satisfy, for all `a`, `b` and `c`:
828863
///
829-
/// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
830864
/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
865+
/// - duality: `a < b` if and only if `b > a`.
831866
///
832867
/// Note that these requirements mean that the trait itself must be implemented symmetrically and
833868
/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
834869
/// PartialOrd<V>`.
835870
///
871+
/// ## Corollaries
872+
///
873+
/// The following corollaries follow from the above requirements:
874+
///
875+
/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
876+
/// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
877+
/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
878+
///
836879
/// ## Derivable
837880
///
838881
/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
@@ -850,10 +893,6 @@ impl PartialOrd for Ordering {
850893
///
851894
/// `PartialOrd` requires your type to be [`PartialEq`].
852895
///
853-
/// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's
854-
/// easy to accidentally make them disagree by deriving some of the traits and manually
855-
/// implementing others.
856-
///
857896
/// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
858897
///
859898
/// ```

0 commit comments

Comments
 (0)