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

Rollup of 8 pull requests #86502

Merged
merged 23 commits into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1cfc187
document PartialEq, PartialOrd, Ord requirements more explicitly
RalfJung May 24, 2021
a7abd13
make Ord doc style consistent with the other two; explain which prope…
RalfJung May 27, 2021
7dd2577
Fix linkchecker redirection tests.
ehuss Jun 8, 2021
bbd0532
Test the linkchecker itself.
ehuss Jun 8, 2021
dbc8a1c
Change the linkchecker self-tests to validate more output.
ehuss Jun 8, 2021
1e9f0b3
linkchecker: Fix bug where fragment errors printed the wrong path.
ehuss Jun 9, 2021
052d77e
Account for bad placeholder errors on consts/statics with trait objects
JohnTitor Jun 10, 2021
45675f3
wording
RalfJung Jun 15, 2021
bde9570
Lazify is_really_default condition in the RustdocGUI bootstrap step
the8472 Jun 8, 2021
87fb7cb
Updated release note
Rustin170506 Jun 18, 2021
8b51854
fix panic-safety in specialized Zip::next_back
the8472 Jun 19, 2021
b4734b7
disable test on platforms that don't support unwinding
the8472 Jun 20, 2021
3f0729f
expand: Move some more derive logic to `rustc_builtin_macros`
petrochenkov Jun 20, 2021
d9fd5ea
cfg_eval: Replace multiple `unwrap`s with a single `unwrap`
petrochenkov Jun 20, 2021
37d0d27
Do not set depth to 0 in fully_expand_fragment
fee1-dead Jun 20, 2021
1a1909a
Rollup merge of #83739 - JohnTitor:issue-75889, r=estebank
JohnTitor Jun 21, 2021
e6732e0
Rollup merge of #85637 - RalfJung:partial-ord, r=m-ou-se
JohnTitor Jun 21, 2021
e7a4f1e
Rollup merge of #86152 - the8472:lazify-npm-queries, r=Mark-Simulacrum
JohnTitor Jun 21, 2021
e435e32
Rollup merge of #86156 - ehuss:linkchecker-fixes, r=Mark-Simulacrum
JohnTitor Jun 21, 2021
13b0f1a
Rollup merge of #86427 - hi-rustin:rustin-patch-release-note, r=Mark-…
JohnTitor Jun 21, 2021
504c378
Rollup merge of #86452 - the8472:fix-zip-drop-safety, r=m-ou-se
JohnTitor Jun 21, 2021
e5ecded
Rollup merge of #86484 - fee1-dead:builtin-macro-recursion, r=petroch…
JohnTitor Jun 21, 2021
8b9e138
Rollup merge of #86491 - petrochenkov:derefact, r=Aaron1011
JohnTitor Jun 21, 2021
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ dependencies = [
"libc",
"merge",
"num_cpus",
"once_cell",
"opener",
"pretty_assertions",
"serde",
Expand Down
2 changes: 2 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1749,6 +1749,7 @@ Language
- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
that you can create an enum that has the exact layout and ABI of the type
it contains.
- [You can now use outer attribute procedural macros on inline modules.][64273]
- [There are some *syntax-only* changes:][67131]
- `default` is syntactically allowed before items in `trait` definitions.
- Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
Expand Down Expand Up @@ -1810,6 +1811,7 @@ Compatibility Notes
[67935]: https://github.com/rust-lang/rust/pull/67935/
[68339]: https://github.com/rust-lang/rust/pull/68339/
[68122]: https://github.com/rust-lang/rust/pull/68122/
[64273]: https://github.com/rust-lang/rust/pull/64273/
[67712]: https://github.com/rust-lang/rust/pull/67712/
[67887]: https://github.com/rust-lang/rust/pull/67887/
[67131]: https://github.com/rust-lang/rust/pull/67131/
Expand Down
59 changes: 29 additions & 30 deletions compiler/rustc_builtin_macros/src/cfg_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,61 +24,60 @@ crate fn expand(
annotatable: Annotatable,
) -> Vec<Annotatable> {
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
cfg_eval(ecx, annotatable)
vec![cfg_eval(ecx, annotatable)]
}

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

struct CfgEval<'a, 'b> {
cfg: &'a mut StripUnconfigured<'b>,
}

fn flat_map_annotatable(vis: &mut impl MutVisitor, annotatable: Annotatable) -> Annotatable {
// Since the item itself has already been configured by the InvocationCollector,
// we know that fold result vector will contain exactly one element
fn flat_map_annotatable(
vis: &mut impl MutVisitor,
annotatable: Annotatable,
) -> Option<Annotatable> {
match annotatable {
Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()),
Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item),
Annotatable::TraitItem(item) => {
Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap())
vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem)
}
Annotatable::ImplItem(item) => {
Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap())
vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem)
}
Annotatable::ForeignItem(item) => {
Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap())
vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem)
}
Annotatable::Stmt(stmt) => {
Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap()))
vis.flat_map_stmt(stmt.into_inner()).pop().map(P).map(Annotatable::Stmt)
}
Annotatable::Expr(mut expr) => Annotatable::Expr({
Annotatable::Expr(mut expr) => {
vis.visit_expr(&mut expr);
expr
}),
Annotatable::Arm(arm) => Annotatable::Arm(vis.flat_map_arm(arm).pop().unwrap()),
Annotatable::ExprField(field) => {
Annotatable::ExprField(vis.flat_map_expr_field(field).pop().unwrap())
Some(Annotatable::Expr(expr))
}
Annotatable::PatField(fp) => {
Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap())
Annotatable::Arm(arm) => vis.flat_map_arm(arm).pop().map(Annotatable::Arm),
Annotatable::ExprField(field) => {
vis.flat_map_expr_field(field).pop().map(Annotatable::ExprField)
}
Annotatable::PatField(fp) => vis.flat_map_pat_field(fp).pop().map(Annotatable::PatField),
Annotatable::GenericParam(param) => {
Annotatable::GenericParam(vis.flat_map_generic_param(param).pop().unwrap())
}
Annotatable::Param(param) => Annotatable::Param(vis.flat_map_param(param).pop().unwrap()),
Annotatable::FieldDef(sf) => {
Annotatable::FieldDef(vis.flat_map_field_def(sf).pop().unwrap())
vis.flat_map_generic_param(param).pop().map(Annotatable::GenericParam)
}
Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()),
Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
}
}

Expand Down Expand Up @@ -123,11 +122,11 @@ impl CfgEval<'_, '_> {
self.cfg.configure(node)
}

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

// The majority of parsed attribute targets will never need to have early cfg-expansion
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_builtin_macros/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ impl MultiItemModifier for Expander {
return ExpandResult::Ready(vec![item]);
}

let item = cfg_eval(ecx, item);

let result =
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
let template =
Expand Down Expand Up @@ -54,12 +56,12 @@ impl MultiItemModifier for Expander {
report_path_args(sess, &meta);
meta.path
})
.map(|path| (path, None))
.map(|path| (path, item.clone(), None))
.collect()
});

match result {
Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
Ok(()) => ExpandResult::Ready(vec![item]),
Err(Indeterminate) => ExpandResult::Retry(item),
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ impl SyntaxExtension {
/// Error type that denotes indeterminacy.
pub struct Indeterminate;

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

pub trait ResolverExpand {
fn next_node_id(&mut self) -> NodeId;
Expand Down
32 changes: 3 additions & 29 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
let orig_expansion_data = self.cx.current_expansion.clone();
let orig_force_mode = self.cx.force_mode;
self.cx.current_expansion.depth = 0;

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

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

Expand All @@ -500,42 +500,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
.resolver
.take_derive_resolutions(expn_id)
.map(|derives| {
enum AnnotatableRef<'a> {
Item(&'a P<ast::Item>),
Stmt(&'a ast::Stmt),
}
let item = match &fragment {
AstFragment::Items(items) => match &items[..] {
[item] => AnnotatableRef::Item(item),
_ => unreachable!(),
},
AstFragment::Stmts(stmts) => match &stmts[..] {
[stmt] => AnnotatableRef::Stmt(stmt),
_ => unreachable!(),
},
_ => unreachable!(),
};

derive_invocations.reserve(derives.len());
derives
.into_iter()
.map(|(path, _exts)| {
.map(|(path, item, _exts)| {
// FIXME: Consider using the derive resolutions (`_exts`)
// instead of enqueuing the derives to be resolved again later.
let expn_id = ExpnId::fresh(None);
derive_invocations.push((
Invocation {
kind: InvocationKind::Derive {
path,
item: match item {
AnnotatableRef::Item(item) => {
Annotatable::Item(item.clone())
}
AnnotatableRef::Stmt(stmt) => {
Annotatable::Stmt(P(stmt.clone()))
}
},
},
kind: InvocationKind::Derive { path, item },
fragment_kind,
expansion_data: ExpansionData {
id: expn_id,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
has_derive_copy: false,
});
let parent_scope = self.invocation_parent_scopes[&expn_id];
for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
if opt_ext.is_none() {
*opt_ext = Some(
match self.resolve_macro_path(
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,14 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
match it.kind {
hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
// (#75889): Account for `const C: dyn Fn() -> _ = "";`
if let hir::TyKind::TraitObject(..) = ty.kind {
let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_item(it);
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
}
}
_ => (),
}
}
Expand Down
89 changes: 64 additions & 25 deletions library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,25 @@ use self::Ordering::*;
/// Trait for equality comparisons which are [partial equivalence
/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
///
/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
/// We use the easier-to-read infix notation in the remainder of this documentation.
///
/// This trait allows for partial equality, for types that do not have a full
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
/// so floating point types implement `PartialEq` but not [`trait@Eq`].
///
/// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
/// `C`):
/// Implementations must ensure that `eq` and `ne` are consistent with each other:
///
/// - `a != b` if and only if `!(a == b)`
/// (ensured by the default implementation).
///
/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
/// be consistent with `PartialEq` (see the documentation of those traits for the exact
/// requirememts). It's easy to accidentally make them disagree by deriving some of the traits and
/// manually implementing others.
///
/// The equality relation `==` must satisfy the following conditions
/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
///
/// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
/// implies `b == a`**; and
Expand All @@ -53,15 +66,6 @@ use self::Ordering::*;
///
/// ## How can I implement `PartialEq`?
///
/// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined
/// in terms of it by default. Any manual implementation of [`ne`] *must* respect
/// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and
/// only if `a != b`.
///
/// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with
/// each other. It's easy to accidentally make them disagree by deriving some
/// of the traits and manually implementing others.
///
/// An example implementation for a domain in which two books are considered
/// the same book if their ISBN matches, even if the formats differ:
///
Expand Down Expand Up @@ -631,10 +635,25 @@ impl<T: Clone> Clone for Reverse<T> {

/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
///
/// An order is a total order if it is (for all `a`, `b` and `c`):
/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
/// `max`, `min`, and `clamp` are consistent with `cmp`:
///
/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
/// (ensured by the default implementation).
///
/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
/// deriving some of the traits and manually implementing others.
///
/// ## Corollaries
///
/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
/// This means that for all `a`, `b` and `c`:
///
/// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
/// ## Derivable
///
Expand All @@ -659,12 +678,6 @@ impl<T: Clone> Clone for Reverse<T> {
/// Then you must define an implementation for [`cmp`]. You may find it useful to use
/// [`cmp`] on your type's fields.
///
/// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must*
/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if
/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for
/// all `a` and `b`. It's easy to accidentally make them disagree by
/// deriving some of the traits and manually implementing others.
///
/// Here's an example where you want to sort people by height only, disregarding `id`
/// and `name`:
///
Expand Down Expand Up @@ -824,15 +837,45 @@ impl PartialOrd for Ordering {

/// Trait for values that can be compared for a sort-order.
///
/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
/// the `<`, `<=`, `>`, and `>=` operators, respectively.
///
/// The methods of this trait must be consistent with each other and with those of `PartialEq` in
/// the following sense:
///
/// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
/// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
/// (ensured by the default implementation).
/// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
/// (ensured by the default implementation).
/// - `a <= b` if and only if `a < b || a == b`
/// (ensured by the default implementation).
/// - `a >= b` if and only if `a > b || a == b`
/// (ensured by the default implementation).
/// - `a != b` if and only if `!(a == b)` (already part of `PartialEq`).
///
/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
/// easy to accidentally make them disagree by deriving some of the traits and manually
/// implementing others.
///
/// The comparison must satisfy, for all `a`, `b` and `c`:
///
/// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
/// - duality: `a < b` if and only if `b > a`.
///
/// Note that these requirements mean that the trait itself must be implemented symmetrically and
/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
/// PartialOrd<V>`.
///
/// ## Corollaries
///
/// The following corollaries follow from the above requirements:
///
/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
/// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
///
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
Expand All @@ -850,10 +893,6 @@ impl PartialOrd for Ordering {
///
/// `PartialOrd` requires your type to be [`PartialEq`].
///
/// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's
/// easy to accidentally make them disagree by deriving some of the traits and manually
/// implementing others.
///
/// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
///
/// ```
Expand Down
Loading