Skip to content

Commit 74a1041

Browse files
committed
Implement the new parsing rules for types in the parser, modifying the AST appropriately.
1 parent 8fb027e commit 74a1041

File tree

7 files changed

+262
-234
lines changed

7 files changed

+262
-234
lines changed

src/librustc/diagnostics.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,7 @@ register_diagnostics!(
145145
E0166,
146146
E0167,
147147
E0168,
148-
E0169
148+
E0169,
149+
E0170,
150+
E0171
149151
)

src/librustc/middle/resolve.rs

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,29 +1396,53 @@ impl<'a> Resolver<'a> {
13961396
// methods within to a new module, if the type was defined
13971397
// within this module.
13981398

1399-
// Create the module and add all methods.
1400-
match ty.node {
1401-
TyPath(ref path, _, _) if path.segments.len() == 1 => {
1399+
let mod_name = match ty.node {
1400+
TyPath(ref path, _) if path.segments.len() == 1 => {
14021401
// FIXME(18446) we should distinguish between the name of
14031402
// a trait and the name of an impl of that trait.
1404-
let mod_name = path.segments.last().unwrap().identifier.name;
1403+
Some(path.segments.last().unwrap().identifier.name)
1404+
}
1405+
TyObjectSum(ref lhs_ty, _) => {
1406+
match lhs_ty.node {
1407+
TyPath(ref path, _) if path.segments.len() == 1 => {
1408+
Some(path.segments.last().unwrap().identifier.name)
1409+
}
1410+
_ => {
1411+
None
1412+
}
1413+
}
1414+
}
1415+
_ => {
1416+
None
1417+
}
1418+
};
14051419

1420+
match mod_name {
1421+
None => {
1422+
self.resolve_error(ty.span,
1423+
"inherent implementations may \
1424+
only be implemented in the same \
1425+
module as the type they are \
1426+
implemented for")
1427+
}
1428+
Some(mod_name) => {
1429+
// Create the module and add all methods.
14061430
let parent_opt = parent.module().children.borrow()
1407-
.get(&mod_name).cloned();
1431+
.get(&mod_name).cloned();
14081432
let new_parent = match parent_opt {
14091433
// It already exists
14101434
Some(ref child) if child.get_module_if_available()
1411-
.is_some() &&
1412-
(child.get_module().kind.get() == ImplModuleKind ||
1413-
child.get_module().kind.get() == TraitModuleKind) => {
1414-
ModuleReducedGraphParent(child.get_module())
1415-
}
1435+
.is_some() &&
1436+
(child.get_module().kind.get() == ImplModuleKind ||
1437+
child.get_module().kind.get() == TraitModuleKind) => {
1438+
ModuleReducedGraphParent(child.get_module())
1439+
}
14161440
Some(ref child) if child.get_module_if_available()
1417-
.is_some() &&
1418-
child.get_module().kind.get() ==
1419-
EnumModuleKind => {
1420-
ModuleReducedGraphParent(child.get_module())
1421-
}
1441+
.is_some() &&
1442+
child.get_module().kind.get() ==
1443+
EnumModuleKind => {
1444+
ModuleReducedGraphParent(child.get_module())
1445+
}
14221446
// Create the module
14231447
_ => {
14241448
let name_bindings =
@@ -1433,7 +1457,7 @@ impl<'a> Resolver<'a> {
14331457
let ns = TypeNS;
14341458
let is_public =
14351459
!name_bindings.defined_in_namespace(ns) ||
1436-
name_bindings.defined_in_public_namespace(ns);
1460+
name_bindings.defined_in_public_namespace(ns);
14371461

14381462
name_bindings.define_module(parent_link,
14391463
Some(def_id),
@@ -1459,21 +1483,21 @@ impl<'a> Resolver<'a> {
14591483
ForbidDuplicateValues,
14601484
method.span);
14611485
let def = match method.pe_explicit_self()
1462-
.node {
1463-
SelfStatic => {
1464-
// Static methods become
1465-
// `DefStaticMethod`s.
1466-
DefStaticMethod(local_def(method.id),
1467-
FromImpl(local_def(item.id)))
1468-
}
1469-
_ => {
1470-
// Non-static methods become
1471-
// `DefMethod`s.
1472-
DefMethod(local_def(method.id),
1473-
None,
1474-
FromImpl(local_def(item.id)))
1475-
}
1476-
};
1486+
.node {
1487+
SelfStatic => {
1488+
// Static methods become
1489+
// `DefStaticMethod`s.
1490+
DefStaticMethod(local_def(method.id),
1491+
FromImpl(local_def(item.id)))
1492+
}
1493+
_ => {
1494+
// Non-static methods become
1495+
// `DefMethod`s.
1496+
DefMethod(local_def(method.id),
1497+
None,
1498+
FromImpl(local_def(item.id)))
1499+
}
1500+
};
14771501

14781502
// NB: not IMPORTABLE
14791503
let modifiers = if method.pe_vis() == ast::Public {
@@ -1496,7 +1520,7 @@ impl<'a> Resolver<'a> {
14961520
ForbidDuplicateTypesAndModules,
14971521
typedef.span);
14981522
let def = DefAssociatedTy(local_def(
1499-
typedef.id));
1523+
typedef.id));
15001524
// NB: not IMPORTABLE
15011525
let modifiers = if typedef.vis == ast::Public {
15021526
PUBLIC
@@ -1511,13 +1535,6 @@ impl<'a> Resolver<'a> {
15111535
}
15121536
}
15131537
}
1514-
_ => {
1515-
self.resolve_error(ty.span,
1516-
"inherent implementations may \
1517-
only be implemented in the same \
1518-
module as the type they are \
1519-
implemented for")
1520-
}
15211538
}
15221539

15231540
parent

src/librustc/middle/typeck/astconv.rs

Lines changed: 98 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope,
5959
ShiftedRscope, BindingRscope};
6060
use middle::typeck::rscope;
6161
use middle::typeck::TypeAndSubsts;
62+
use util::common::ErrorReported;
6263
use util::nodemap::DefIdMap;
63-
use util::ppaux::{Repr, UserString};
64+
use util::ppaux::{mod, Repr, UserString};
6465

6566
use std::rc::Rc;
6667
use std::iter::AdditiveIterator;
@@ -585,7 +586,7 @@ fn check_path_args(tcx: &ty::ctxt,
585586
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
586587
-> Option<Ty<'tcx>> {
587588
match ast_ty.node {
588-
ast::TyPath(ref path, _, id) => {
589+
ast::TyPath(ref path, id) => {
589590
let a_def = match tcx.def_map.borrow().get(&id) {
590591
None => {
591592
tcx.sess.span_bug(ast_ty.span,
@@ -642,7 +643,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
642643
}
643644

644645
match ast_ty.node {
645-
ast::TyPath(ref path, _, id) => {
646+
ast::TyPath(ref path, id) => {
646647
let a_def = match this.tcx().def_map.borrow().get(&id) {
647648
None => {
648649
this.tcx()
@@ -682,64 +683,92 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
682683
}
683684
}
684685

685-
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
686-
// If a_seq_ty is a str or a vec, make it a str/vec.
687-
// Also handle first-class trait types.
688-
fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
689-
this: &AC,
690-
rscope: &RS,
691-
a_seq_mutbl: ast::Mutability,
692-
a_seq_ty: &ast::Ty,
693-
region: ty::Region,
694-
constr: |Ty<'tcx>| -> Ty<'tcx>)
695-
-> Ty<'tcx>
686+
fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
687+
rscope: &RS,
688+
ty: &ast::Ty,
689+
bounds: &[ast::TyParamBound])
690+
-> Result<ty::TraitRef<'tcx>, ErrorReported>
691+
where AC : AstConv<'tcx>, RS : RegionScope
696692
{
697-
let tcx = this.tcx();
698-
699-
debug!("mk_pointer(region={}, a_seq_ty={})",
700-
region,
701-
a_seq_ty.repr(tcx));
693+
/*!
694+
* In a type like `Foo + Send`, we want to wait to collect the
695+
* full set of bounds before we make the object type, because we
696+
* need them to infer a region bound. (For example, if we tried
697+
* made a type from just `Foo`, then it wouldn't be enough to
698+
* infer a 'static bound, and hence the user would get an error.)
699+
* So this function is used when we're dealing with a sum type to
700+
* convert the LHS. It only accepts a type that refers to a trait
701+
* name, and reports an error otherwise.
702+
*/
702703

703-
match a_seq_ty.node {
704-
ast::TyVec(ref ty) => {
705-
let ty = ast_ty_to_ty(this, rscope, &**ty);
706-
return constr(ty::mk_vec(tcx, ty, None));
704+
match ty.node {
705+
ast::TyPath(ref path, id) => {
706+
match this.tcx().def_map.borrow().get(&id) {
707+
Some(&def::DefTrait(trait_def_id)) => {
708+
return Ok(ast_path_to_trait_ref(this,
709+
rscope,
710+
trait_def_id,
711+
None,
712+
path));
713+
}
714+
_ => {
715+
span_err!(this.tcx().sess, ty.span, E0170, "expected a reference to a trait");
716+
Err(ErrorReported)
717+
}
718+
}
707719
}
708-
ast::TyPath(ref path, ref opt_bounds, id) => {
709-
// Note that the "bounds must be empty if path is not a trait"
710-
// restriction is enforced in the below case for ty_path, which
711-
// will run after this as long as the path isn't a trait.
712-
match tcx.def_map.borrow().get(&id) {
713-
Some(&def::DefPrimTy(ast::TyStr)) => {
714-
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
715-
return ty::mk_str_slice(tcx, region, a_seq_mutbl);
720+
_ => {
721+
span_err!(this.tcx().sess, ty.span, E0171,
722+
"expected a path on the left-hand side of `+`, not `{}`",
723+
pprust::ty_to_string(ty));
724+
match ty.node {
725+
ast::TyRptr(None, ref mut_ty) => {
726+
span_note!(this.tcx().sess, ty.span,
727+
"perhaps you meant `&{}({} +{})`? (per RFC 248)",
728+
ppaux::mutability_to_string(mut_ty.mutbl),
729+
pprust::ty_to_string(&*mut_ty.ty),
730+
pprust::bounds_to_string(bounds));
716731
}
717-
Some(&def::DefTrait(trait_def_id)) => {
718-
let result = ast_path_to_trait_ref(this,
719-
rscope,
720-
trait_def_id,
721-
None,
722-
path);
723-
let empty_vec = [];
724-
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
725-
Some(ref bounds) => bounds.as_slice() };
726-
let existential_bounds = conv_existential_bounds(this,
727-
rscope,
728-
path.span,
729-
&[Rc::new(result.clone())],
730-
bounds);
731-
let tr = ty::mk_trait(tcx,
732-
result,
733-
existential_bounds);
734-
return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr});
732+
733+
ast::TyRptr(Some(ref lt), ref mut_ty) => {
734+
span_note!(this.tcx().sess, ty.span,
735+
"perhaps you meant `&{} {}({} +{})`? (per RFC 248)",
736+
pprust::lifetime_to_string(lt),
737+
ppaux::mutability_to_string(mut_ty.mutbl),
738+
pprust::ty_to_string(&*mut_ty.ty),
739+
pprust::bounds_to_string(bounds));
740+
}
741+
742+
_ => {
743+
span_note!(this.tcx().sess, ty.span,
744+
"perhaps you forget parentheses? (per RFC 248)");
735745
}
736-
_ => {}
737746
}
747+
Err(ErrorReported)
738748
}
739-
_ => {}
740749
}
741750

742-
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
751+
}
752+
753+
fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
754+
rscope: &RS,
755+
span: Span,
756+
trait_ref: ty::TraitRef<'tcx>,
757+
bounds: &[ast::TyParamBound])
758+
-> Ty<'tcx>
759+
where AC : AstConv<'tcx>, RS : RegionScope
760+
{
761+
let existential_bounds = conv_existential_bounds(this,
762+
rscope,
763+
span,
764+
&[Rc::new(trait_ref.clone())],
765+
bounds);
766+
767+
let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
768+
debug!("trait_ref_to_object_type: result={}",
769+
result.repr(this.tcx()));
770+
771+
result
743772
}
744773

745774
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>(
806835
ast::TyVec(ref ty) => {
807836
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
808837
}
838+
ast::TyObjectSum(ref ty, ref bounds) => {
839+
match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) {
840+
Ok(trait_ref) => {
841+
trait_ref_to_object_type(this, rscope, ast_ty.span,
842+
trait_ref, bounds.as_slice())
843+
}
844+
Err(ErrorReported) => {
845+
ty::mk_err()
846+
}
847+
}
848+
}
809849
ast::TyPtr(ref mt) => {
810850
ty::mk_ptr(tcx, ty::mt {
811851
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>(
815855
ast::TyRptr(ref region, ref mt) => {
816856
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
817857
debug!("ty_rptr r={}", r.repr(this.tcx()));
818-
mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r,
819-
|ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
858+
let t = ast_ty_to_ty(this, rscope, &*mt.ty);
859+
ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl})
820860
}
821861
ast::TyTup(ref fields) => {
822862
let flds = fields.iter()
@@ -874,7 +914,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
874914
ast::TyPolyTraitRef(ref bounds) => {
875915
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
876916
}
877-
ast::TyPath(ref path, ref bounds, id) => {
917+
ast::TyPath(ref path, id) => {
878918
let a_def = match tcx.def_map.borrow().get(&id) {
879919
None => {
880920
tcx.sess
@@ -884,35 +924,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
884924
}
885925
Some(&d) => d
886926
};
887-
// Kind bounds on path types are only supported for traits.
888-
match a_def {
889-
// But don't emit the error if the user meant to do a trait anyway.
890-
def::DefTrait(..) => { },
891-
_ if bounds.is_some() =>
892-
tcx.sess.span_err(ast_ty.span,
893-
"kind bounds can only be used on trait types"),
894-
_ => { },
895-
}
896927
match a_def {
897928
def::DefTrait(trait_def_id) => {
929+
// N.B. this case overlaps somewhat with
930+
// TyObjectSum, see that fn for details
898931
let result = ast_path_to_trait_ref(this,
899932
rscope,
900933
trait_def_id,
901934
None,
902935
path);
903-
let empty_bounds: &[ast::TyParamBound] = &[];
904-
let ast_bounds = match *bounds {
905-
Some(ref b) => b.as_slice(),
906-
None => empty_bounds
907-
};
908-
let bounds = conv_existential_bounds(this,
909-
rscope,
910-
ast_ty.span,
911-
&[Rc::new(result.clone())],
912-
ast_bounds);
913-
let result_ty = ty::mk_trait(tcx, result, bounds);
914-
debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx()));
915-
result_ty
936+
trait_ref_to_object_type(this, rscope, path.span, result, &[])
916937
}
917938
def::DefTy(did, _) | def::DefStruct(did) => {
918939
ast_path_to_ty(this, rscope, did, path).ty

0 commit comments

Comments
 (0)