Auto merge of #116236 - dtolnay:builtinmacrocomment, r=cjgillot
Modernize rustc_builtin_macros generics helpers - Rustfmt-compatible formatting for the code snippets in comments - Eliminate an _"Extra scope required"_ obsoleted by NLL
This commit is contained in:
commit
c716f180e8
1 changed files with 111 additions and 93 deletions
|
@ -37,8 +37,9 @@
|
||||||
//! following snippet
|
//! following snippet
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # #![allow(dead_code)]
|
//! struct A {
|
||||||
//! struct A { x : i32 }
|
//! x: i32,
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! struct B(i32);
|
//! struct B(i32);
|
||||||
//!
|
//!
|
||||||
|
@ -74,6 +75,7 @@
|
||||||
//! trait PartialEq {
|
//! trait PartialEq {
|
||||||
//! fn eq(&self, other: &Self) -> bool;
|
//! fn eq(&self, other: &Self) -> bool;
|
||||||
//! }
|
//! }
|
||||||
|
//!
|
||||||
//! impl PartialEq for i32 {
|
//! impl PartialEq for i32 {
|
||||||
//! fn eq(&self, other: &i32) -> bool {
|
//! fn eq(&self, other: &i32) -> bool {
|
||||||
//! *self == *other
|
//! *self == *other
|
||||||
|
@ -90,22 +92,22 @@
|
||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
//! Struct(vec![FieldInfo {
|
//! Struct(vec![FieldInfo {
|
||||||
//! span: <span of x>
|
//! span: <span of x>,
|
||||||
//! name: Some(<ident of x>),
|
//! name: Some(<ident of x>),
|
||||||
//! self_: <expr for &self.x>,
|
//! self_: <expr for &self.x>,
|
||||||
//! other: vec![<expr for &other.x]
|
//! other: vec![<expr for &other.x>],
|
||||||
//! }])
|
//! }])
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! For the `B` impl, called with `B(a)` and `B(b)`,
|
//! For the `B` impl, called with `B(a)` and `B(b)`,
|
||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
//! Struct(vec![FieldInfo {
|
//! Struct(vec![FieldInfo {
|
||||||
//! span: <span of `i32`>,
|
//! span: <span of i32>,
|
||||||
//! name: None,
|
//! name: None,
|
||||||
//! self_: <expr for &a>
|
//! self_: <expr for &a>,
|
||||||
//! other: vec![<expr for &b>]
|
//! other: vec![<expr for &b>],
|
||||||
//! }])
|
//! }])
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Enums
|
//! ## Enums
|
||||||
|
@ -114,33 +116,42 @@
|
||||||
//! == C0(b)`, the SubstructureFields is
|
//! == C0(b)`, the SubstructureFields is
|
||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
//! EnumMatching(0, <ast::Variant for C0>,
|
//! EnumMatching(
|
||||||
//! vec![FieldInfo {
|
//! 0,
|
||||||
//! span: <span of i32>
|
//! <ast::Variant for C0>,
|
||||||
//! name: None,
|
//! vec![FieldInfo {
|
||||||
//! self_: <expr for &a>,
|
//! span: <span of i32>,
|
||||||
//! other: vec![<expr for &b>]
|
//! name: None,
|
||||||
//! }])
|
//! self_: <expr for &a>,
|
||||||
|
//! other: vec![<expr for &b>],
|
||||||
|
//! }],
|
||||||
|
//! )
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! For `C1 {x}` and `C1 {x}`,
|
//! For `C1 {x}` and `C1 {x}`,
|
||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
//! EnumMatching(1, <ast::Variant for C1>,
|
//! EnumMatching(
|
||||||
//! vec![FieldInfo {
|
//! 1,
|
||||||
//! span: <span of x>
|
//! <ast::Variant for C1>,
|
||||||
//! name: Some(<ident of x>),
|
//! vec![FieldInfo {
|
||||||
//! self_: <expr for &self.x>,
|
//! span: <span of x>,
|
||||||
//! other: vec![<expr for &other.x>]
|
//! name: Some(<ident of x>),
|
||||||
//! }])
|
//! self_: <expr for &self.x>,
|
||||||
|
//! other: vec![<expr for &other.x>],
|
||||||
|
//! }],
|
||||||
|
//! )
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! For the tags,
|
//! For the tags,
|
||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
//! EnumTag(
|
//! EnumTag(
|
||||||
//! &[<ident of self tag>, <ident of other tag>], <expr to combine with>)
|
//! &[<ident of self tag>, <ident of other tag>],
|
||||||
|
//! <expr to combine with>,
|
||||||
|
//! )
|
||||||
//! ```
|
//! ```
|
||||||
|
//!
|
||||||
//! Note that this setup doesn't allow for the brute-force "match every variant
|
//! Note that this setup doesn't allow for the brute-force "match every variant
|
||||||
//! against every other variant" approach, which is bad because it produces a
|
//! against every other variant" approach, which is bad because it produces a
|
||||||
//! quadratic amount of code (see #15375).
|
//! quadratic amount of code (see #15375).
|
||||||
|
@ -154,9 +165,13 @@
|
||||||
//!
|
//!
|
||||||
//! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
|
//! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
|
||||||
//!
|
//!
|
||||||
//! StaticEnum(<ast::EnumDef of C>,
|
//! StaticEnum(
|
||||||
//! vec![(<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
|
//! <ast::EnumDef of C>,
|
||||||
//! (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)]))])
|
//! vec![
|
||||||
|
//! (<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
|
||||||
|
//! (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)])),
|
||||||
|
//! ],
|
||||||
|
//! )
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
pub use StaticFields::*;
|
pub use StaticFields::*;
|
||||||
|
@ -522,7 +537,10 @@ impl<'a> TraitDef<'a> {
|
||||||
/// Given that we are deriving a trait `DerivedTrait` for a type like:
|
/// Given that we are deriving a trait `DerivedTrait` for a type like:
|
||||||
///
|
///
|
||||||
/// ```ignore (only-for-syntax-highlight)
|
/// ```ignore (only-for-syntax-highlight)
|
||||||
/// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait {
|
/// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z>
|
||||||
|
/// where
|
||||||
|
/// C: WhereTrait,
|
||||||
|
/// {
|
||||||
/// a: A,
|
/// a: A,
|
||||||
/// b: B::Item,
|
/// b: B::Item,
|
||||||
/// b1: <B as DeclaredTrait>::Item,
|
/// b1: <B as DeclaredTrait>::Item,
|
||||||
|
@ -535,12 +553,13 @@ impl<'a> TraitDef<'a> {
|
||||||
/// create an impl like:
|
/// create an impl like:
|
||||||
///
|
///
|
||||||
/// ```ignore (only-for-syntax-highlight)
|
/// ```ignore (only-for-syntax-highlight)
|
||||||
/// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where
|
/// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z>
|
||||||
/// C: WhereTrait,
|
/// where
|
||||||
|
/// C: WhereTrait,
|
||||||
/// A: DerivedTrait + B1 + ... + BN,
|
/// A: DerivedTrait + B1 + ... + BN,
|
||||||
/// B: DerivedTrait + B1 + ... + BN,
|
/// B: DerivedTrait + B1 + ... + BN,
|
||||||
/// C: DerivedTrait + B1 + ... + BN,
|
/// C: DerivedTrait + B1 + ... + BN,
|
||||||
/// B::Item: DerivedTrait + B1 + ... + BN,
|
/// B::Item: DerivedTrait + B1 + ... + BN,
|
||||||
/// <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN,
|
/// <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN,
|
||||||
/// ...
|
/// ...
|
||||||
/// {
|
/// {
|
||||||
|
@ -676,65 +695,59 @@ impl<'a> TraitDef<'a> {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
{
|
let ty_param_names: Vec<Symbol> = params
|
||||||
// Extra scope required here so ty_params goes out of scope before params is moved
|
.iter()
|
||||||
|
.filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
|
||||||
|
.map(|ty_param| ty_param.ident.name)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut ty_params = params
|
if !ty_param_names.is_empty() {
|
||||||
.iter()
|
for field_ty in field_tys {
|
||||||
.filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
|
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
|
||||||
.peekable();
|
|
||||||
|
|
||||||
if ty_params.peek().is_some() {
|
for field_ty_param in field_ty_params {
|
||||||
let ty_param_names: Vec<Symbol> =
|
// if we have already handled this type, skip it
|
||||||
ty_params.map(|ty_param| ty_param.ident.name).collect();
|
if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
|
||||||
|
&& let [sole_segment] = &*p.segments
|
||||||
for field_ty in field_tys {
|
&& ty_param_names.contains(&sole_segment.ident.name)
|
||||||
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
|
{
|
||||||
|
continue;
|
||||||
for field_ty_param in field_ty_params {
|
}
|
||||||
// if we have already handled this type, skip it
|
let mut bounds: Vec<_> = self
|
||||||
if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
|
.additional_bounds
|
||||||
&& let [sole_segment] = &*p.segments
|
.iter()
|
||||||
&& ty_param_names.contains(&sole_segment.ident.name)
|
.map(|p| {
|
||||||
{
|
cx.trait_bound(
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mut bounds: Vec<_> = self
|
|
||||||
.additional_bounds
|
|
||||||
.iter()
|
|
||||||
.map(|p| {
|
|
||||||
cx.trait_bound(
|
|
||||||
p.to_path(cx, self.span, type_ident, generics),
|
|
||||||
self.is_const,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Require the current trait.
|
|
||||||
if !self.skip_path_as_bound {
|
|
||||||
bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a `Copy` bound if required.
|
|
||||||
if is_packed && self.needs_copy_as_bound_if_packed {
|
|
||||||
let p = deriving::path_std!(marker::Copy);
|
|
||||||
bounds.push(cx.trait_bound(
|
|
||||||
p.to_path(cx, self.span, type_ident, generics),
|
p.to_path(cx, self.span, type_ident, generics),
|
||||||
self.is_const,
|
self.is_const,
|
||||||
));
|
)
|
||||||
}
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
if !bounds.is_empty() {
|
// Require the current trait.
|
||||||
let predicate = ast::WhereBoundPredicate {
|
if !self.skip_path_as_bound {
|
||||||
span: self.span,
|
bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
|
||||||
bound_generic_params: field_ty_param.bound_generic_params,
|
}
|
||||||
bounded_ty: field_ty_param.ty,
|
|
||||||
bounds,
|
|
||||||
};
|
|
||||||
|
|
||||||
let predicate = ast::WherePredicate::BoundPredicate(predicate);
|
// Add a `Copy` bound if required.
|
||||||
where_clause.predicates.push(predicate);
|
if is_packed && self.needs_copy_as_bound_if_packed {
|
||||||
}
|
let p = deriving::path_std!(marker::Copy);
|
||||||
|
bounds.push(cx.trait_bound(
|
||||||
|
p.to_path(cx, self.span, type_ident, generics),
|
||||||
|
self.is_const,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bounds.is_empty() {
|
||||||
|
let predicate = ast::WhereBoundPredicate {
|
||||||
|
span: self.span,
|
||||||
|
bound_generic_params: field_ty_param.bound_generic_params,
|
||||||
|
bounded_ty: field_ty_param.ty,
|
||||||
|
bounds,
|
||||||
|
};
|
||||||
|
|
||||||
|
let predicate = ast::WherePredicate::BoundPredicate(predicate);
|
||||||
|
where_clause.predicates.push(predicate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1026,6 +1039,7 @@ impl<'a> MethodDef<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The normal case uses field access.
|
/// The normal case uses field access.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #[derive(PartialEq)]
|
/// #[derive(PartialEq)]
|
||||||
/// # struct Dummy;
|
/// # struct Dummy;
|
||||||
|
@ -1038,10 +1052,12 @@ impl<'a> MethodDef<'a> {
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
/// But if the struct is `repr(packed)`, we can't use something like
|
/// But if the struct is `repr(packed)`, we can't use something like
|
||||||
/// `&self.x` because that might cause an unaligned ref. So for any trait
|
/// `&self.x` because that might cause an unaligned ref. So for any trait
|
||||||
/// method that takes a reference, we use a local block to force a copy.
|
/// method that takes a reference, we use a local block to force a copy.
|
||||||
/// This requires that the field impl `Copy`.
|
/// This requires that the field impl `Copy`.
|
||||||
|
///
|
||||||
/// ```rust,ignore (example)
|
/// ```rust,ignore (example)
|
||||||
/// # struct A { x: u8, y: u8 }
|
/// # struct A { x: u8, y: u8 }
|
||||||
/// impl PartialEq for A {
|
/// impl PartialEq for A {
|
||||||
|
@ -1053,7 +1069,7 @@ impl<'a> MethodDef<'a> {
|
||||||
/// impl Hash for A {
|
/// impl Hash for A {
|
||||||
/// fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
|
/// fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
|
||||||
/// ::core::hash::Hash::hash(&{ self.x }, state);
|
/// ::core::hash::Hash::hash(&{ self.x }, state);
|
||||||
/// ::core::hash::Hash::hash(&{ self.y }, state)
|
/// ::core::hash::Hash::hash(&{ self.y }, state);
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1107,7 +1123,9 @@ impl<'a> MethodDef<'a> {
|
||||||
/// A2(i32)
|
/// A2(i32)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
/// is equivalent to:
|
/// is equivalent to:
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(core_intrinsics)]
|
/// #![feature(core_intrinsics)]
|
||||||
/// enum A {
|
/// enum A {
|
||||||
|
@ -1119,15 +1137,15 @@ impl<'a> MethodDef<'a> {
|
||||||
/// fn eq(&self, other: &A) -> bool {
|
/// fn eq(&self, other: &A) -> bool {
|
||||||
/// let __self_tag = ::core::intrinsics::discriminant_value(self);
|
/// let __self_tag = ::core::intrinsics::discriminant_value(self);
|
||||||
/// let __arg1_tag = ::core::intrinsics::discriminant_value(other);
|
/// let __arg1_tag = ::core::intrinsics::discriminant_value(other);
|
||||||
/// __self_tag == __arg1_tag &&
|
/// __self_tag == __arg1_tag
|
||||||
/// match (self, other) {
|
/// && match (self, other) {
|
||||||
/// (A::A2(__self_0), A::A2(__arg1_0)) =>
|
/// (A::A2(__self_0), A::A2(__arg1_0)) => *__self_0 == *__arg1_0,
|
||||||
/// *__self_0 == *__arg1_0,
|
|
||||||
/// _ => true,
|
/// _ => true,
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
/// Creates a tag check combined with a match for a tuple of all
|
/// Creates a tag check combined with a match for a tuple of all
|
||||||
/// `selflike_args`, with an arm for each variant with fields, possibly an
|
/// `selflike_args`, with an arm for each variant with fields, possibly an
|
||||||
/// arm for each fieldless variant (if `unify_fieldless_variants` is not
|
/// arm for each fieldless variant (if `unify_fieldless_variants` is not
|
||||||
|
@ -1349,7 +1367,7 @@ impl<'a> MethodDef<'a> {
|
||||||
// (Variant1, Variant1, ...) => Body1
|
// (Variant1, Variant1, ...) => Body1
|
||||||
// (Variant2, Variant2, ...) => Body2,
|
// (Variant2, Variant2, ...) => Body2,
|
||||||
// ...
|
// ...
|
||||||
// _ => ::core::intrinsics::unreachable()
|
// _ => ::core::intrinsics::unreachable(),
|
||||||
// }
|
// }
|
||||||
let get_match_expr = |mut selflike_args: ThinVec<P<Expr>>| {
|
let get_match_expr = |mut selflike_args: ThinVec<P<Expr>>| {
|
||||||
let match_arg = if selflike_args.len() == 1 {
|
let match_arg = if selflike_args.len() == 1 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue