Skip to content

Commit 48c1c54

Browse files
committed
Auto merge of #44758 - arielb1:a-small-path, r=eddyb
put empty generic lists behind a pointer This reduces the size of hir::Expr from 128 to 88 bytes (!) and shaves 200MB out of #36799. This is a performance-sensitive PR so please don't roll it up. r? @eddyb
2 parents 1ed7d41 + e921b32 commit 48c1c54

File tree

10 files changed

+187
-112
lines changed

10 files changed

+187
-112
lines changed

src/librustc/hir/intravisit.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
627627
path_span: Span,
628628
segment: &'v PathSegment) {
629629
visitor.visit_name(path_span, segment.name);
630-
visitor.visit_path_parameters(path_span, &segment.parameters);
630+
if let Some(ref parameters) = segment.parameters {
631+
visitor.visit_path_parameters(path_span, parameters);
632+
}
631633
}
632634

633635
pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,

src/librustc/hir/lowering.rs

+18-24
Original file line numberDiff line numberDiff line change
@@ -690,10 +690,9 @@ impl<'a> LoweringContext<'a> {
690690
TyKind::ImplicitSelf => {
691691
hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
692692
def: self.expect_full_def(t.id),
693-
segments: hir_vec![hir::PathSegment {
694-
name: keywords::SelfType.name(),
695-
parameters: hir::PathParameters::none()
696-
}],
693+
segments: hir_vec![
694+
hir::PathSegment::from_name(keywords::SelfType.name())
695+
],
697696
span: t.span,
698697
})))
699698
}
@@ -914,12 +913,8 @@ impl<'a> LoweringContext<'a> {
914913
segments: segments.map(|segment| {
915914
self.lower_path_segment(p.span, segment, param_mode, 0,
916915
ParenthesizedGenericArgs::Err)
917-
}).chain(name.map(|name| {
918-
hir::PathSegment {
919-
name,
920-
parameters: hir::PathParameters::none()
921-
}
922-
})).collect(),
916+
}).chain(name.map(|name| hir::PathSegment::from_name(name)))
917+
.collect(),
923918
span: p.span,
924919
}
925920
}
@@ -940,7 +935,7 @@ impl<'a> LoweringContext<'a> {
940935
expected_lifetimes: usize,
941936
parenthesized_generic_args: ParenthesizedGenericArgs)
942937
-> hir::PathSegment {
943-
let mut parameters = if let Some(ref parameters) = segment.parameters {
938+
let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
944939
let msg = "parenthesized parameters may only be used with a trait";
945940
match **parameters {
946941
PathParameters::AngleBracketed(ref data) => {
@@ -951,12 +946,12 @@ impl<'a> LoweringContext<'a> {
951946
ParenthesizedGenericArgs::Warn => {
952947
self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
953948
CRATE_NODE_ID, data.span, msg.into());
954-
hir::PathParameters::none()
949+
(hir::PathParameters::none(), true)
955950
}
956951
ParenthesizedGenericArgs::Err => {
957952
struct_span_err!(self.sess, data.span, E0214, "{}", msg)
958953
.span_label(data.span, "only traits may use parentheses").emit();
959-
hir::PathParameters::none()
954+
(hir::PathParameters::none(), true)
960955
}
961956
}
962957
}
@@ -970,40 +965,39 @@ impl<'a> LoweringContext<'a> {
970965
}).collect();
971966
}
972967

973-
hir::PathSegment {
974-
name: self.lower_ident(segment.identifier),
968+
hir::PathSegment::new(
969+
self.lower_ident(segment.identifier),
975970
parameters,
976-
}
971+
infer_types
972+
)
977973
}
978974

979975
fn lower_angle_bracketed_parameter_data(&mut self,
980976
data: &AngleBracketedParameterData,
981977
param_mode: ParamMode)
982-
-> hir::PathParameters {
978+
-> (hir::PathParameters, bool) {
983979
let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
984-
hir::PathParameters {
980+
(hir::PathParameters {
985981
lifetimes: self.lower_lifetimes(lifetimes),
986982
types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
987-
infer_types: types.is_empty() && param_mode == ParamMode::Optional,
988983
bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
989984
parenthesized: false,
990-
}
985+
}, types.is_empty() && param_mode == ParamMode::Optional)
991986
}
992987

993988
fn lower_parenthesized_parameter_data(&mut self,
994989
data: &ParenthesizedParameterData)
995-
-> hir::PathParameters {
990+
-> (hir::PathParameters, bool) {
996991
let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
997992
let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect();
998993
let mk_tup = |this: &mut Self, tys, span| {
999994
let LoweredNodeId { node_id, hir_id } = this.next_id();
1000995
P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span })
1001996
};
1002997

1003-
hir::PathParameters {
998+
(hir::PathParameters {
1004999
lifetimes: hir::HirVec::new(),
10051000
types: hir_vec![mk_tup(self, inputs, span)],
1006-
infer_types: false,
10071001
bindings: hir_vec![hir::TypeBinding {
10081002
id: self.next_id().node_id,
10091003
name: Symbol::intern(FN_OUTPUT_NAME),
@@ -1012,7 +1006,7 @@ impl<'a> LoweringContext<'a> {
10121006
span: output.as_ref().map_or(span, |ty| ty.span),
10131007
}],
10141008
parenthesized: true,
1015-
}
1009+
}, false)
10161010
}
10171011

10181012
fn lower_local(&mut self, l: &Local) -> P<hir::Local> {

src/librustc/hir/mod.rs

+39-8
Original file line numberDiff line numberDiff line change
@@ -236,17 +236,49 @@ pub struct PathSegment {
236236
/// this is more than just simple syntactic sugar; the use of
237237
/// parens affects the region binding rules, so we preserve the
238238
/// distinction.
239-
pub parameters: PathParameters,
239+
pub parameters: Option<P<PathParameters>>,
240+
241+
/// Whether to infer remaining type parameters, if any.
242+
/// This only applies to expression and pattern paths, and
243+
/// out of those only the segments with no type parameters
244+
/// to begin with, e.g. `Vec::new` is `<Vec<..>>::new::<..>`.
245+
pub infer_types: bool,
240246
}
241247

242248
impl PathSegment {
243249
/// Convert an identifier to the corresponding segment.
244250
pub fn from_name(name: Name) -> PathSegment {
245251
PathSegment {
246252
name,
247-
parameters: PathParameters::none()
253+
infer_types: true,
254+
parameters: None
255+
}
256+
}
257+
258+
pub fn new(name: Name, parameters: PathParameters, infer_types: bool) -> Self {
259+
PathSegment {
260+
name,
261+
infer_types,
262+
parameters: if parameters.is_empty() {
263+
None
264+
} else {
265+
Some(P(parameters))
266+
}
248267
}
249268
}
269+
270+
// FIXME: hack required because you can't create a static
271+
// PathParameters, so you can't just return a &PathParameters.
272+
pub fn with_parameters<F, R>(&self, f: F) -> R
273+
where F: FnOnce(&PathParameters) -> R
274+
{
275+
let dummy = PathParameters::none();
276+
f(if let Some(ref params) = self.parameters {
277+
&params
278+
} else {
279+
&dummy
280+
})
281+
}
250282
}
251283

252284
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -255,11 +287,6 @@ pub struct PathParameters {
255287
pub lifetimes: HirVec<Lifetime>,
256288
/// The type parameters for this path segment, if present.
257289
pub types: HirVec<P<Ty>>,
258-
/// Whether to infer remaining type parameters, if any.
259-
/// This only applies to expression and pattern paths, and
260-
/// out of those only the segments with no type parameters
261-
/// to begin with, e.g. `Vec::new` is `<Vec<..>>::new::<..>`.
262-
pub infer_types: bool,
263290
/// Bindings (equality constraints) on associated types, if present.
264291
/// E.g., `Foo<A=Bar>`.
265292
pub bindings: HirVec<TypeBinding>,
@@ -274,12 +301,16 @@ impl PathParameters {
274301
Self {
275302
lifetimes: HirVec::new(),
276303
types: HirVec::new(),
277-
infer_types: true,
278304
bindings: HirVec::new(),
279305
parenthesized: false,
280306
}
281307
}
282308

309+
pub fn is_empty(&self) -> bool {
310+
self.lifetimes.is_empty() && self.types.is_empty() &&
311+
self.bindings.is_empty() && !self.parenthesized
312+
}
313+
283314
pub fn inputs(&self) -> &[P<Ty>] {
284315
if self.parenthesized {
285316
if let Some(ref ty) = self.types.get(0) {

src/librustc/hir/print.rs

+34-11
Original file line numberDiff line numberDiff line change
@@ -1213,11 +1213,17 @@ impl<'a> State<'a> {
12131213
self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
12141214
self.s.word(".")?;
12151215
self.print_name(segment.name)?;
1216-
if !segment.parameters.lifetimes.is_empty() ||
1217-
!segment.parameters.types.is_empty() ||
1218-
!segment.parameters.bindings.is_empty() {
1219-
self.print_path_parameters(&segment.parameters, true)?;
1220-
}
1216+
1217+
segment.with_parameters(|parameters| {
1218+
if !parameters.lifetimes.is_empty() ||
1219+
!parameters.types.is_empty() ||
1220+
!parameters.bindings.is_empty()
1221+
{
1222+
self.print_path_parameters(&parameters, segment.infer_types, true)
1223+
} else {
1224+
Ok(())
1225+
}
1226+
})?;
12211227
self.print_call_post(base_args)
12221228
}
12231229

@@ -1564,8 +1570,12 @@ impl<'a> State<'a> {
15641570
}
15651571
if segment.name != keywords::CrateRoot.name() &&
15661572
segment.name != keywords::DollarCrate.name() {
1567-
self.print_name(segment.name)?;
1568-
self.print_path_parameters(&segment.parameters, colons_before_params)?;
1573+
self.print_name(segment.name)?;
1574+
segment.with_parameters(|parameters| {
1575+
self.print_path_parameters(parameters,
1576+
segment.infer_types,
1577+
colons_before_params)
1578+
})?;
15691579
}
15701580
}
15711581

@@ -1593,29 +1603,42 @@ impl<'a> State<'a> {
15931603
if segment.name != keywords::CrateRoot.name() &&
15941604
segment.name != keywords::DollarCrate.name() {
15951605
self.print_name(segment.name)?;
1596-
self.print_path_parameters(&segment.parameters, colons_before_params)?;
1606+
segment.with_parameters(|parameters| {
1607+
self.print_path_parameters(parameters,
1608+
segment.infer_types,
1609+
colons_before_params)
1610+
})?;
15971611
}
15981612
}
15991613

16001614
self.s.word(">")?;
16011615
self.s.word("::")?;
16021616
let item_segment = path.segments.last().unwrap();
16031617
self.print_name(item_segment.name)?;
1604-
self.print_path_parameters(&item_segment.parameters, colons_before_params)
1618+
item_segment.with_parameters(|parameters| {
1619+
self.print_path_parameters(parameters,
1620+
item_segment.infer_types,
1621+
colons_before_params)
1622+
})
16051623
}
16061624
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
16071625
self.s.word("<")?;
16081626
self.print_type(qself)?;
16091627
self.s.word(">")?;
16101628
self.s.word("::")?;
16111629
self.print_name(item_segment.name)?;
1612-
self.print_path_parameters(&item_segment.parameters, colons_before_params)
1630+
item_segment.with_parameters(|parameters| {
1631+
self.print_path_parameters(parameters,
1632+
item_segment.infer_types,
1633+
colons_before_params)
1634+
})
16131635
}
16141636
}
16151637
}
16161638

16171639
fn print_path_parameters(&mut self,
16181640
parameters: &hir::PathParameters,
1641+
infer_types: bool,
16191642
colons_before_params: bool)
16201643
-> io::Result<()> {
16211644
if parameters.parenthesized {
@@ -1652,7 +1675,7 @@ impl<'a> State<'a> {
16521675

16531676
// FIXME(eddyb) This would leak into error messages, e.g.:
16541677
// "non-exhaustive patterns: `Some::<..>(_)` not covered".
1655-
if parameters.infer_types && false {
1678+
if infer_types && false {
16561679
start_or_comma(self)?;
16571680
self.s.word("..")?;
16581681
}

src/librustc/ich/impls_hir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,13 @@ impl_stable_hash_for!(struct hir::Path {
150150

151151
impl_stable_hash_for!(struct hir::PathSegment {
152152
name,
153+
infer_types,
153154
parameters
154155
});
155156

156157
impl_stable_hash_for!(struct hir::PathParameters {
157158
lifetimes,
158159
types,
159-
infer_types,
160160
bindings,
161161
parenthesized
162162
});

src/librustc/middle/resolve_lifetime.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
445445
fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
446446
for (i, segment) in path.segments.iter().enumerate() {
447447
let depth = path.segments.len() - i - 1;
448-
self.visit_segment_parameters(path.def, depth, &segment.parameters);
448+
if let Some(ref parameters) = segment.parameters {
449+
self.visit_segment_parameters(path.def, depth, parameters);
450+
}
449451
}
450452
}
451453

0 commit comments

Comments
 (0)