提交 74a1041a 编写于 作者: N Niko Matsakis

Implement the new parsing rules for types in the parser, modifying the AST appropriately.

上级 8fb027e3
......@@ -145,5 +145,7 @@
E0166,
E0167,
E0168,
E0169
E0169,
E0170,
E0171
)
......@@ -1396,29 +1396,53 @@ fn build_reduced_graph_for_item(&mut self,
// methods within to a new module, if the type was defined
// within this module.
// Create the module and add all methods.
match ty.node {
TyPath(ref path, _, _) if path.segments.len() == 1 => {
let mod_name = match ty.node {
TyPath(ref path, _) if path.segments.len() == 1 => {
// FIXME(18446) we should distinguish between the name of
// a trait and the name of an impl of that trait.
let mod_name = path.segments.last().unwrap().identifier.name;
Some(path.segments.last().unwrap().identifier.name)
}
TyObjectSum(ref lhs_ty, _) => {
match lhs_ty.node {
TyPath(ref path, _) if path.segments.len() == 1 => {
Some(path.segments.last().unwrap().identifier.name)
}
_ => {
None
}
}
}
_ => {
None
}
};
match mod_name {
None => {
self.resolve_error(ty.span,
"inherent implementations may \
only be implemented in the same \
module as the type they are \
implemented for")
}
Some(mod_name) => {
// Create the module and add all methods.
let parent_opt = parent.module().children.borrow()
.get(&mod_name).cloned();
.get(&mod_name).cloned();
let new_parent = match parent_opt {
// It already exists
Some(ref child) if child.get_module_if_available()
.is_some() &&
(child.get_module().kind.get() == ImplModuleKind ||
child.get_module().kind.get() == TraitModuleKind) => {
ModuleReducedGraphParent(child.get_module())
}
.is_some() &&
(child.get_module().kind.get() == ImplModuleKind ||
child.get_module().kind.get() == TraitModuleKind) => {
ModuleReducedGraphParent(child.get_module())
}
Some(ref child) if child.get_module_if_available()
.is_some() &&
child.get_module().kind.get() ==
EnumModuleKind => {
ModuleReducedGraphParent(child.get_module())
}
.is_some() &&
child.get_module().kind.get() ==
EnumModuleKind => {
ModuleReducedGraphParent(child.get_module())
}
// Create the module
_ => {
let name_bindings =
......@@ -1433,7 +1457,7 @@ fn build_reduced_graph_for_item(&mut self,
let ns = TypeNS;
let is_public =
!name_bindings.defined_in_namespace(ns) ||
name_bindings.defined_in_public_namespace(ns);
name_bindings.defined_in_public_namespace(ns);
name_bindings.define_module(parent_link,
Some(def_id),
......@@ -1459,21 +1483,21 @@ fn build_reduced_graph_for_item(&mut self,
ForbidDuplicateValues,
method.span);
let def = match method.pe_explicit_self()
.node {
SelfStatic => {
// Static methods become
// `DefStaticMethod`s.
DefStaticMethod(local_def(method.id),
FromImpl(local_def(item.id)))
}
_ => {
// Non-static methods become
// `DefMethod`s.
DefMethod(local_def(method.id),
None,
FromImpl(local_def(item.id)))
}
};
.node {
SelfStatic => {
// Static methods become
// `DefStaticMethod`s.
DefStaticMethod(local_def(method.id),
FromImpl(local_def(item.id)))
}
_ => {
// Non-static methods become
// `DefMethod`s.
DefMethod(local_def(method.id),
None,
FromImpl(local_def(item.id)))
}
};
// NB: not IMPORTABLE
let modifiers = if method.pe_vis() == ast::Public {
......@@ -1496,7 +1520,7 @@ fn build_reduced_graph_for_item(&mut self,
ForbidDuplicateTypesAndModules,
typedef.span);
let def = DefAssociatedTy(local_def(
typedef.id));
typedef.id));
// NB: not IMPORTABLE
let modifiers = if typedef.vis == ast::Public {
PUBLIC
......@@ -1511,13 +1535,6 @@ fn build_reduced_graph_for_item(&mut self,
}
}
}
_ => {
self.resolve_error(ty.span,
"inherent implementations may \
only be implemented in the same \
module as the type they are \
implemented for")
}
}
parent
......
......@@ -59,8 +59,9 @@
ShiftedRscope, BindingRscope};
use middle::typeck::rscope;
use middle::typeck::TypeAndSubsts;
use util::common::ErrorReported;
use util::nodemap::DefIdMap;
use util::ppaux::{Repr, UserString};
use util::ppaux::{mod, Repr, UserString};
use std::rc::Rc;
use std::iter::AdditiveIterator;
......@@ -585,7 +586,7 @@ fn check_path_args(tcx: &ty::ctxt,
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
-> Option<Ty<'tcx>> {
match ast_ty.node {
ast::TyPath(ref path, _, id) => {
ast::TyPath(ref path, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
None => {
tcx.sess.span_bug(ast_ty.span,
......@@ -642,7 +643,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
match ast_ty.node {
ast::TyPath(ref path, _, id) => {
ast::TyPath(ref path, id) => {
let a_def = match this.tcx().def_map.borrow().get(&id) {
None => {
this.tcx()
......@@ -682,64 +683,92 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
}
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
// If a_seq_ty is a str or a vec, make it a str/vec.
// Also handle first-class trait types.
fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
this: &AC,
rscope: &RS,
a_seq_mutbl: ast::Mutability,
a_seq_ty: &ast::Ty,
region: ty::Region,
constr: |Ty<'tcx>| -> Ty<'tcx>)
-> Ty<'tcx>
fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
rscope: &RS,
ty: &ast::Ty,
bounds: &[ast::TyParamBound])
-> Result<ty::TraitRef<'tcx>, ErrorReported>
where AC : AstConv<'tcx>, RS : RegionScope
{
let tcx = this.tcx();
debug!("mk_pointer(region={}, a_seq_ty={})",
region,
a_seq_ty.repr(tcx));
/*!
* In a type like `Foo + Send`, we want to wait to collect the
* full set of bounds before we make the object type, because we
* need them to infer a region bound. (For example, if we tried
* made a type from just `Foo`, then it wouldn't be enough to
* infer a 'static bound, and hence the user would get an error.)
* So this function is used when we're dealing with a sum type to
* convert the LHS. It only accepts a type that refers to a trait
* name, and reports an error otherwise.
*/
match a_seq_ty.node {
ast::TyVec(ref ty) => {
let ty = ast_ty_to_ty(this, rscope, &**ty);
return constr(ty::mk_vec(tcx, ty, None));
match ty.node {
ast::TyPath(ref path, id) => {
match this.tcx().def_map.borrow().get(&id) {
Some(&def::DefTrait(trait_def_id)) => {
return Ok(ast_path_to_trait_ref(this,
rscope,
trait_def_id,
None,
path));
}
_ => {
span_err!(this.tcx().sess, ty.span, E0170, "expected a reference to a trait");
Err(ErrorReported)
}
}
}
ast::TyPath(ref path, ref opt_bounds, id) => {
// Note that the "bounds must be empty if path is not a trait"
// restriction is enforced in the below case for ty_path, which
// will run after this as long as the path isn't a trait.
match tcx.def_map.borrow().get(&id) {
Some(&def::DefPrimTy(ast::TyStr)) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
return ty::mk_str_slice(tcx, region, a_seq_mutbl);
_ => {
span_err!(this.tcx().sess, ty.span, E0171,
"expected a path on the left-hand side of `+`, not `{}`",
pprust::ty_to_string(ty));
match ty.node {
ast::TyRptr(None, ref mut_ty) => {
span_note!(this.tcx().sess, ty.span,
"perhaps you meant `&{}({} +{})`? (per RFC 248)",
ppaux::mutability_to_string(mut_ty.mutbl),
pprust::ty_to_string(&*mut_ty.ty),
pprust::bounds_to_string(bounds));
}
Some(&def::DefTrait(trait_def_id)) => {
let result = ast_path_to_trait_ref(this,
rscope,
trait_def_id,
None,
path);
let empty_vec = [];
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
Some(ref bounds) => bounds.as_slice() };
let existential_bounds = conv_existential_bounds(this,
rscope,
path.span,
&[Rc::new(result.clone())],
bounds);
let tr = ty::mk_trait(tcx,
result,
existential_bounds);
return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr});
ast::TyRptr(Some(ref lt), ref mut_ty) => {
span_note!(this.tcx().sess, ty.span,
"perhaps you meant `&{} {}({} +{})`? (per RFC 248)",
pprust::lifetime_to_string(lt),
ppaux::mutability_to_string(mut_ty.mutbl),
pprust::ty_to_string(&*mut_ty.ty),
pprust::bounds_to_string(bounds));
}
_ => {
span_note!(this.tcx().sess, ty.span,
"perhaps you forget parentheses? (per RFC 248)");
}
_ => {}
}
Err(ErrorReported)
}
_ => {}
}
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
}
fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
rscope: &RS,
span: Span,
trait_ref: ty::TraitRef<'tcx>,
bounds: &[ast::TyParamBound])
-> Ty<'tcx>
where AC : AstConv<'tcx>, RS : RegionScope
{
let existential_bounds = conv_existential_bounds(this,
rscope,
span,
&[Rc::new(trait_ref.clone())],
bounds);
let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
debug!("trait_ref_to_object_type: result={}",
result.repr(this.tcx()));
result
}
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
......@@ -806,6 +835,17 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ast::TyVec(ref ty) => {
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
}
ast::TyObjectSum(ref ty, ref bounds) => {
match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) {
Ok(trait_ref) => {
trait_ref_to_object_type(this, rscope, ast_ty.span,
trait_ref, bounds.as_slice())
}
Err(ErrorReported) => {
ty::mk_err()
}
}
}
ast::TyPtr(ref mt) => {
ty::mk_ptr(tcx, ty::mt {
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
......@@ -815,8 +855,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ast::TyRptr(ref region, ref mt) => {
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
debug!("ty_rptr r={}", r.repr(this.tcx()));
mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r,
|ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
let t = ast_ty_to_ty(this, rscope, &*mt.ty);
ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl})
}
ast::TyTup(ref fields) => {
let flds = fields.iter()
......@@ -874,7 +914,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ast::TyPolyTraitRef(ref bounds) => {
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
}
ast::TyPath(ref path, ref bounds, id) => {
ast::TyPath(ref path, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
None => {
tcx.sess
......@@ -884,35 +924,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
Some(&d) => d
};
// Kind bounds on path types are only supported for traits.
match a_def {
// But don't emit the error if the user meant to do a trait anyway.
def::DefTrait(..) => { },
_ if bounds.is_some() =>
tcx.sess.span_err(ast_ty.span,
"kind bounds can only be used on trait types"),
_ => { },
}
match a_def {
def::DefTrait(trait_def_id) => {
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let result = ast_path_to_trait_ref(this,
rscope,
trait_def_id,
None,
path);
let empty_bounds: &[ast::TyParamBound] = &[];
let ast_bounds = match *bounds {
Some(ref b) => b.as_slice(),
None => empty_bounds
};
let bounds = conv_existential_bounds(this,
rscope,
ast_ty.span,
&[Rc::new(result.clone())],
ast_bounds);
let result_ty = ty::mk_trait(tcx, result, bounds);
debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx()));
result_ty
trait_ref_to_object_type(this, rscope, path.span, result, &[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
ast_path_to_ty(this, rscope, did, path).ty
......
......@@ -1151,7 +1151,9 @@ pub enum Ty_ {
/// A path (`module::module::...::Type`) or primitive
///
/// Type parameters are stored in the Path itself
TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
TyPath(Path, NodeId),
/// Something like `A+B`. Note that `B` must always be a path.
TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef(TyParamBounds),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
......
......@@ -1029,7 +1029,7 @@ fn parser_done(p: Parser){
parameters: ast::PathParameters::none(),
}
),
}, None, ast::DUMMY_NODE_ID),
}, ast::DUMMY_NODE_ID),
span:sp(10,13)
}),
pat: P(ast::Pat {
......
此差异已折叠。
......@@ -293,6 +293,10 @@ pub fn ty_to_string(ty: &ast::Ty) -> String {
$to_string(|s| s.print_type(ty))
}
pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
$to_string(|s| s.print_bounds("", bounds))
}
pub fn pat_to_string(pat: &ast::Pat) -> String {
$to_string(|s| s.print_pat(pat))
}
......@@ -739,11 +743,15 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
Some(&generics),
None));
}
ast::TyPath(ref path, ref bounds, _) => {
try!(self.print_bounded_path(path, bounds));
ast::TyPath(ref path, _) => {
try!(self.print_path(path, false));
}
ast::TyObjectSum(ref ty, ref bounds) => {
try!(self.print_type(&**ty));
try!(self.print_bounds("+", bounds.as_slice()));
}
ast::TyPolyTraitRef(ref bounds) => {
try!(self.print_bounds("", bounds));
try!(self.print_bounds("", bounds.as_slice()));
}
ast::TyQPath(ref qpath) => {
try!(word(&mut self.s, "<"));
......@@ -970,7 +978,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
}
_ => {}
}
try!(self.print_bounds(":", bounds));
try!(self.print_bounds(":", bounds.as_slice()));
try!(self.print_where_clause(generics));
try!(word(&mut self.s, " "));
try!(self.bopen());
......@@ -2329,7 +2337,7 @@ pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
pub fn print_bounds(&mut self,
prefix: &str,
bounds: &OwnedSlice<ast::TyParamBound>)
bounds: &[ast::TyParamBound])
-> IoResult<()> {
if !bounds.is_empty() {
try!(word(&mut self.s, prefix));
......@@ -2418,7 +2426,7 @@ pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
_ => {}
}
try!(self.print_ident(param.ident));
try!(self.print_bounds(":", &param.bounds));
try!(self.print_bounds(":", param.bounds.as_slice()));
match param.default {
Some(ref default) => {
try!(space(&mut self.s));
......@@ -2447,7 +2455,7 @@ pub fn print_where_clause(&mut self, generics: &ast::Generics)
}
try!(self.print_ident(predicate.ident));
try!(self.print_bounds(":", &predicate.bounds));
try!(self.print_bounds(":", predicate.bounds.as_slice()));
}
Ok(())
......@@ -2664,7 +2672,7 @@ pub fn print_ty_fn(&mut self,
try!(self.pclose());
}
try!(self.print_bounds(":", bounds));
try!(self.print_bounds(":", bounds.as_slice()));
try!(self.print_fn_output(decl));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册