1
Fork 0

Auto merge of #101467 - nnethercote:shrink-hir-Ty-Pat, r=spastorino

Shrink `hir::Ty` and `hir::Pat`

r? `@ghost`
This commit is contained in:
bors 2022-09-08 13:11:57 +00:00
commit 24d6992020
19 changed files with 142 additions and 95 deletions

View file

@ -1128,8 +1128,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
); );
// Destructure like a tuple struct. // Destructure like a tuple struct.
let tuple_struct_pat = let tuple_struct_pat = hir::PatKind::TupleStruct(
hir::PatKind::TupleStruct(qpath, pats, rest.map(|r| r.0)); qpath,
pats,
hir::DotDotPos::new(rest.map(|r| r.0)),
);
return self.pat_without_dbm(lhs.span, tuple_struct_pat); return self.pat_without_dbm(lhs.span, tuple_struct_pat);
} }
} }
@ -1184,13 +1187,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Tup(elements) => { ExprKind::Tup(elements) => {
let (pats, rest) = let (pats, rest) =
self.destructure_sequence(elements, "tuple", eq_sign_span, assignments); self.destructure_sequence(elements, "tuple", eq_sign_span, assignments);
let tuple_pat = hir::PatKind::Tuple(pats, rest.map(|r| r.0)); let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0)));
return self.pat_without_dbm(lhs.span, tuple_pat); return self.pat_without_dbm(lhs.span, tuple_pat);
} }
ExprKind::Paren(e) => { ExprKind::Paren(e) => {
// We special-case `(..)` for consistency with patterns. // We special-case `(..)` for consistency with patterns.
if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {
let tuple_pat = hir::PatKind::Tuple(&[], Some(0)); let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0)));
return self.pat_without_dbm(lhs.span, tuple_pat); return self.pat_without_dbm(lhs.span, tuple_pat);
} else { } else {
return self.destructure_assign_mut(e, eq_sign_span, assignments); return self.destructure_assign_mut(e, eq_sign_span, assignments);

View file

@ -1196,7 +1196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let lifetime_bound = this.elided_dyn_bound(t.span); let lifetime_bound = this.elided_dyn_bound(t.span);
(bounds, lifetime_bound) (bounds, lifetime_bound)
}); });
let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None); let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None);
return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
} }
@ -1934,8 +1934,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let res = res.unwrap_or( let res = res.unwrap_or(
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error), self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
); );
let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res))
hir::GenericArg::Lifetime(l)
}, },
)); ));
@ -2004,7 +2003,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
let span = self.lower_span(l.ident.span); let span = self.lower_span(l.ident.span);
let ident = self.lower_ident(l.ident); let ident = self.lower_ident(l.ident);
self.new_named_lifetime(l.id, l.id, span, ident) self.new_named_lifetime(l.id, l.id, span, ident)
@ -2017,7 +2016,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: Span, span: Span,
ident: Ident, ident: Ident,
res: LifetimeRes, res: LifetimeRes,
) -> hir::Lifetime { ) -> &'hir hir::Lifetime {
let name = match res { let name = match res {
LifetimeRes::Param { param, .. } => { LifetimeRes::Param { param, .. } => {
let p_name = ParamName::Plain(ident); let p_name = ParamName::Plain(ident);
@ -2038,7 +2037,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}; };
debug!(?name); debug!(?name);
hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name } self.arena.alloc(hir::Lifetime {
hir_id: self.lower_node_id(id),
span: self.lower_span(span),
name,
})
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
@ -2048,7 +2051,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
new_id: NodeId, new_id: NodeId,
span: Span, span: Span,
ident: Ident, ident: Ident,
) -> hir::Lifetime { ) -> &'hir hir::Lifetime {
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
self.new_named_lifetime_with_res(new_id, span, ident, res) self.new_named_lifetime_with_res(new_id, span, ident, res)
} }
@ -2462,14 +2465,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// bound, like the bound in `Box<dyn Debug>`. This method is not invoked /// bound, like the bound in `Box<dyn Debug>`. This method is not invoked
/// when the bound is written, even if it is written with `'_` like in /// when the bound is written, even if it is written with `'_` like in
/// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked. /// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked.
fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime { fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
let r = hir::Lifetime { let r = hir::Lifetime {
hir_id: self.next_id(), hir_id: self.next_id(),
span: self.lower_span(span), span: self.lower_span(span),
name: hir::LifetimeName::ImplicitObjectLifetimeDefault, name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
}; };
debug!("elided_dyn_bound: r={:?}", r); debug!("elided_dyn_bound: r={:?}", r);
r self.arena.alloc(r)
} }
} }

View file

@ -116,7 +116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self, &mut self,
pats: &[P<Pat>], pats: &[P<Pat>],
ctx: &str, ctx: &str,
) -> (&'hir [hir::Pat<'hir>], Option<usize>) { ) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) {
let mut elems = Vec::with_capacity(pats.len()); let mut elems = Vec::with_capacity(pats.len());
let mut rest = None; let mut rest = None;
@ -160,7 +160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
(self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos)) (self.arena.alloc_from_iter(elems), hir::DotDotPos::new(rest.map(|(ddpos, _)| ddpos)))
} }
/// Lower a slice pattern of form `[pat_0, ..., pat_n]` into /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into

View file

@ -259,7 +259,7 @@ impl InferArg {
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub enum GenericArg<'hir> { pub enum GenericArg<'hir> {
Lifetime(Lifetime), Lifetime(&'hir Lifetime),
Type(&'hir Ty<'hir>), Type(&'hir Ty<'hir>),
Const(ConstArg), Const(ConstArg),
Infer(InferArg), Infer(InferArg),
@ -430,7 +430,7 @@ pub enum GenericBound<'hir> {
Trait(PolyTraitRef<'hir>, TraitBoundModifier), Trait(PolyTraitRef<'hir>, TraitBoundModifier),
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>), LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
Outlives(Lifetime), Outlives(&'hir Lifetime),
} }
impl GenericBound<'_> { impl GenericBound<'_> {
@ -756,7 +756,7 @@ impl<'hir> WhereBoundPredicate<'hir> {
pub struct WhereRegionPredicate<'hir> { pub struct WhereRegionPredicate<'hir> {
pub span: Span, pub span: Span,
pub in_where_clause: bool, pub in_where_clause: bool,
pub lifetime: Lifetime, pub lifetime: &'hir Lifetime,
pub bounds: GenericBounds<'hir>, pub bounds: GenericBounds<'hir>,
} }
@ -1059,6 +1059,35 @@ impl fmt::Display for RangeEnd {
} }
} }
// Equivalent to `Option<usize>`. That type takes up 16 bytes on 64-bit, but
// this type only takes up 4 bytes, at the cost of being restricted to a
// maximum value of `u32::MAX - 1`. In practice, this is more than enough.
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable_Generic)]
pub struct DotDotPos(u32);
impl DotDotPos {
// Panics if n >= u32::MAX.
pub fn new(n: Option<usize>) -> Self {
match n {
Some(n) => {
assert!(n < u32::MAX as usize);
Self(n as u32)
}
None => Self(u32::MAX),
}
}
pub fn as_opt_usize(&self) -> Option<usize> {
if self.0 == u32::MAX { None } else { Some(self.0 as usize) }
}
}
impl fmt::Debug for DotDotPos {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_opt_usize().fmt(f)
}
}
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub enum PatKind<'hir> { pub enum PatKind<'hir> {
/// Represents a wildcard pattern (i.e., `_`). /// Represents a wildcard pattern (i.e., `_`).
@ -1075,9 +1104,9 @@ pub enum PatKind<'hir> {
Struct(QPath<'hir>, &'hir [PatField<'hir>], bool), Struct(QPath<'hir>, &'hir [PatField<'hir>], bool),
/// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// If the `..` pattern fragment is present, then `DotDotPos` denotes its position.
/// `0 <= position <= subpats.len()` /// `0 <= position <= subpats.len()`
TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], Option<usize>), TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], DotDotPos),
/// An or-pattern `A | B | C`. /// An or-pattern `A | B | C`.
/// Invariant: `pats.len() >= 2`. /// Invariant: `pats.len() >= 2`.
@ -1089,7 +1118,7 @@ pub enum PatKind<'hir> {
/// A tuple pattern (e.g., `(a, b)`). /// A tuple pattern (e.g., `(a, b)`).
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
/// `0 <= position <= subpats.len()` /// `0 <= position <= subpats.len()`
Tuple(&'hir [Pat<'hir>], Option<usize>), Tuple(&'hir [Pat<'hir>], DotDotPos),
/// A `box` pattern. /// A `box` pattern.
Box(&'hir Pat<'hir>), Box(&'hir Pat<'hir>),
@ -2499,7 +2528,7 @@ pub enum TyKind<'hir> {
/// A raw pointer (i.e., `*const T` or `*mut T`). /// A raw pointer (i.e., `*const T` or `*mut T`).
Ptr(MutTy<'hir>), Ptr(MutTy<'hir>),
/// A reference (i.e., `&'a T` or `&'a mut T`). /// A reference (i.e., `&'a T` or `&'a mut T`).
Rptr(Lifetime, MutTy<'hir>), Rptr(&'hir Lifetime, MutTy<'hir>),
/// A bare function (e.g., `fn(usize) -> bool`). /// A bare function (e.g., `fn(usize) -> bool`).
BareFn(&'hir BareFnTy<'hir>), BareFn(&'hir BareFnTy<'hir>),
/// The never type (`!`). /// The never type (`!`).
@ -2518,7 +2547,7 @@ pub enum TyKind<'hir> {
OpaqueDef(ItemId, &'hir [GenericArg<'hir>]), OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
/// A trait object type `Bound1 + Bound2 + Bound3` /// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime. /// where `Bound` is a trait or a lifetime.
TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime, TraitObjectSyntax), TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
/// Unused for now. /// Unused for now.
Typeof(AnonConst), Typeof(AnonConst),
/// `TyKind::Infer` means the type should be inferred instead of it having been /// `TyKind::Infer` means the type should be inferred instead of it having been
@ -3474,7 +3503,7 @@ mod size_asserts {
static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItem<'_>, 72);
static_assert_size!(ForeignItemKind<'_>, 40); static_assert_size!(ForeignItemKind<'_>, 40);
#[cfg(not(bootstrap))] #[cfg(not(bootstrap))]
static_assert_size!(GenericArg<'_>, 32); static_assert_size!(GenericArg<'_>, 24);
static_assert_size!(GenericBound<'_>, 48); static_assert_size!(GenericBound<'_>, 48);
static_assert_size!(Generics<'_>, 56); static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 80); static_assert_size!(Impl<'_>, 80);
@ -3486,17 +3515,17 @@ mod size_asserts {
static_assert_size!(ItemKind<'_>, 48); static_assert_size!(ItemKind<'_>, 48);
static_assert_size!(Local<'_>, 64); static_assert_size!(Local<'_>, 64);
static_assert_size!(Param<'_>, 32); static_assert_size!(Param<'_>, 32);
static_assert_size!(Pat<'_>, 88); static_assert_size!(Pat<'_>, 72);
static_assert_size!(PatKind<'_>, 64); static_assert_size!(PatKind<'_>, 48);
static_assert_size!(Path<'_>, 48); static_assert_size!(Path<'_>, 48);
static_assert_size!(PathSegment<'_>, 56); static_assert_size!(PathSegment<'_>, 56);
static_assert_size!(QPath<'_>, 24); static_assert_size!(QPath<'_>, 24);
static_assert_size!(Stmt<'_>, 32); static_assert_size!(Stmt<'_>, 32);
static_assert_size!(StmtKind<'_>, 16); static_assert_size!(StmtKind<'_>, 16);
#[cfg(not(bootstrap))] #[cfg(not(bootstrap))]
static_assert_size!(TraitItem<'static>, 88); static_assert_size!(TraitItem<'_>, 88);
#[cfg(not(bootstrap))] #[cfg(not(bootstrap))]
static_assert_size!(TraitItemKind<'_>, 48); static_assert_size!(TraitItemKind<'_>, 48);
static_assert_size!(Ty<'_>, 72); static_assert_size!(Ty<'_>, 48);
static_assert_size!(TyKind<'_>, 56); static_assert_size!(TyKind<'_>, 32);
} }

View file

@ -35,7 +35,7 @@ pub trait EnumerateAndAdjustIterator {
fn enumerate_and_adjust( fn enumerate_and_adjust(
self, self,
expected_len: usize, expected_len: usize,
gap_pos: Option<usize>, gap_pos: hir::DotDotPos,
) -> EnumerateAndAdjust<Self> ) -> EnumerateAndAdjust<Self>
where where
Self: Sized; Self: Sized;
@ -45,7 +45,7 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
fn enumerate_and_adjust( fn enumerate_and_adjust(
self, self,
expected_len: usize, expected_len: usize,
gap_pos: Option<usize>, gap_pos: hir::DotDotPos,
) -> EnumerateAndAdjust<Self> ) -> EnumerateAndAdjust<Self>
where where
Self: Sized, Self: Sized,
@ -53,7 +53,7 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
let actual_len = self.len(); let actual_len = self.len();
EnumerateAndAdjust { EnumerateAndAdjust {
enumerate: self.enumerate(), enumerate: self.enumerate(),
gap_pos: gap_pos.unwrap_or(expected_len), gap_pos: gap_pos.as_opt_usize().unwrap_or(expected_len),
gap_len: expected_len - actual_len, gap_len: expected_len - actual_len,
} }
} }

View file

@ -1761,7 +1761,8 @@ impl<'a> State<'a> {
PatKind::TupleStruct(ref qpath, elts, ddpos) => { PatKind::TupleStruct(ref qpath, elts, ddpos) => {
self.print_qpath(qpath, true); self.print_qpath(qpath, true);
self.popen(); self.popen();
if let Some(ddpos) = ddpos { if let Some(ddpos) = ddpos.as_opt_usize() {
let ddpos = ddpos as usize;
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
if ddpos != 0 { if ddpos != 0 {
self.word_space(","); self.word_space(",");
@ -1804,7 +1805,7 @@ impl<'a> State<'a> {
} }
PatKind::Tuple(elts, ddpos) => { PatKind::Tuple(elts, ddpos) => {
self.popen(); self.popen();
if let Some(ddpos) = ddpos { if let Some(ddpos) = ddpos.as_opt_usize() {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
if ddpos != 0 { if ddpos != 0 {
self.word_space(","); self.word_space(",");

View file

@ -338,7 +338,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
&mut self, &mut self,
pats: &'tcx [hir::Pat<'tcx>], pats: &'tcx [hir::Pat<'tcx>],
expected_len: usize, expected_len: usize,
gap_pos: Option<usize>, gap_pos: hir::DotDotPos,
) -> Vec<FieldPat<'tcx>> { ) -> Vec<FieldPat<'tcx>> {
pats.iter() pats.iter()
.enumerate_and_adjust(expected_len, gap_pos) .enumerate_and_adjust(expected_len, gap_pos)

View file

@ -226,19 +226,16 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
lhs: &hir::Pat<'_>, lhs: &hir::Pat<'_>,
res: Res, res: Res,
pats: &[hir::Pat<'_>], pats: &[hir::Pat<'_>],
dotdot: Option<usize>, dotdot: hir::DotDotPos,
) { ) {
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
ty::Adt(adt, _) => adt.variant_of_res(res), ty::Adt(adt, _) => adt.variant_of_res(res),
_ => span_bug!(lhs.span, "non-ADT in tuple struct pattern"), _ => span_bug!(lhs.span, "non-ADT in tuple struct pattern"),
}; };
let first_n = pats.iter().enumerate().take(dotdot.unwrap_or(pats.len())); let dotdot = dotdot.as_opt_usize().unwrap_or(pats.len());
let first_n = pats.iter().enumerate().take(dotdot);
let missing = variant.fields.len() - pats.len(); let missing = variant.fields.len() - pats.len();
let last_n = pats let last_n = pats.iter().enumerate().skip(dotdot).map(|(idx, pat)| (idx + missing, pat));
.iter()
.enumerate()
.skip(dotdot.unwrap_or(pats.len()))
.map(|(idx, pat)| (idx + missing, pat));
for (idx, pat) in first_n.chain(last_n) { for (idx, pat) in first_n.chain(last_n) {
if let PatKind::Wild = pat.kind { if let PatKind::Wild = pat.kind {
continue; continue;

View file

@ -437,6 +437,11 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
} }
} }
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
self.record("Lifetime", Id::Node(lifetime.hir_id), lifetime);
hir_visit::walk_lifetime(self, lifetime)
}
fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) { fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
self.record("Path", Id::None, path); self.record("Path", Id::None, path);
hir_visit::walk_path(self, path) hir_visit::walk_path(self, path)

View file

@ -981,7 +981,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &'tcx Pat<'tcx>, pat: &'tcx Pat<'tcx>,
qpath: &'tcx hir::QPath<'tcx>, qpath: &'tcx hir::QPath<'tcx>,
subpats: &'tcx [Pat<'tcx>], subpats: &'tcx [Pat<'tcx>],
ddpos: Option<usize>, ddpos: hir::DotDotPos,
expected: Ty<'tcx>, expected: Ty<'tcx>,
def_bm: BindingMode, def_bm: BindingMode,
ti: TopInfo<'tcx>, ti: TopInfo<'tcx>,
@ -1066,7 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type-check subpatterns. // Type-check subpatterns.
if subpats.len() == variant.fields.len() if subpats.len() == variant.fields.len()
|| subpats.len() < variant.fields.len() && ddpos.is_some() || subpats.len() < variant.fields.len() && ddpos.as_opt_usize().is_some()
{ {
let ty::Adt(_, substs) = pat_ty.kind() else { let ty::Adt(_, substs) = pat_ty.kind() else {
bug!("unexpected pattern type {:?}", pat_ty); bug!("unexpected pattern type {:?}", pat_ty);
@ -1254,14 +1254,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
span: Span, span: Span,
elements: &'tcx [Pat<'tcx>], elements: &'tcx [Pat<'tcx>],
ddpos: Option<usize>, ddpos: hir::DotDotPos,
expected: Ty<'tcx>, expected: Ty<'tcx>,
def_bm: BindingMode, def_bm: BindingMode,
ti: TopInfo<'tcx>, ti: TopInfo<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let mut expected_len = elements.len(); let mut expected_len = elements.len();
if ddpos.is_some() { if ddpos.as_opt_usize().is_some() {
// Require known type only when `..` is present. // Require known type only when `..` is present.
if let ty::Tuple(tys) = self.structurally_resolved_type(span, expected).kind() { if let ty::Tuple(tys) = self.structurally_resolved_type(span, expected).kind() {
expected_len = tys.len(); expected_len = tys.len();

View file

@ -190,7 +190,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
) )
} }
fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime { fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
let def = cx.tcx.named_region(lifetime.hir_id); let def = cx.tcx.named_region(lifetime.hir_id);
if let Some( if let Some(
rl::Region::EarlyBound(node_id) rl::Region::EarlyBound(node_id)
@ -495,7 +495,7 @@ fn clean_generic_param<'tcx>(
.filter(|bp| !bp.in_where_clause) .filter(|bp| !bp.in_where_clause)
.flat_map(|bp| bp.bounds) .flat_map(|bp| bp.bounds)
.map(|bound| match bound { .map(|bound| match bound {
hir::GenericBound::Outlives(lt) => clean_lifetime(*lt, cx), hir::GenericBound::Outlives(lt) => clean_lifetime(lt, cx),
_ => panic!(), _ => panic!(),
}) })
.collect() .collect()
@ -1392,7 +1392,7 @@ fn maybe_expand_private_type_alias<'tcx>(
} }
_ => None, _ => None,
}); });
if let Some(lt) = lifetime.cloned() { if let Some(lt) = lifetime {
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id); let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let cleaned = let cleaned =
if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() }; if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() };

View file

@ -119,59 +119,60 @@ hir-stats HIR STATS
hir-stats Name Accumulated Size Count Item Size hir-stats Name Accumulated Size Count Item Size
hir-stats ---------------------------------------------------------------- hir-stats ----------------------------------------------------------------
hir-stats ForeignItemRef 24 ( 0.2%) 1 24 hir-stats ForeignItemRef 24 ( 0.2%) 1 24
hir-stats Lifetime 32 ( 0.3%) 1 32
hir-stats Mod 32 ( 0.3%) 1 32 hir-stats Mod 32 ( 0.3%) 1 32
hir-stats ExprField 40 ( 0.4%) 1 40 hir-stats ExprField 40 ( 0.4%) 1 40
hir-stats TraitItemRef 56 ( 0.6%) 2 28 hir-stats TraitItemRef 56 ( 0.6%) 2 28
hir-stats Param 64 ( 0.6%) 2 32 hir-stats Local 64 ( 0.7%) 1 64
hir-stats Local 64 ( 0.6%) 1 64 hir-stats Param 64 ( 0.7%) 2 32
hir-stats InlineAsm 72 ( 0.7%) 1 72 hir-stats InlineAsm 72 ( 0.7%) 1 72
hir-stats ImplItemRef 72 ( 0.7%) 2 36 hir-stats ImplItemRef 72 ( 0.7%) 2 36
hir-stats FieldDef 96 ( 0.9%) 2 48 hir-stats Body 96 ( 1.0%) 3 32
hir-stats Arm 96 ( 0.9%) 2 48 hir-stats GenericArg 96 ( 1.0%) 4 24
hir-stats Body 96 ( 0.9%) 3 32 hir-stats - Type 24 ( 0.2%) 1
hir-stats Stmt 96 ( 0.9%) 3 32 hir-stats - Lifetime 72 ( 0.7%) 3
hir-stats FieldDef 96 ( 1.0%) 2 48
hir-stats Arm 96 ( 1.0%) 2 48
hir-stats Stmt 96 ( 1.0%) 3 32
hir-stats - Local 32 ( 0.3%) 1 hir-stats - Local 32 ( 0.3%) 1
hir-stats - Semi 32 ( 0.3%) 1 hir-stats - Semi 32 ( 0.3%) 1
hir-stats - Expr 32 ( 0.3%) 1 hir-stats - Expr 32 ( 0.3%) 1
hir-stats FnDecl 120 ( 1.2%) 3 40 hir-stats FnDecl 120 ( 1.2%) 3 40
hir-stats Attribute 128 ( 1.3%) 4 32 hir-stats Attribute 128 ( 1.3%) 4 32
hir-stats GenericArg 128 ( 1.3%) 4 32 hir-stats GenericArgs 144 ( 1.5%) 3 48
hir-stats - Type 32 ( 0.3%) 1 hir-stats Variant 160 ( 1.7%) 2 80
hir-stats - Lifetime 96 ( 0.9%) 3 hir-stats WherePredicate 168 ( 1.7%) 3 56
hir-stats GenericArgs 144 ( 1.4%) 3 48 hir-stats - BoundPredicate 168 ( 1.7%) 3
hir-stats Variant 160 ( 1.6%) 2 80 hir-stats GenericBound 192 ( 2.0%) 4 48
hir-stats GenericBound 192 ( 1.9%) 4 48 hir-stats - Trait 192 ( 2.0%) 4
hir-stats - Trait 192 ( 1.9%) 4 hir-stats Block 288 ( 3.0%) 6 48
hir-stats WherePredicate 216 ( 2.1%) 3 72 hir-stats Pat 360 ( 3.7%) 5 72
hir-stats - BoundPredicate 216 ( 2.1%) 3 hir-stats - Wild 72 ( 0.7%) 1
hir-stats Block 288 ( 2.8%) 6 48 hir-stats - Struct 72 ( 0.7%) 1
hir-stats GenericParam 400 ( 3.9%) 5 80 hir-stats - Binding 216 ( 2.2%) 3
hir-stats Pat 440 ( 4.3%) 5 88 hir-stats GenericParam 400 ( 4.1%) 5 80
hir-stats - Wild 88 ( 0.9%) 1 hir-stats Generics 560 ( 5.8%) 10 56
hir-stats - Struct 88 ( 0.9%) 1 hir-stats Ty 720 ( 7.4%) 15 48
hir-stats - Binding 264 ( 2.6%) 3 hir-stats - Ptr 48 ( 0.5%) 1
hir-stats Generics 560 ( 5.5%) 10 56 hir-stats - Rptr 48 ( 0.5%) 1
hir-stats Expr 768 ( 7.6%) 12 64 hir-stats - Path 624 ( 6.4%) 13
hir-stats - Path 64 ( 0.6%) 1 hir-stats Expr 768 ( 7.9%) 12 64
hir-stats - Struct 64 ( 0.6%) 1 hir-stats - Path 64 ( 0.7%) 1
hir-stats - Match 64 ( 0.6%) 1 hir-stats - Struct 64 ( 0.7%) 1
hir-stats - InlineAsm 64 ( 0.6%) 1 hir-stats - Match 64 ( 0.7%) 1
hir-stats - InlineAsm 64 ( 0.7%) 1
hir-stats - Lit 128 ( 1.3%) 2 hir-stats - Lit 128 ( 1.3%) 2
hir-stats - Block 384 ( 3.8%) 6 hir-stats - Block 384 ( 4.0%) 6
hir-stats Item 960 ( 9.4%) 12 80 hir-stats Item 960 ( 9.9%) 12 80
hir-stats - Trait 80 ( 0.8%) 1 hir-stats - Trait 80 ( 0.8%) 1
hir-stats - Enum 80 ( 0.8%) 1 hir-stats - Enum 80 ( 0.8%) 1
hir-stats - ExternCrate 80 ( 0.8%) 1 hir-stats - ExternCrate 80 ( 0.8%) 1
hir-stats - ForeignMod 80 ( 0.8%) 1 hir-stats - ForeignMod 80 ( 0.8%) 1
hir-stats - Impl 80 ( 0.8%) 1 hir-stats - Impl 80 ( 0.8%) 1
hir-stats - Fn 160 ( 1.6%) 2 hir-stats - Fn 160 ( 1.7%) 2
hir-stats - Use 400 ( 3.9%) 5 hir-stats - Use 400 ( 4.1%) 5
hir-stats Ty 1_080 (10.6%) 15 72 hir-stats Path 1_536 (15.9%) 32 48
hir-stats - Ptr 72 ( 0.7%) 1 hir-stats PathSegment 2_240 (23.1%) 40 56
hir-stats - Rptr 72 ( 0.7%) 1
hir-stats - Path 936 ( 9.2%) 13
hir-stats Path 1_536 (15.1%) 32 48
hir-stats PathSegment 2_240 (22.0%) 40 56
hir-stats ---------------------------------------------------------------- hir-stats ----------------------------------------------------------------
hir-stats Total 10_168 hir-stats Total 9_680
hir-stats hir-stats

View file

@ -51,7 +51,9 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
false false
}, },
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => !etc.is_some() && array_rec(a), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => {
!etc.as_opt_usize().is_some() && array_rec(a)
}
PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),
PatKind::Path(_) | PatKind::Lit(_) => true, PatKind::Path(_) | PatKind::Lit(_) => true,
} }

View file

@ -248,7 +248,7 @@ impl<'a> NormalizedPat<'a> {
} else { } else {
(None, adt.non_enum_variant()) (None, adt.non_enum_variant())
}; };
let (front, back) = match wild_idx { let (front, back) = match wild_idx.as_opt_usize() {
Some(i) => pats.split_at(i), Some(i) => pats.split_at(i),
None => (pats, [].as_slice()), None => (pats, [].as_slice()),
}; };
@ -268,7 +268,7 @@ impl<'a> NormalizedPat<'a> {
ty::Tuple(subs) => subs.len(), ty::Tuple(subs) => subs.len(),
_ => return Self::Wild, _ => return Self::Wild,
}; };
let (front, back) = match wild_idx { let (front, back) = match wild_idx.as_opt_usize() {
Some(i) => pats.split_at(i), Some(i) => pats.split_at(i),
None => (pats, [].as_slice()), None => (pats, [].as_slice()),
}; };

View file

@ -200,6 +200,8 @@ fn form_exhaustive_matches<'a>(cx: &LateContext<'a>, ty: Ty<'a>, left: &Pat<'_>,
// We don't actually know the position and the presence of the `..` (dotdot) operator // We don't actually know the position and the presence of the `..` (dotdot) operator
// in the arms, so we need to evaluate the correct offsets here in order to iterate in // in the arms, so we need to evaluate the correct offsets here in order to iterate in
// both arms at the same time. // both arms at the same time.
let left_pos = left_pos.as_opt_usize();
let right_pos = right_pos.as_opt_usize();
let len = max( let len = max(
left_in.len() + { left_in.len() + {
if left_pos.is_some() { 1 } else { 0 } if left_pos.is_some() { 1 } else { 0 }

View file

@ -122,7 +122,8 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
if_chain! { if_chain! {
if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr); if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
if !is_else_clause(cx.tcx, expr); if !is_else_clause(cx.tcx, expr);
if let PatKind::TupleStruct(ref path1, [field], None) = let_pat.kind; if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind;
if ddpos.as_opt_usize().is_none();
if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind; if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
let caller_ty = cx.typeck_results().expr_ty(let_expr); let caller_ty = cx.typeck_results().expr_ty(let_expr);
let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else); let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);

View file

@ -19,10 +19,12 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
&& cx.typeck_results().pat_ty(local.pat).is_unit() && cx.typeck_results().pat_ty(local.pat).is_unit()
{ {
if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer)) if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer))
|| matches!(local.pat.kind, PatKind::Tuple([], None))) || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
&& expr_needs_inferred_result(cx, init) && expr_needs_inferred_result(cx, init)
{ {
if !matches!(local.pat.kind, PatKind::Wild | PatKind::Tuple([], None)) { if !matches!(local.pat.kind, PatKind::Wild)
&& !matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none())
{
span_lint_and_then( span_lint_and_then(
cx, cx,
LET_UNIT_VALUE, LET_UNIT_VALUE,

View file

@ -929,7 +929,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
} }
} }
pub fn hash_lifetime(&mut self, lifetime: Lifetime) { pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
std::mem::discriminant(&lifetime.name).hash(&mut self.s); std::mem::discriminant(&lifetime.name).hash(&mut self.s);
if let LifetimeName::Param(param_id, ref name) = lifetime.name { if let LifetimeName::Param(param_id, ref name) = lifetime.name {
std::mem::discriminant(name).hash(&mut self.s); std::mem::discriminant(name).hash(&mut self.s);

View file

@ -1552,7 +1552,8 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl It
pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
if_chain! { if_chain! {
if let PatKind::TupleStruct(ref path, pat, None) = arm.pat.kind; if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind;
if ddpos.as_opt_usize().is_none();
if is_lang_ctor(cx, path, ResultOk); if is_lang_ctor(cx, path, ResultOk);
if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind; if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
if path_to_local_id(arm.body, hir_id); if path_to_local_id(arm.body, hir_id);