提交 7a2a669b 编写于 作者: E Eduard-Mihai Burtescu

rustc: always include elidable lifetimes in HIR types.

上级 f79feba2
......@@ -547,8 +547,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
TyPtr(ref mutable_type) => {
visitor.visit_ty(&mutable_type.ty)
}
TyRptr(ref opt_lifetime, ref mutable_type) => {
walk_list!(visitor, visit_lifetime, opt_lifetime);
TyRptr(ref lifetime, ref mutable_type) => {
visitor.visit_lifetime(lifetime);
visitor.visit_ty(&mutable_type.ty)
}
TyNever => {},
......
......@@ -41,12 +41,12 @@
// in the HIR, especially for multiple identifiers.
use hir;
use hir::map::Definitions;
use hir::map::{Definitions, DefKey};
use hir::map::definitions::DefPathData;
use hir::def_id::{DefIndex, DefId};
use hir::def::{Def, PathResolution};
use session::Session;
use util::nodemap::{NodeMap, FxHashMap};
use util::nodemap::{DefIdMap, NodeMap, FxHashMap};
use std::collections::BTreeMap;
use std::iter;
......@@ -78,6 +78,8 @@ pub struct LoweringContext<'a> {
trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
bodies: FxHashMap<hir::BodyId, hir::Body>,
type_def_lifetime_params: DefIdMap<usize>,
}
pub trait Resolver {
......@@ -110,6 +112,7 @@ pub fn lower_crate(sess: &Session,
trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(),
bodies: FxHashMap(),
type_def_lifetime_params: DefIdMap(),
}.lower_crate(krate)
}
......@@ -123,24 +126,33 @@ enum ParamMode {
impl<'a> LoweringContext<'a> {
fn lower_crate(mut self, c: &Crate) -> hir::Crate {
self.lower_items(c);
let module = self.lower_mod(&c.module);
let attrs = self.lower_attrs(&c.attrs);
let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();
/// Full-crate AST visitor that inserts into a fresh
/// `LoweringContext` any information that may be
/// needed from arbitrary locations in the crate.
/// E.g. The number of lifetime generic parameters
/// declared for every type and trait definition.
struct MiscCollector<'lcx, 'interner: 'lcx> {
lctx: &'lcx mut LoweringContext<'interner>,
}
hir::Crate {
module: module,
attrs: attrs,
span: c.span,
exported_macros: exported_macros,
items: self.items,
trait_items: self.trait_items,
impl_items: self.impl_items,
bodies: self.bodies,
impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
fn visit_item(&mut self, item: &'lcx Item) {
match item.node {
ItemKind::Struct(_, ref generics) |
ItemKind::Union(_, ref generics) |
ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) |
ItemKind::Trait(_, ref generics, ..) => {
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
let count = generics.lifetimes.len();
self.lctx.type_def_lifetime_params.insert(def_id, count);
}
_ => {}
}
visit::walk_item(self, item);
}
}
}
fn lower_items(&mut self, c: &Crate) {
struct ItemLowerer<'lcx, 'interner: 'lcx> {
lctx: &'lcx mut LoweringContext<'interner>,
}
......@@ -167,8 +179,23 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
}
}
let mut item_lowerer = ItemLowerer { lctx: self };
visit::walk_crate(&mut item_lowerer, c);
visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
let module = self.lower_mod(&c.module);
let attrs = self.lower_attrs(&c.attrs);
let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();
hir::Crate {
module: module,
attrs: attrs,
span: c.span,
exported_macros: exported_macros,
items: self.items,
trait_items: self.trait_items,
impl_items: self.impl_items,
bodies: self.bodies,
}
}
fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>)
......@@ -232,6 +259,14 @@ fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
result
}
fn def_key(&mut self, id: DefId) -> DefKey {
if id.is_local() {
self.resolver.definitions().def_key(id.index)
} else {
self.sess.cstore.def_key(id)
}
}
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
}
......@@ -279,7 +314,11 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
TyKind::Rptr(ref region, ref mt) => {
hir::TyRptr(self.lower_opt_lifetime(region), self.lower_mt(mt))
let lifetime = match *region {
Some(ref lt) => self.lower_lifetime(lt),
None => self.elided_lifetime(t.span)
};
hir::TyRptr(lifetime, self.lower_mt(mt))
}
TyKind::BareFn(ref f) => {
hir::TyBareFn(P(hir::BareFnTy {
......@@ -377,7 +416,40 @@ fn lower_qpath(&mut self,
}
_ => param_mode
};
self.lower_path_segment(segment, param_mode)
// Figure out if this is a type/trait segment,
// which may need lifetime elision performed.
let parent_def_id = |this: &mut Self, def_id: DefId| {
DefId {
krate: def_id.krate,
index: this.def_key(def_id).parent.expect("missing parent")
}
};
let type_def_id = match resolution.base_def {
Def::AssociatedTy(def_id) if i + 2 == proj_start => {
Some(parent_def_id(self, def_id))
}
Def::Variant(def_id) if i + 1 == proj_start => {
Some(parent_def_id(self, def_id))
}
Def::Struct(def_id) |
Def::Union(def_id) |
Def::Enum(def_id) |
Def::TyAlias(def_id) |
Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
_ => None
};
let num_lifetimes = type_def_id.map_or(0, |def_id| {
if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
return n;
}
assert!(!def_id.is_local());
let (n, _) = self.sess.cstore.item_generics_own_param_counts(def_id);
self.type_def_lifetime_params.insert(def_id, n);
n
});
self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
}).collect(),
span: p.span,
});
......@@ -411,7 +483,7 @@ fn lower_qpath(&mut self,
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
let segment = P(self.lower_path_segment(segment, param_mode));
let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
let qpath = hir::QPath::TypeRelative(ty, segment);
// It's finished, return the extension of the right node type.
......@@ -443,7 +515,7 @@ fn lower_path_extra(&mut self,
hir::Path {
def: self.expect_full_def(id),
segments: segments.map(|segment| {
self.lower_path_segment(segment, param_mode)
self.lower_path_segment(p.span, segment, param_mode, 0)
}).chain(name.map(|name| {
hir::PathSegment {
name: name,
......@@ -464,10 +536,12 @@ fn lower_path(&mut self,
}
fn lower_path_segment(&mut self,
path_span: Span,
segment: &PathSegment,
param_mode: ParamMode)
param_mode: ParamMode,
expected_lifetimes: usize)
-> hir::PathSegment {
let parameters = if let Some(ref parameters) = segment.parameters {
let mut parameters = if let Some(ref parameters) = segment.parameters {
match **parameters {
PathParameters::AngleBracketed(ref data) => {
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
......@@ -482,6 +556,14 @@ fn lower_path_segment(&mut self,
hir::AngleBracketedParameters(data)
};
if let hir::AngleBracketedParameters(ref mut data) = parameters {
if data.lifetimes.is_empty() {
data.lifetimes = (0..expected_lifetimes).map(|_| {
self.elided_lifetime(path_span)
}).collect();
}
}
hir::PathSegment {
name: segment.identifier.name,
parameters: parameters,
......@@ -628,10 +710,6 @@ fn lower_lifetime_defs(&mut self, lts: &Vec<LifetimeDef>) -> hir::HirVec<hir::Li
lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
}
fn lower_opt_lifetime(&mut self, o_lt: &Option<Lifetime>) -> Option<hir::Lifetime> {
o_lt.as_ref().map(|lt| self.lower_lifetime(lt))
}
fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
let mut add_bounds = NodeMap();
......@@ -751,8 +829,12 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
}
fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit) {
hir::QPath::Resolved(None, path) => path.and_then(|path| path),
qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath)
};
hir::TraitRef {
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit, false),
path: path,
ref_id: p.ref_id,
}
}
......@@ -2276,4 +2358,12 @@ fn ty(&mut self, span: Span, node: hir::Ty_) -> P<hir::Ty> {
span: span,
})
}
fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime {
hir::Lifetime {
id: self.next_id(),
span: span,
name: keywords::Invalid.name()
}
}
}
......@@ -77,6 +77,13 @@
pub struct Lifetime {
pub id: NodeId,
pub span: Span,
/// Either "'a", referring to a named lifetime definition,
/// or "" (aka keywords::Invalid), for elision placeholders.
///
/// HIR lowering inserts these placeholders in type paths that
/// refer to type definitions needing lifetime parameters,
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
pub name: Name,
}
......@@ -89,6 +96,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl Lifetime {
pub fn is_elided(&self) -> bool {
self.name == keywords::Invalid.name()
}
}
/// A lifetime definition, eg `'a: 'b+'c+'d`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct LifetimeDef {
......@@ -165,30 +178,6 @@ pub fn none() -> PathParameters {
})
}
pub fn is_empty(&self) -> bool {
match *self {
AngleBracketedParameters(ref data) => data.is_empty(),
// Even if the user supplied no types, something like
// `X()` is equivalent to `X<(),()>`.
ParenthesizedParameters(..) => false,
}
}
pub fn has_lifetimes(&self) -> bool {
match *self {
AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(),
ParenthesizedParameters(_) => false,
}
}
pub fn has_types(&self) -> bool {
match *self {
AngleBracketedParameters(ref data) => !data.types.is_empty(),
ParenthesizedParameters(..) => true,
}
}
/// Returns the types that the user wrote. Note that these do not necessarily map to the type
/// parameters in the parenthesized case.
pub fn types(&self) -> HirVec<&P<Ty>> {
......@@ -245,12 +234,6 @@ pub struct AngleBracketedParameterData {
pub bindings: HirVec<TypeBinding>,
}
impl AngleBracketedParameterData {
fn is_empty(&self) -> bool {
self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
}
}
/// A path like `Foo(A,B) -> C`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct ParenthesizedParameterData {
......@@ -1208,7 +1191,7 @@ pub enum Ty_ {
/// A raw pointer (`*const T` or `*mut T`)
TyPtr(MutTy),
/// A reference (`&'a T` or `&'a mut T`)
TyRptr(Option<Lifetime>, MutTy),
TyRptr(Lifetime, MutTy),
/// A bare function (e.g. `fn(usize) -> bool`)
TyBareFn(P<BareFnTy>),
/// The never type (`!`)
......
......@@ -26,6 +26,7 @@
use hir;
use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
use std::cell::Cell;
use std::io::{self, Write, Read};
pub enum AnnNode<'a> {
......@@ -359,9 +360,9 @@ pub fn print_foreign_mod(&mut self,
Ok(())
}
pub fn print_opt_lifetime(&mut self, lifetime: &Option<hir::Lifetime>) -> io::Result<()> {
if let Some(l) = *lifetime {
self.print_lifetime(&l)?;
pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
if !lifetime.is_elided() {
self.print_lifetime(lifetime)?;
self.nbsp()?;
}
Ok(())
......@@ -1553,65 +1554,49 @@ fn print_path_parameters(&mut self,
parameters: &hir::PathParameters,
colons_before_params: bool)
-> io::Result<()> {
if parameters.is_empty() {
let infer_types = match *parameters {
hir::AngleBracketedParameters(ref data) => data.infer_types,
hir::ParenthesizedParameters(_) => false
};
// FIXME(eddyb) See the comment below about infer_types.
if !(infer_types && false) {
return Ok(());
}
}
if colons_before_params {
word(&mut self.s, "::")?
}
match *parameters {
hir::AngleBracketedParameters(ref data) => {
word(&mut self.s, "<")?;
let start = if colons_before_params { "::<" } else { "<" };
let empty = Cell::new(true);
let start_or_comma = |this: &mut Self| {
if empty.get() {
empty.set(false);
word(&mut this.s, start)
} else {
this.word_space(",")
}
};
let mut comma = false;
for lifetime in &data.lifetimes {
if comma {
self.word_space(",")?
if !data.lifetimes.iter().all(|lt| lt.is_elided()) {
for lifetime in &data.lifetimes {
start_or_comma(self)?;
self.print_lifetime(lifetime)?;
}
self.print_lifetime(lifetime)?;
comma = true;
}
if !data.types.is_empty() {
if comma {
self.word_space(",")?
}
start_or_comma(self)?;
self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
comma = true;
}
// FIXME(eddyb) This would leak into error messages, e.g.:
// "non-exhaustive patterns: `Some::<..>(_)` not covered".
if data.infer_types && false {
if comma {
self.word_space(",")?
}
start_or_comma(self)?;
word(&mut self.s, "..")?;
comma = true;
}
for binding in data.bindings.iter() {
if comma {
self.word_space(",")?
}
start_or_comma(self)?;
self.print_name(binding.name)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&binding.ty)?;
comma = true;
}
word(&mut self.s, ">")?
if !empty.get() {
word(&mut self.s, ">")?
}
}
hir::ParenthesizedParameters(ref data) => {
......
......@@ -182,6 +182,7 @@ fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::Generics<'tcx>;
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize);
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef;
fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef;
......@@ -331,6 +332,8 @@ fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::Generics<'tcx> { bug!("item_generics") }
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize)
{ bug!("item_generics_own_param_counts") }
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef
{ bug!("trait_def") }
......
......@@ -279,6 +279,9 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
}
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
if lifetime_ref.is_elided() {
return;
}
if lifetime_ref.name == keywords::StaticLifetime.name() {
self.insert_lifetime(lifetime_ref, DefStaticRegion);
return;
......
......@@ -939,12 +939,12 @@ pub fn report_aliasability_violation(&self,
/// Given a type, if it is an immutable reference, return a suggestion to make it mutable
fn suggest_mut_for_immutable(&self, pty: &hir::Ty) -> Option<String> {
// Check wether the argument is an immutable reference
if let hir::TyRptr(opt_lifetime, hir::MutTy {
if let hir::TyRptr(lifetime, hir::MutTy {
mutbl: hir::Mutability::MutImmutable,
ref ty
}) = pty.node {
// Account for existing lifetimes when generating the message
if let Some(lifetime) = opt_lifetime {
if !lifetime.is_elided() {
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(ty.span) {
if let Ok(lifetime_snippet) = self.tcx.sess.codemap()
.span_to_snippet(lifetime.span) {
......
......@@ -377,8 +377,8 @@ fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
// Lint for constants that look like binding identifiers (#7526)
if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
if path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
if let Def::Const(..) = path.def {
if let Def::Const(..) = path.def {
if path.segments.len() == 1 {
NonUpperCaseGlobals::check_upper_case(cx,
"constant in pattern",
path.segments[0].name,
......
......@@ -110,6 +110,11 @@ fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
self.get_crate_data(def.krate).get_generics(def.index, tcx)
}
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize) {
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).generics_own_param_counts(def.index)
}
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
{
self.dep_graph.read(DepNode::MetaData(def_id));
......
......@@ -598,7 +598,20 @@ pub fn get_generics(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::Generics<'tcx> {
self.entry(item_id).generics.unwrap().decode((self, tcx))
let g = self.entry(item_id).generics.unwrap().decode(self);
ty::Generics {
parent: g.parent,
parent_regions: g.parent_regions,
parent_types: g.parent_types,
regions: g.regions.decode((self, tcx)).collect(),
types: g.types.decode((self, tcx)).collect(),
has_self: g.has_self,
}
}
pub fn generics_own_param_counts(&self, item_id: DefIndex) -> (usize, usize) {
let g = self.entry(item_id).generics.unwrap().decode(self);
(g.regions.len, g.types.len)
}
pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
......
......@@ -417,9 +417,19 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
}
}
fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics<'tcx>> {
fn encode_generics(&mut self, def_id: DefId) -> Lazy<Generics<'tcx>> {
let tcx = self.tcx;
self.lazy(tcx.item_generics(def_id))
let g = tcx.item_generics(def_id);
let regions = self.lazy_seq_ref(&g.regions);
let types = self.lazy_seq_ref(&g.types);
self.lazy(&Generics {
parent: g.parent,
parent_regions: g.parent_regions,
parent_types: g.parent_types,
regions: regions,
types: types,
has_self: g.has_self,
})
}
fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
......
......@@ -213,7 +213,7 @@ pub struct Entry<'tcx> {
pub ty: Option<Lazy<Ty<'tcx>>>,
pub inherent_impls: LazySeq<DefIndex>,
pub variances: LazySeq<ty::Variance>,
pub generics: Option<Lazy<ty::Generics<'tcx>>>,
pub generics: Option<Lazy<Generics<'tcx>>>,
pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
......@@ -247,6 +247,19 @@ pub enum EntryKind<'tcx> {
AssociatedConst(AssociatedContainer),
}
/// A copy of `ty::Generics` which allows lazy decoding of
/// `regions` and `types` (e.g. knowing the number of type
/// and lifetime parameters before `TyCtxt` is created).
#[derive(RustcEncodable, RustcDecodable)]
pub struct Generics<'tcx> {
pub parent: Option<DefId>,
pub parent_regions: u32,
pub parent_types: u32,
pub regions: LazySeq<ty::RegionParameterDef<'tcx>>,
pub types: LazySeq<ty::TypeParameterDef<'tcx>>,
pub has_self: bool,
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct ModData {
pub reexports: LazySeq<def::Export>,
......
......@@ -404,19 +404,20 @@ fn create_substs_for_ast_path(&self,
};
let expected_num_region_params = decl_generics.regions.len();
let supplied_num_region_params = lifetimes.len();
let has_exact_lifetimes = expected_num_region_params == supplied_num_region_params;
let mut can_report_lifetime_count_mismatch = !has_exact_lifetimes;
let mut maybe_report_lifetime_count_mismatch = || {
if can_report_lifetime_count_mismatch {
can_report_lifetime_count_mismatch = false;
let mut reported_lifetime_count_mismatch = false;
let mut report_lifetime_count_mismatch = || {
if !reported_lifetime_count_mismatch {
reported_lifetime_count_mismatch = true;
let all_infer = lifetimes.iter().all(|lt| lt.is_elided());
let supplied = if all_infer { 0 } else { supplied_num_region_params };
report_lifetime_number_error(tcx, span,
supplied_num_region_params,
supplied,
expected_num_region_params);
}
};
if supplied_num_region_params != 0 {
maybe_report_lifetime_count_mismatch();
if expected_num_region_params != supplied_num_region_params {
report_lifetime_count_mismatch();
}
// If a self-type was declared, one should be provided.
......@@ -444,13 +445,9 @@ fn create_substs_for_ast_path(&self,
let mut output_assoc_binding = None;
let substs = Substs::for_item(tcx, def_id, |def, _| {
let i = def.index as usize - self_ty.is_some() as usize;
let l = if has_exact_lifetimes {
Some(&lifetimes[i])
} else {
None
};
let l = lifetimes.get(i);
self.try_opt_ast_region_to_region(rscope, span, l, Some(def)).unwrap_or_else(|_| {
maybe_report_lifetime_count_mismatch();
report_lifetime_count_mismatch();
tcx.mk_region(ty::ReStatic)
})
}, |def, substs| {
......@@ -1472,7 +1469,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
})
}
hir::TyRptr(ref region, ref mt) => {
let r = self.opt_ast_region_to_region(rscope, ast_ty.span, region.as_ref(), None);
let r = self.opt_ast_region_to_region(rscope, ast_ty.span, Some(region), None);
debug!("TyRef r={:?}", r);
let rscope1 =
&ObjectLifetimeDefaultRscope::new(
......
......@@ -1688,9 +1688,15 @@ fn clean(&self, cx: &DocContext) -> Type {
match self.node {
TyNever => Never,
TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
TyRptr(ref l, ref m) =>
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
type_: box m.ty.clean(cx)},
TyRptr(ref l, ref m) => {
let lifetime = if l.is_elided() {
None
} else {
Some(l.clean(cx))
};
BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx),
type_: box m.ty.clean(cx)}
}
TySlice(ref ty) => Vector(box ty.clean(cx)),
TyArray(ref ty, length) => {
use rustc_const_eval::eval_length;
......@@ -1729,7 +1735,9 @@ fn clean(&self, cx: &DocContext) -> Type {
for (i, lt_param) in generics.lifetimes.iter().enumerate() {
if let Some(lt) = provided_params.lifetimes().get(i).cloned()
.cloned() {
lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
if !lt.is_elided() {
lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
}
}
}
return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
......@@ -2242,7 +2250,11 @@ fn clean(&self, cx: &DocContext) -> PathParameters {
match *self {
hir::AngleBracketedParameters(ref data) => {
PathParameters::AngleBracketed {
lifetimes: data.lifetimes.clean(cx),
lifetimes: if data.lifetimes.iter().all(|lt| lt.is_elided()) {
vec![]
} else {
data.lifetimes.clean(cx)
},
types: data.types.clean(cx),
bindings: data.bindings.clean(cx)
}
......
......@@ -38,9 +38,9 @@ fn test<'a,'b>() {
}
fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
//~^ ERROR wrong number of lifetime parameters: expected 1, found 0
// Here, the omitted lifetimes are expanded to distinct things.
same_type(x, y) //~ ERROR cannot infer
//~^ ERROR cannot infer
same_type(x, y)
}
fn main() { }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册