mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
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
This commit is contained in:
commit
48c1c548e1
@ -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,
|
||||
|
@ -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,
|
||||
})))
|
||||
}
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
@ -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) => {
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -970,29 +965,29 @@ 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| {
|
||||
@ -1000,10 +995,9 @@ impl<'a> LoweringContext<'a> {
|
||||
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),
|
||||
@ -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> {
|
||||
|
@ -236,7 +236,13 @@ 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 {
|
||||
@ -244,9 +250,35 @@ impl PathSegment {
|
||||
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 {
|
||||
¶ms
|
||||
} else {
|
||||
&dummy
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
@ -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>,
|
||||
@ -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) {
|
||||
|
@ -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(¶meters, segment.infer_types, true)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})?;
|
||||
self.print_call_post(base_args)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1593,7 +1603,11 @@ 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)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1601,7 +1615,11 @@ impl<'a> State<'a> {
|
||||
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("<")?;
|
||||
@ -1609,13 +1627,18 @@ impl<'a> State<'a> {
|
||||
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 {
|
||||
@ -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("..")?;
|
||||
}
|
||||
|
@ -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
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,11 +157,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
item_segment: &hir::PathSegment)
|
||||
-> &'tcx Substs<'tcx>
|
||||
{
|
||||
|
||||
let (substs, assoc_bindings) =
|
||||
self.create_substs_for_ast_path(span,
|
||||
def_id,
|
||||
&item_segment.parameters,
|
||||
None);
|
||||
item_segment.with_parameters(|parameters| {
|
||||
self.create_substs_for_ast_path(
|
||||
span,
|
||||
def_id,
|
||||
parameters,
|
||||
item_segment.infer_types,
|
||||
None)
|
||||
});
|
||||
|
||||
assoc_bindings.first().map(|b| self.prohibit_projection(b.span));
|
||||
|
||||
@ -177,6 +182,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
span: Span,
|
||||
def_id: DefId,
|
||||
parameters: &hir::PathParameters,
|
||||
infer_types: bool,
|
||||
self_ty: Option<Ty<'tcx>>)
|
||||
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
|
||||
{
|
||||
@ -204,7 +210,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
// Check the number of type parameters supplied by the user.
|
||||
let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
|
||||
if !parameters.infer_types || num_types_provided > ty_param_defs.len() {
|
||||
if !infer_types || num_types_provided > ty_param_defs.len() {
|
||||
check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
|
||||
}
|
||||
|
||||
@ -240,7 +246,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
if i < num_types_provided {
|
||||
// A provided type parameter.
|
||||
self.ast_ty_to_ty(¶meters.types[i])
|
||||
} else if parameters.infer_types {
|
||||
} else if infer_types {
|
||||
// No type parameters were provided, we can infer all.
|
||||
let ty_var = if !default_needs_object_self(def) {
|
||||
self.ty_infer_for_def(def, substs, span)
|
||||
@ -390,7 +396,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
let trait_def = self.tcx().trait_def(trait_def_id);
|
||||
|
||||
if !self.tcx().sess.features.borrow().unboxed_closures &&
|
||||
trait_segment.parameters.parenthesized != trait_def.paren_sugar {
|
||||
trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar {
|
||||
// For now, require that parenthetical notation be used only with `Fn()` etc.
|
||||
let msg = if trait_def.paren_sugar {
|
||||
"the precise format of `Fn`-family traits' type parameters is subject to change. \
|
||||
@ -402,10 +408,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
span, GateIssue::Language, msg);
|
||||
}
|
||||
|
||||
self.create_substs_for_ast_path(span,
|
||||
trait_def_id,
|
||||
&trait_segment.parameters,
|
||||
Some(self_ty))
|
||||
trait_segment.with_parameters(|parameters| {
|
||||
self.create_substs_for_ast_path(span,
|
||||
trait_def_id,
|
||||
parameters,
|
||||
trait_segment.infer_types,
|
||||
Some(self_ty))
|
||||
})
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(&self,
|
||||
@ -876,25 +885,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
|
||||
for segment in segments {
|
||||
for typ in &segment.parameters.types {
|
||||
struct_span_err!(self.tcx().sess, typ.span, E0109,
|
||||
"type parameters are not allowed on this type")
|
||||
.span_label(typ.span, "type parameter not allowed")
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
for lifetime in &segment.parameters.lifetimes {
|
||||
struct_span_err!(self.tcx().sess, lifetime.span, E0110,
|
||||
"lifetime parameters are not allowed on this type")
|
||||
.span_label(lifetime.span,
|
||||
"lifetime parameter not allowed on this type")
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
for binding in &segment.parameters.bindings {
|
||||
self.prohibit_projection(binding.span);
|
||||
break;
|
||||
}
|
||||
segment.with_parameters(|parameters| {
|
||||
for typ in ¶meters.types {
|
||||
struct_span_err!(self.tcx().sess, typ.span, E0109,
|
||||
"type parameters are not allowed on this type")
|
||||
.span_label(typ.span, "type parameter not allowed")
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
for lifetime in ¶meters.lifetimes {
|
||||
struct_span_err!(self.tcx().sess, lifetime.span, E0110,
|
||||
"lifetime parameters are not allowed on this type")
|
||||
.span_label(lifetime.span,
|
||||
"lifetime parameter not allowed on this type")
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
for binding in ¶meters.bindings {
|
||||
self.prohibit_projection(binding.span);
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -978,12 +989,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
Def::Err => {
|
||||
for segment in &path.segments {
|
||||
for ty in &segment.parameters.types {
|
||||
self.ast_ty_to_ty(ty);
|
||||
}
|
||||
for binding in &segment.parameters.bindings {
|
||||
self.ast_ty_to_ty(&binding.ty);
|
||||
}
|
||||
segment.with_parameters(|parameters| {
|
||||
for ty in ¶meters.types {
|
||||
self.ast_ty_to_ty(ty);
|
||||
}
|
||||
for binding in ¶meters.bindings {
|
||||
self.ast_ty_to_ty(&binding.ty);
|
||||
}
|
||||
});
|
||||
}
|
||||
self.set_tainted_by_errors();
|
||||
return self.tcx().types.err;
|
||||
@ -1314,15 +1327,16 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
if Some(trait_did) == tcx.lang_items().send_trait() ||
|
||||
Some(trait_did) == tcx.lang_items().sync_trait() {
|
||||
let segments = &bound.trait_ref.path.segments;
|
||||
let parameters = &segments[segments.len() - 1].parameters;
|
||||
if !parameters.types.is_empty() {
|
||||
check_type_argument_count(tcx, bound.trait_ref.path.span,
|
||||
parameters.types.len(), &[]);
|
||||
}
|
||||
if !parameters.lifetimes.is_empty() {
|
||||
report_lifetime_number_error(tcx, bound.trait_ref.path.span,
|
||||
parameters.lifetimes.len(), 0);
|
||||
}
|
||||
segments[segments.len() - 1].with_parameters(|parameters| {
|
||||
if !parameters.types.is_empty() {
|
||||
check_type_argument_count(tcx, bound.trait_ref.path.span,
|
||||
parameters.types.len(), &[]);
|
||||
}
|
||||
if !parameters.lifetimes.is_empty() {
|
||||
report_lifetime_number_error(tcx, bound.trait_ref.path.span,
|
||||
parameters.lifetimes.len(), 0);
|
||||
}
|
||||
});
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -300,7 +300,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
if i < parent_substs.len() {
|
||||
parent_substs.region_at(i)
|
||||
} else if let Some(lifetime)
|
||||
= provided.lifetimes.get(i - parent_substs.len()) {
|
||||
= provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) {
|
||||
AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
|
||||
} else {
|
||||
self.region_var_for_def(self.span, def)
|
||||
@ -310,7 +310,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
if i < parent_substs.len() {
|
||||
parent_substs.type_at(i)
|
||||
} else if let Some(ast_ty)
|
||||
= provided.types.get(i - parent_substs.len() - method_generics.regions.len()) {
|
||||
= provided.as_ref().and_then(|p| {
|
||||
p.types.get(i - parent_substs.len() - method_generics.regions.len())
|
||||
})
|
||||
{
|
||||
self.to_ty(ast_ty)
|
||||
} else {
|
||||
self.type_var_for_def(self.span, def, cur_substs)
|
||||
|
@ -4668,7 +4668,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
i -= fn_start;
|
||||
fn_segment
|
||||
};
|
||||
let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]);
|
||||
let lifetimes = segment.map_or(&[][..], |(s, _)| {
|
||||
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
|
||||
});
|
||||
|
||||
if let Some(lifetime) = lifetimes.get(i) {
|
||||
AstConv::ast_region_to_region(self, lifetime, Some(def))
|
||||
@ -4692,7 +4694,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
fn_segment
|
||||
};
|
||||
let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
|
||||
(&s.parameters.types[..], s.parameters.infer_types)
|
||||
(s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
|
||||
});
|
||||
|
||||
// Skip over the lifetimes in the same segment.
|
||||
@ -4769,8 +4771,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
is_method_call: bool) {
|
||||
let (lifetimes, types, infer_types, bindings) = segment.map_or(
|
||||
(&[][..], &[][..], true, &[][..]),
|
||||
|(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..],
|
||||
s.parameters.infer_types, &s.parameters.bindings[..]));
|
||||
|(s, _)| s.parameters.as_ref().map_or(
|
||||
(&[][..], &[][..], s.infer_types, &[][..]),
|
||||
|p| (&p.lifetimes[..], &p.types[..],
|
||||
s.infer_types, &p.bindings[..])));
|
||||
let infer_lifetimes = lifetimes.len() == 0;
|
||||
|
||||
let count_lifetime_params = |n| {
|
||||
|
@ -1852,25 +1852,27 @@ impl Clean<Type> for hir::Ty {
|
||||
};
|
||||
|
||||
if let Some(&hir::ItemTy(ref ty, ref generics)) = alias {
|
||||
let provided_params = &path.segments.last().unwrap().parameters;
|
||||
let provided_params = &path.segments.last().unwrap();
|
||||
let mut ty_substs = FxHashMap();
|
||||
let mut lt_substs = FxHashMap();
|
||||
for (i, ty_param) in generics.ty_params.iter().enumerate() {
|
||||
let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
|
||||
if let Some(ty) = provided_params.types.get(i).cloned() {
|
||||
ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
|
||||
} else if let Some(default) = ty_param.default.clone() {
|
||||
ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
|
||||
}
|
||||
}
|
||||
for (i, lt_param) in generics.lifetimes.iter().enumerate() {
|
||||
if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
|
||||
if !lt.is_elided() {
|
||||
let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
|
||||
lt_substs.insert(lt_def_id, lt.clean(cx));
|
||||
provided_params.with_parameters(|provided_params| {
|
||||
for (i, ty_param) in generics.ty_params.iter().enumerate() {
|
||||
let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
|
||||
if let Some(ty) = provided_params.types.get(i).cloned() {
|
||||
ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
|
||||
} else if let Some(default) = ty_param.default.clone() {
|
||||
ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i, lt_param) in generics.lifetimes.iter().enumerate() {
|
||||
if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
|
||||
if !lt.is_elided() {
|
||||
let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
|
||||
lt_substs.insert(lt_def_id, lt.clean(cx));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
|
||||
}
|
||||
resolve_type(cx, path.clean(cx), self.id)
|
||||
@ -2419,7 +2421,7 @@ impl Clean<PathSegment> for hir::PathSegment {
|
||||
fn clean(&self, cx: &DocContext) -> PathSegment {
|
||||
PathSegment {
|
||||
name: self.name.clean(cx),
|
||||
params: self.parameters.clean(cx)
|
||||
params: self.with_parameters(|parameters| parameters.clean(cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user