Fix pretty-printer test failure by carrying the bound lifetime names through

the types.  Initially I thought it would be necessary to thread this data
through not only the AST but the types themselves, but then I remembered that
the pretty printer only cares about the AST.  Regardless, I have elected to
leave the changes to the types intact since they will eventually be needed.  I
left a few FIXMEs where it didn't seem worth finishing up since the code wasn't
crucial yet.
This commit is contained in:
Niko Matsakis 2013-03-27 12:55:18 -04:00 committed by Graydon Hoare
parent 83aa70d7e3
commit 2a74fda316
14 changed files with 130 additions and 100 deletions

View File

@ -24,6 +24,7 @@ use core::vec;
use syntax::ast;
use syntax::ast::*;
use syntax::codemap::{respan, dummy_sp};
use syntax::opt_vec;
// Compact string representation for ty::t values. API ty_str &
// parse_from_str. Extra parameters are for converting to/from def_ids in the
@ -479,7 +480,9 @@ fn parse_sig(st: @mut PState, conv: conv_did) -> ty::FnSig {
}
st.pos += 1u; // eat the ']'
let ret_ty = parse_ty(st, conv);
ty::FnSig {inputs: inputs, output: ret_ty}
ty::FnSig {bound_lifetime_names: opt_vec::Empty, // FIXME(#4846)
inputs: inputs,
output: ret_ty}
}
// Rust metadata parsing

View File

@ -40,6 +40,7 @@ use util::ppaux::ty_to_str;
use syntax::codemap::span;
use syntax::{ast, ast_util};
use syntax::{attr, ast_map};
use syntax::opt_vec;
use syntax::parse::token::special_idents;
fn abi_info(arch: session::arch) -> @cabi::ABIInfo {
@ -615,7 +616,8 @@ pub fn trans_intrinsic(ccx: @CrateContext,
sigil: ast::BorrowedSigil,
onceness: ast::Many,
region: ty::re_bound(ty::br_anon(0)),
sig: FnSig {inputs: ~[arg {mode: ast::expl(ast::by_copy),
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: ~[arg {mode: ast::expl(ast::by_copy),
ty: star_u8}],
output: ty::mk_nil(bcx.tcx())}
});

View File

@ -37,6 +37,7 @@ use syntax::ast;
use syntax::ast_map;
use syntax::ast_map::{path, path_mod, path_name};
use syntax::ast_util::local_def;
use syntax::opt_vec;
use syntax::parse::token::special_idents;
pub fn monomorphic_fn(ccx: @CrateContext,
@ -282,7 +283,8 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
ty::BareFnTy {
purity: ast::impure_fn,
abi: ast::RustAbi,
sig: FnSig {inputs: ~[],
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: ~[],
output: ty::mk_nil(tcx)}}))
}
ty::ty_closure(ref fty) => {
@ -316,7 +318,8 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
sigil: sigil,
onceness: ast::Many,
region: ty::re_static,
sig: ty::FnSig {inputs: ~[],
sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: ~[],
output: ty::mk_nil(tcx)}})
}
}

View File

@ -45,6 +45,8 @@ use syntax::codemap::span;
use syntax::codemap;
use syntax::print::pprust;
use syntax::{ast, ast_map};
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax;
// Data types
@ -376,10 +378,12 @@ pub struct ClosureTy {
* Signature of a function type, which I have arbitrarily
* decided to use to refer to the input/output types.
*
* - `lifetimes` is the list of region names bound in this fn.
* - `inputs` is the list of arguments and their modes.
* - `output` is the return type. */
#[deriving(Eq)]
pub struct FnSig {
bound_lifetime_names: OptVec<ast::ident>,
inputs: ~[arg],
output: t
}
@ -1062,7 +1066,8 @@ pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
BareFnTy {
purity: ast::pure_fn,
abi: ast::RustAbi,
sig: FnSig {inputs: input_args,
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: input_args,
output: output}})
}
@ -1203,6 +1208,7 @@ pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
};
FnSig {
bound_lifetime_names: copy sig.bound_lifetime_names,
inputs: args,
output: fldop(sig.output)
}

View File

@ -58,7 +58,7 @@ use middle::const_eval;
use middle::ty::{arg, field, substs};
use middle::ty::{ty_param_substs_and_ty};
use middle::ty;
use middle::typeck::rscope::{in_binding_rscope, in_binding_rscope_ext};
use middle::typeck::rscope::{in_binding_rscope};
use middle::typeck::rscope::{region_scope, type_rscope, RegionError};
use middle::typeck::rscope::{RegionParamNames};
@ -67,6 +67,7 @@ use core::vec;
use syntax::{ast, ast_util};
use syntax::codemap::span;
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax::print::pprust::{lifetime_to_str, path_to_str};
use syntax::parse::token::special_idents;
use util::common::indenter;
@ -347,7 +348,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
}
ast::ty_bare_fn(ref bf) => {
ty::mk_bare_fn(tcx, ty_of_bare_fn(self, rscope, bf.purity,
bf.abi, &bf.decl))
bf.abi, &bf.lifetimes, &bf.decl))
}
ast::ty_closure(ref f) => {
let fn_decl = ty_of_closure(self,
@ -508,18 +509,50 @@ pub fn ty_of_arg<AC:AstConv,RS:region_scope + Copy + Durable>(
arg {mode: mode, ty: ty}
}
pub fn bound_lifetimes<AC:AstConv>(
self: &AC,
ast_lifetimes: &OptVec<ast::Lifetime>) -> OptVec<ast::ident>
{
/*!
*
* Converts a list of lifetimes into a list of bound identifier
* names. Does not permit special names like 'static or 'self to
* be bound. Note that this function is for use in closures,
* methods, and fn definitions. It is legal to bind 'self in a
* type. Eventually this distinction should go away and the same
* rules should apply everywhere ('self would not be a special name
* at that point).
*/
let special_idents = [special_idents::static, special_idents::self_];
let mut bound_lifetime_names = opt_vec::Empty;
ast_lifetimes.map_to_vec(|ast_lifetime| {
if special_idents.any(|&i| i == ast_lifetime.ident) {
self.tcx().sess.span_err(
ast_lifetime.span,
fmt!("illegal lifetime parameter name: `%s`",
lifetime_to_str(ast_lifetime, self.tcx().sess.intr())));
} else {
bound_lifetime_names.push(ast_lifetime.ident);
}
});
bound_lifetime_names
}
pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
purity: ast::purity,
abi: ast::Abi,
decl: &ast::fn_decl)
-> ty::BareFnTy {
self: &AC,
rscope: &RS,
purity: ast::purity,
abi: ast::Abi,
lifetimes: &OptVec<ast::Lifetime>,
decl: &ast::fn_decl) -> ty::BareFnTy
{
debug!("ty_of_bare_fn");
// new region names that appear inside of the fn decl are bound to
// that function type
let rb = in_binding_rscope(rscope);
let bound_lifetime_names = bound_lifetimes(self, lifetimes);
let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names));
let input_tys = decl.inputs.map(|a| ty_of_arg(self, &rb, *a, None));
let output_ty = match decl.output.node {
@ -530,34 +563,9 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
ty::BareFnTy {
purity: purity,
abi: abi,
sig: ty::FnSig {inputs: input_tys, output: output_ty}
}
}
pub fn ty_of_bare_fn_ext<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
purity: ast::purity,
abi: ast::Abi,
decl: &ast::fn_decl,
+region_param_names: RegionParamNames)
-> ty::BareFnTy {
debug!("ty_of_bare_fn_ext");
// new region names that appear inside of the fn decl are bound to
// that function type
let rb = in_binding_rscope_ext(rscope, region_param_names);
let input_tys = decl.inputs.map(|a| ty_of_arg(self, &rb, *a, None));
let output_ty = match decl.output.node {
ast::ty_infer => self.ty_infer(decl.output.span),
_ => ast_ty_to_ty(self, &rb, decl.output)
};
ty::BareFnTy {
purity: purity,
abi: abi,
sig: ty::FnSig {inputs: input_tys, output: output_ty}
sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
inputs: input_tys,
output: output_ty}
}
}
@ -569,10 +577,16 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
onceness: ast::Onceness,
opt_lifetime: Option<@ast::Lifetime>,
decl: &ast::fn_decl,
expected_tys: Option<ty::FnSig>,
expected_sig: Option<ty::FnSig>,
lifetimes: &OptVec<ast::Lifetime>,
span: span)
-> ty::ClosureTy {
-> ty::ClosureTy
{
// The caller should not both provide explicit bound lifetime
// names and expected types. Either we infer the bound lifetime
// names or they are provided, but not both.
fail_unless!(lifetimes.is_empty() || expected_sig.is_none());
debug!("ty_of_fn_decl");
let _i = indenter();
@ -599,11 +613,11 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
// new region names that appear inside of the fn decl are bound to
// that function type
let region_param_names = RegionParamNames::from_lifetimes(lifetimes);
let rb = in_binding_rscope_ext(rscope, region_param_names);
let bound_lifetime_names = bound_lifetimes(self, lifetimes);
let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names));
let input_tys = do decl.inputs.mapi |i, a| {
let expected_arg_ty = do expected_tys.chain_ref |e| {
let expected_arg_ty = do expected_sig.chain_ref |e| {
// no guarantee that the correct number of expected args
// were supplied
if i < e.inputs.len() {Some(e.inputs[i])} else {None}
@ -611,7 +625,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
ty_of_arg(self, &rb, *a, expected_arg_ty)
};
let expected_ret_ty = expected_tys.map(|e| e.output);
let expected_ret_ty = expected_sig.map(|e| e.output);
let output_ty = match decl.output.node {
ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
ast::ty_infer => self.ty_infer(decl.output.span),
@ -623,7 +637,8 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
sigil: sigil,
onceness: onceness,
region: bound_region,
sig: ty::FnSig {inputs: input_tys,
sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
inputs: input_tys,
output: output_ty}
}
}

View File

@ -1633,7 +1633,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
// sigils.
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
let mut error_happened = false;
let (expected_tys,
let (expected_sig,
expected_purity,
expected_sigil,
expected_onceness) = {
@ -1668,13 +1668,14 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
expected_onceness,
None,
decl,
expected_tys,
expected_sig,
&opt_vec::Empty,
expr.span);
let mut fty_sig;
let fty = if error_happened {
fty_sig = FnSig {
bound_lifetime_names: opt_vec::Empty,
inputs: fn_ty.sig.inputs.map(|an_arg| {
arg { mode: an_arg.mode,
ty: ty::mk_err(tcx)
@ -3492,6 +3493,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
onceness: ast::Once,
region: ty::re_bound(ty::br_anon(0)),
sig: ty::FnSig {
bound_lifetime_names: opt_vec::Empty,
inputs: ~[arg {mode: ast::expl(ast::by_copy),
ty: ty::mk_imm_ptr(
ccx.tcx,
@ -3723,7 +3725,8 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
purity: ast::unsafe_fn,
abi: ast::RustAbi,
sig: FnSig {inputs: inputs,
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: inputs,
output: output}
});
let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));

View File

@ -59,6 +59,7 @@ use syntax::codemap;
use syntax::print::pprust::path_to_str;
use syntax::visit;
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
@ -716,6 +717,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
&type_rscope(region_parameterization),
ast::impure_fn,
ast::RustAbi,
&opt_vec::Empty,
&ast_util::dtor_dec()));
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id),
@ -776,17 +778,16 @@ pub fn ty_of_method(ccx: &CrateCtxt,
-> ty::method {
let rscope = MethodRscope::new(m.self_ty.node,
rp,
rcvr_generics,
method_generics);
rcvr_generics);
ty::method {
ident: m.ident,
tps: ty_param_bounds(ccx, &m.generics),
fty: astconv::ty_of_bare_fn_ext(ccx,
&rscope,
m.purity,
ast::RustAbi,
&m.decl,
rscope.region_param_names()),
fty: astconv::ty_of_bare_fn(ccx,
&rscope,
m.purity,
ast::RustAbi,
&method_generics.lifetimes,
&m.decl),
self_ty: m.self_ty.node,
vis: m.vis,
def_id: local_def(m.id)
@ -799,16 +800,16 @@ pub fn ty_of_ty_method(self: &CrateCtxt,
id: ast::def_id,
generics: &ast::Generics)
-> ty::method {
let rscope = MethodRscope::new(m.self_ty.node, rp, generics, &m.generics);
let rscope = MethodRscope::new(m.self_ty.node, rp, generics);
ty::method {
ident: m.ident,
tps: ty_param_bounds(self, &m.generics),
fty: astconv::ty_of_bare_fn_ext(self,
&rscope,
m.purity,
ast::RustAbi,
&m.decl,
rscope.region_param_names()),
fty: astconv::ty_of_bare_fn(self,
&rscope,
m.purity,
ast::RustAbi,
&m.generics.lifetimes,
&m.decl),
// assume public, because this is only invoked on trait methods
self_ty: m.self_ty.node,
vis: ast::public,
@ -869,13 +870,12 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
}
ast::item_fn(ref decl, purity, ref generics, _) => {
let bounds = ty_param_bounds(ccx, generics);
let region_param_names = RegionParamNames::from_generics(generics);
let tofd = astconv::ty_of_bare_fn_ext(ccx,
&empty_rscope,
purity,
ast::RustAbi,
decl,
region_param_names);
let tofd = astconv::ty_of_bare_fn(ccx,
&empty_rscope,
purity,
ast::RustAbi,
&generics.lifetimes,
decl);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: None,
@ -971,11 +971,10 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item)
generics)
}
ast::foreign_item_const(t) => {
let rb = in_binding_rscope(&empty_rscope);
ty::ty_param_bounds_and_ty {
bounds: @~[],
region_param: None,
ty: ast_ty_to_ty(ccx, &rb, t)
ty: ast_ty_to_ty(ccx, &empty_rscope, t)
}
}
}
@ -1043,7 +1042,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
-> ty::ty_param_bounds_and_ty {
let bounds = ty_param_bounds(ccx, generics);
let region_param_names = RegionParamNames::from_generics(generics);
let rb = in_binding_rscope_ext(&empty_rscope, region_param_names);
let rb = in_binding_rscope(&empty_rscope, region_param_names);
let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, *a, None) );
let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
@ -1052,7 +1051,9 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
ty::BareFnTy {
abi: ast::RustAbi,
purity: ast::unsafe_fn,
sig: ty::FnSig {inputs: input_tys, output: output_ty}
sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: input_tys,
output: output_ty}
});
let tpt = ty_param_bounds_and_ty {
bounds: bounds,

View File

@ -70,6 +70,7 @@ use core::result::{iter_vec2, map_vec2};
use core::vec;
use syntax::ast::{Onceness, purity, ret_style};
use syntax::ast;
use syntax::opt_vec;
use syntax::codemap::span;
pub trait Combine {
@ -432,7 +433,9 @@ pub fn super_fn_sigs<C:Combine>(
do argvecs(self, a_f.inputs, b_f.inputs)
.chain |inputs| {
do self.tys(a_f.output, b_f.output).chain |output| {
Ok(FnSig {inputs: /*bad*/copy inputs, output: output})
Ok(FnSig {bound_lifetime_names: opt_vec::Empty, // FIXME(#4846)
inputs: /*bad*/copy inputs,
output: output})
}
}
}

View File

@ -156,12 +156,10 @@ impl MethodRscope {
// trait).
pub fn new(self_ty: ast::self_ty_,
variance: Option<ty::region_variance>,
rcvr_generics: &ast::Generics,
method_generics: &ast::Generics)
rcvr_generics: &ast::Generics)
-> MethodRscope {
let mut region_param_names =
RegionParamNames::from_generics(rcvr_generics);
region_param_names.add_generics(method_generics);
MethodRscope {
self_ty: self_ty,
variance: variance,
@ -273,18 +271,7 @@ pub struct binding_rscope {
region_param_names: RegionParamNames,
}
pub fn in_binding_rscope<RS:region_scope + Copy + Durable>(self: &RS)
-> binding_rscope {
let base = @copy *self;
let base = base as @region_scope;
binding_rscope {
base: base,
anon_bindings: @mut 0,
region_param_names: RegionParamNames::new()
}
}
pub fn in_binding_rscope_ext<RS:region_scope + Copy + Durable>(
pub fn in_binding_rscope<RS:region_scope + Copy + Durable>(
self: &RS,
+region_param_names: RegionParamNames)
-> binding_rscope {

View File

@ -904,6 +904,7 @@ pub struct TyClosure {
pub struct TyBareFn {
purity: purity,
abi: Abi,
lifetimes: OptVec<Lifetime>,
decl: fn_decl
}

View File

@ -615,6 +615,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
}
ty_bare_fn(ref f) => {
ty_bare_fn(@TyBareFn {
lifetimes: f.lifetimes,
purity: f.purity,
abi: f.abi,
decl: fold_fn_decl(&f.decl, fld)

View File

@ -363,10 +363,11 @@ pub impl Parser {
let purity = self.parse_purity();
self.expect_keyword(&~"fn");
let (decl, _) = self.parse_ty_fn_decl();
let (decl, lifetimes) = self.parse_ty_fn_decl();
return ty_bare_fn(@TyBareFn {
abi: RustAbi,
purity: purity,
lifetimes: lifetimes,
decl: decl
});
}

View File

@ -14,6 +14,7 @@ use ast::{RegionTyParamBound, TraitTyParamBound, required, provided};
use ast;
use ast_util;
use opt_vec::OptVec;
use opt_vec;
use attr;
use codemap::{CodeMap, BytePos};
use codemap;
@ -402,14 +403,18 @@ pub fn print_type(s: @ps, &&ty: @ast::Ty) {
pclose(s);
}
ast::ty_bare_fn(f) => {
let generics = ast::Generics {lifetimes: copy f.lifetimes,
ty_params: opt_vec::Empty};
print_ty_fn(s, Some(f.abi), None, None,
f.purity, ast::Many, &f.decl, None,
None, None);
Some(&generics), None);
}
ast::ty_closure(f) => {
let generics = ast::Generics {lifetimes: copy f.lifetimes,
ty_params: opt_vec::Empty};
print_ty_fn(s, None, Some(f.sigil), f.region,
f.purity, f.onceness, &f.decl, None,
None, None);
Some(&generics), None);
}
ast::ty_path(path, _) => print_path(s, path, false),
ast::ty_fixed_length_vec(ref mt, v) => {
@ -1923,7 +1928,8 @@ pub fn print_ty_fn(s: @ps,
opt_region: Option<@ast::Lifetime>,
purity: ast::purity,
onceness: ast::Onceness,
decl: &ast::fn_decl, id: Option<ast::ident>,
decl: &ast::fn_decl,
id: Option<ast::ident>,
generics: Option<&ast::Generics>,
opt_self_ty: Option<ast::self_ty_>) {
ibox(s, indent_unit);

View File

@ -1,5 +1,3 @@
// xfail-pretty
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.