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

put empty generic lists behind a pointer #44758

Merged
merged 1 commit into from
Sep 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
path_span: Span,
segment: &'v PathSegment) {
visitor.visit_name(path_span, segment.name);
visitor.visit_path_parameters(path_span, &segment.parameters);
if let Some(ref parameters) = segment.parameters {
visitor.visit_path_parameters(path_span, parameters);
}
}

pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
Expand Down
42 changes: 18 additions & 24 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,10 +690,9 @@ impl<'a> LoweringContext<'a> {
TyKind::ImplicitSelf => {
hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
def: self.expect_full_def(t.id),
segments: hir_vec![hir::PathSegment {
name: keywords::SelfType.name(),
parameters: hir::PathParameters::none()
}],
segments: hir_vec![
hir::PathSegment::from_name(keywords::SelfType.name())
],
span: t.span,
})))
}
Expand Down Expand Up @@ -914,12 +913,8 @@ impl<'a> LoweringContext<'a> {
segments: segments.map(|segment| {
self.lower_path_segment(p.span, segment, param_mode, 0,
ParenthesizedGenericArgs::Err)
}).chain(name.map(|name| {
hir::PathSegment {
name,
parameters: hir::PathParameters::none()
}
})).collect(),
}).chain(name.map(|name| hir::PathSegment::from_name(name)))
.collect(),
span: p.span,
}
}
Expand All @@ -940,7 +935,7 @@ impl<'a> LoweringContext<'a> {
expected_lifetimes: usize,
parenthesized_generic_args: ParenthesizedGenericArgs)
-> hir::PathSegment {
let mut parameters = if let Some(ref parameters) = segment.parameters {
let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
let msg = "parenthesized parameters may only be used with a trait";
match **parameters {
PathParameters::AngleBracketed(ref data) => {
Expand All @@ -951,12 +946,12 @@ impl<'a> LoweringContext<'a> {
ParenthesizedGenericArgs::Warn => {
self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
CRATE_NODE_ID, data.span, msg.into());
hir::PathParameters::none()
(hir::PathParameters::none(), true)
}
ParenthesizedGenericArgs::Err => {
struct_span_err!(self.sess, data.span, E0214, "{}", msg)
.span_label(data.span, "only traits may use parentheses").emit();
hir::PathParameters::none()
(hir::PathParameters::none(), true)
}
}
}
Expand All @@ -970,40 +965,39 @@ impl<'a> LoweringContext<'a> {
}).collect();
}

hir::PathSegment {
name: self.lower_ident(segment.identifier),
hir::PathSegment::new(
self.lower_ident(segment.identifier),
parameters,
}
infer_types
)
}

fn lower_angle_bracketed_parameter_data(&mut self,
data: &AngleBracketedParameterData,
param_mode: ParamMode)
-> hir::PathParameters {
-> (hir::PathParameters, bool) {
let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
hir::PathParameters {
(hir::PathParameters {
lifetimes: self.lower_lifetimes(lifetimes),
types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
infer_types: types.is_empty() && param_mode == ParamMode::Optional,
bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
parenthesized: false,
}
}, types.is_empty() && param_mode == ParamMode::Optional)
}

fn lower_parenthesized_parameter_data(&mut self,
data: &ParenthesizedParameterData)
-> hir::PathParameters {
-> (hir::PathParameters, bool) {
let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect();
let mk_tup = |this: &mut Self, tys, span| {
let LoweredNodeId { node_id, hir_id } = this.next_id();
P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span })
};

hir::PathParameters {
(hir::PathParameters {
lifetimes: hir::HirVec::new(),
types: hir_vec![mk_tup(self, inputs, span)],
infer_types: false,
bindings: hir_vec![hir::TypeBinding {
id: self.next_id().node_id,
name: Symbol::intern(FN_OUTPUT_NAME),
Expand All @@ -1012,7 +1006,7 @@ impl<'a> LoweringContext<'a> {
span: output.as_ref().map_or(span, |ty| ty.span),
}],
parenthesized: true,
}
}, false)
}

fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
Expand Down
47 changes: 39 additions & 8 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,17 +236,49 @@ pub struct PathSegment {
/// this is more than just simple syntactic sugar; the use of
/// parens affects the region binding rules, so we preserve the
/// distinction.
pub parameters: PathParameters,
pub parameters: Option<P<PathParameters>>,

/// Whether to infer remaining type parameters, if any.
/// This only applies to expression and pattern paths, and
/// out of those only the segments with no type parameters
/// to begin with, e.g. `Vec::new` is `<Vec<..>>::new::<..>`.
pub infer_types: bool,
}

impl PathSegment {
/// Convert an identifier to the corresponding segment.
pub fn from_name(name: Name) -> PathSegment {
PathSegment {
name,
parameters: PathParameters::none()
infer_types: true,
parameters: None
}
}

pub fn new(name: Name, parameters: PathParameters, infer_types: bool) -> Self {
PathSegment {
name,
infer_types,
parameters: if parameters.is_empty() {
None
} else {
Some(P(parameters))
}
}
}

// FIXME: hack required because you can't create a static
// PathParameters, so you can't just return a &PathParameters.
pub fn with_parameters<F, R>(&self, f: F) -> R
where F: FnOnce(&PathParameters) -> R
{
let dummy = PathParameters::none();
f(if let Some(ref params) = self.parameters {
&params
} else {
&dummy
})
}
}

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

pub fn is_empty(&self) -> bool {
self.lifetimes.is_empty() && self.types.is_empty() &&
self.bindings.is_empty() && !self.parenthesized
}

pub fn inputs(&self) -> &[P<Ty>] {
if self.parenthesized {
if let Some(ref ty) = self.types.get(0) {
Expand Down
45 changes: 34 additions & 11 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1213,11 +1213,17 @@ impl<'a> State<'a> {
self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
self.s.word(".")?;
self.print_name(segment.name)?;
if !segment.parameters.lifetimes.is_empty() ||
!segment.parameters.types.is_empty() ||
!segment.parameters.bindings.is_empty() {
self.print_path_parameters(&segment.parameters, true)?;
}

segment.with_parameters(|parameters| {
if !parameters.lifetimes.is_empty() ||
!parameters.types.is_empty() ||
!parameters.bindings.is_empty()
{
self.print_path_parameters(&parameters, segment.infer_types, true)
} else {
Ok(())
}
})?;
self.print_call_post(base_args)
}

Expand Down Expand Up @@ -1564,8 +1570,12 @@ impl<'a> State<'a> {
}
if segment.name != keywords::CrateRoot.name() &&
segment.name != keywords::DollarCrate.name() {
self.print_name(segment.name)?;
self.print_path_parameters(&segment.parameters, colons_before_params)?;
self.print_name(segment.name)?;
segment.with_parameters(|parameters| {
self.print_path_parameters(parameters,
segment.infer_types,
colons_before_params)
})?;
}
}

Expand Down Expand Up @@ -1593,29 +1603,42 @@ impl<'a> State<'a> {
if segment.name != keywords::CrateRoot.name() &&
segment.name != keywords::DollarCrate.name() {
self.print_name(segment.name)?;
self.print_path_parameters(&segment.parameters, colons_before_params)?;
segment.with_parameters(|parameters| {
self.print_path_parameters(parameters,
segment.infer_types,
colons_before_params)
})?;
}
}

self.s.word(">")?;
self.s.word("::")?;
let item_segment = path.segments.last().unwrap();
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
item_segment.with_parameters(|parameters| {
self.print_path_parameters(parameters,
item_segment.infer_types,
colons_before_params)
})
}
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
self.s.word("<")?;
self.print_type(qself)?;
self.s.word(">")?;
self.s.word("::")?;
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
item_segment.with_parameters(|parameters| {
self.print_path_parameters(parameters,
item_segment.infer_types,
colons_before_params)
})
}
}
}

fn print_path_parameters(&mut self,
parameters: &hir::PathParameters,
infer_types: bool,
colons_before_params: bool)
-> io::Result<()> {
if parameters.parenthesized {
Expand Down Expand Up @@ -1652,7 +1675,7 @@ impl<'a> State<'a> {

// FIXME(eddyb) This would leak into error messages, e.g.:
// "non-exhaustive patterns: `Some::<..>(_)` not covered".
if parameters.infer_types && false {
if infer_types && false {
start_or_comma(self)?;
self.s.word("..")?;
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,13 @@ impl_stable_hash_for!(struct hir::Path {

impl_stable_hash_for!(struct hir::PathSegment {
name,
infer_types,
parameters
});

impl_stable_hash_for!(struct hir::PathParameters {
lifetimes,
types,
infer_types,
bindings,
parenthesized
});
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
self.visit_segment_parameters(path.def, depth, &segment.parameters);
if let Some(ref parameters) = segment.parameters {
self.visit_segment_parameters(path.def, depth, parameters);
}
}
}

Expand Down
Loading