Skip to content

Commit e0cac48

Browse files
committed
Add parser support for generalized where clauses
Implement support in the parser for generalized where clauses, as well as the conversion of ast::WherePredicates to ty::Predicate in `collect.rs`.
1 parent 8f51ad2 commit e0cac48

25 files changed

+505
-150
lines changed

src/librustc/middle/privacy.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
15051505
self.check_ty_param_bound(bound_pred.span, bound)
15061506
}
15071507
}
1508+
&ast::WherePredicate::RegionPredicate(_) => {}
15081509
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
15091510
self.visit_ty(&*eq_pred.ty);
15101511
}

src/librustc/middle/resolve_lifetime.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,19 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
206206
}
207207
for predicate in generics.where_clause.predicates.iter() {
208208
match predicate {
209-
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ident,
209+
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ref bounded_ty,
210210
ref bounds,
211-
span,
212211
.. }) => {
213-
self.visit_ident(span, ident);
212+
self.visit_ty(&**bounded_ty);
214213
visit::walk_ty_param_bounds_helper(self, bounds);
215214
}
215+
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
216+
ref bound,
217+
.. }) => {
218+
219+
self.visit_lifetime_ref(lifetime);
220+
self.visit_lifetime_ref(bound);
221+
}
216222
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
217223
ref path,
218224
ref ty,
@@ -545,9 +551,18 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
545551
}
546552
for predicate in generics.where_clause.predicates.iter() {
547553
match predicate {
548-
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => {
554+
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds,
555+
ref bounded_ty,
556+
..}) => {
557+
collector.visit_ty(&**bounded_ty);
549558
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
550559
}
560+
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
561+
ref bound,
562+
..}) => {
563+
collector.visit_lifetime_ref(lifetime);
564+
collector.visit_lifetime_ref(bound);
565+
}
551566
&ast::WherePredicate::EqPredicate(_) => unimplemented!()
552567
}
553568
}

src/librustc_resolve/lib.rs

+3-16
Original file line numberDiff line numberDiff line change
@@ -4360,27 +4360,14 @@ impl<'a> Resolver<'a> {
43604360
for predicate in where_clause.predicates.iter() {
43614361
match predicate {
43624362
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
4363-
match self.resolve_identifier(bound_pred.ident,
4364-
TypeNS,
4365-
true,
4366-
bound_pred.span) {
4367-
Some((def @ DefTyParam(..), last_private)) => {
4368-
self.record_def(bound_pred.id, (def, last_private));
4369-
}
4370-
_ => {
4371-
self.resolve_error(
4372-
bound_pred.span,
4373-
format!("undeclared type parameter `{}`",
4374-
token::get_ident(
4375-
bound_pred.ident)).as_slice());
4376-
}
4377-
}
4363+
self.resolve_type(&*bound_pred.bounded_ty);
43784364

43794365
for bound in bound_pred.bounds.iter() {
4380-
self.resolve_type_parameter_bound(bound_pred.id, bound,
4366+
self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound,
43814367
TraitBoundingTypeParameter);
43824368
}
43834369
}
4370+
&ast::WherePredicate::RegionPredicate(_) => {}
43844371
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
43854372
match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
43864373
Some((def @ DefTyParam(..), last_private)) => {

src/librustc_typeck/astconv.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1437,11 +1437,8 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
14371437
ast_bounds: &[ast::TyParamBound])
14381438
-> ty::ExistentialBounds
14391439
{
1440-
let ast_bound_refs: Vec<&ast::TyParamBound> =
1441-
ast_bounds.iter().collect();
1442-
14431440
let partitioned_bounds =
1444-
partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
1441+
partition_bounds(this.tcx(), span, ast_bounds);
14451442

14461443
conv_existential_bounds_from_partitioned_bounds(
14471444
this, rscope, span, principal_trait_ref, partitioned_bounds)
@@ -1455,7 +1452,6 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
14551452
-> Ty<'tcx>
14561453
where AC: AstConv<'tcx>, RS:RegionScope
14571454
{
1458-
let ast_bounds: Vec<&ast::TyParamBound> = ast_bounds.iter().collect();
14591455
let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
14601456

14611457
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
@@ -1620,14 +1616,14 @@ pub struct PartitionedBounds<'a> {
16201616
/// general trait bounds, and region bounds.
16211617
pub fn partition_bounds<'a>(tcx: &ty::ctxt,
16221618
_span: Span,
1623-
ast_bounds: &'a [&ast::TyParamBound])
1619+
ast_bounds: &'a [ast::TyParamBound])
16241620
-> PartitionedBounds<'a>
16251621
{
16261622
let mut builtin_bounds = ty::empty_builtin_bounds();
16271623
let mut region_bounds = Vec::new();
16281624
let mut trait_bounds = Vec::new();
16291625
let mut trait_def_ids = DefIdMap::new();
1630-
for &ast_bound in ast_bounds.iter() {
1626+
for ast_bound in ast_bounds.iter() {
16311627
match *ast_bound {
16321628
ast::TraitTyParamBound(ref b) => {
16331629
match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {

src/librustc_typeck/collect.rs

+54-54
Original file line numberDiff line numberDiff line change
@@ -1364,8 +1364,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
13641364
self_param_ty,
13651365
bounds.as_slice(),
13661366
unbound,
1367-
it.span,
1368-
&generics.where_clause);
1367+
it.span);
13691368

13701369
let substs = mk_item_substs(ccx, &ty_generics);
13711370
let trait_def = Rc::new(ty::TraitDef {
@@ -1619,7 +1618,6 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
16191618
subst::AssocSpace,
16201619
&associated_type.ty_param,
16211620
generics.types.len(subst::AssocSpace),
1622-
&ast_generics.where_clause,
16231621
Some(local_def(trait_id)));
16241622
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
16251623
def.clone());
@@ -1774,7 +1772,6 @@ fn ty_generics<'tcx,AC>(this: &AC,
17741772
space,
17751773
param,
17761774
i,
1777-
where_clause,
17781775
None);
17791776
debug!("ty_generics: def for type param: {}, {}",
17801777
def.repr(this.tcx()),
@@ -1798,6 +1795,52 @@ fn ty_generics<'tcx,AC>(this: &AC,
17981795
// into the predicates list. This is currently kind of non-DRY.
17991796
create_predicates(this.tcx(), &mut result, space);
18001797

1798+
// Add the bounds not associated with a type parameter
1799+
for predicate in where_clause.predicates.iter() {
1800+
match predicate {
1801+
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1802+
let ty = ast_ty_to_ty(this, &ExplicitRscope, &*bound_pred.bounded_ty);
1803+
1804+
for bound in bound_pred.bounds.iter() {
1805+
match bound {
1806+
&ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref) => {
1807+
let trait_ref = astconv::instantiate_poly_trait_ref(
1808+
this,
1809+
&ExplicitRscope,
1810+
//@jroesch: for now trait_ref, poly_trait_ref?
1811+
poly_trait_ref,
1812+
Some(ty),
1813+
AllowEqConstraints::Allow
1814+
);
1815+
1816+
result.predicates.push(space, ty::Predicate::Trait(trait_ref));
1817+
}
1818+
1819+
&ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1820+
let region = ast_region_to_region(this.tcx(), lifetime);
1821+
let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1822+
result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1823+
}
1824+
}
1825+
}
1826+
}
1827+
1828+
&ast::WherePredicate::RegionPredicate(ref region_pred) => {
1829+
let r1 = ast_region_to_region(this.tcx(), &region_pred.lifetime);
1830+
let r2 = ast_region_to_region(this.tcx(), &region_pred.bound);
1831+
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1832+
result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1833+
}
1834+
1835+
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
1836+
// FIXME(#20041)
1837+
this.tcx().sess.span_bug(eq_pred.span,
1838+
"Equality constraints are not yet \
1839+
implemented (#20041)")
1840+
}
1841+
}
1842+
}
1843+
18011844
return result;
18021845

18031846
fn create_type_parameters_for_associated_types<'tcx, AC>(
@@ -1915,7 +1958,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
19151958
space: subst::ParamSpace,
19161959
param: &ast::TyParam,
19171960
index: uint,
1918-
where_clause: &ast::WhereClause,
19191961
associated_with: Option<ast::DefId>)
19201962
-> ty::TypeParameterDef<'tcx>
19211963
where AC: AstConv<'tcx>
@@ -1931,8 +1973,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
19311973
param_ty,
19321974
param.bounds.as_slice(),
19331975
&param.unbound,
1934-
param.span,
1935-
where_clause);
1976+
param.span);
19361977
let default = match param.default {
19371978
None => None,
19381979
Some(ref path) => {
@@ -1977,15 +2018,13 @@ fn compute_bounds<'tcx,AC>(this: &AC,
19772018
param_ty: ty::ParamTy,
19782019
ast_bounds: &[ast::TyParamBound],
19792020
unbound: &Option<ast::TraitRef>,
1980-
span: Span,
1981-
where_clause: &ast::WhereClause)
2021+
span: Span)
19822022
-> ty::ParamBounds<'tcx>
19832023
where AC: AstConv<'tcx> {
19842024
let mut param_bounds = conv_param_bounds(this,
19852025
span,
19862026
param_ty,
1987-
ast_bounds,
1988-
where_clause);
2027+
ast_bounds);
19892028

19902029

19912030
add_unsized_bound(this,
@@ -2031,16 +2070,14 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
20312070
fn conv_param_bounds<'tcx,AC>(this: &AC,
20322071
span: Span,
20332072
param_ty: ty::ParamTy,
2034-
ast_bounds: &[ast::TyParamBound],
2035-
where_clause: &ast::WhereClause)
2073+
ast_bounds: &[ast::TyParamBound])
20362074
-> ty::ParamBounds<'tcx>
2037-
where AC: AstConv<'tcx> {
2038-
let all_bounds =
2039-
merge_param_bounds(this.tcx(), param_ty, ast_bounds, where_clause);
2075+
where AC: AstConv<'tcx>
2076+
{
20402077
let astconv::PartitionedBounds { builtin_bounds,
20412078
trait_bounds,
20422079
region_bounds } =
2043-
astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
2080+
astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice());
20442081
let trait_bounds: Vec<Rc<ty::PolyTraitRef>> =
20452082
trait_bounds.into_iter()
20462083
.map(|bound| {
@@ -2062,43 +2099,6 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
20622099
}
20632100
}
20642101

2065-
/// Merges the bounds declared on a type parameter with those found from where clauses into a
2066-
/// single list.
2067-
fn merge_param_bounds<'a>(tcx: &ty::ctxt,
2068-
param_ty: ty::ParamTy,
2069-
ast_bounds: &'a [ast::TyParamBound],
2070-
where_clause: &'a ast::WhereClause)
2071-
-> Vec<&'a ast::TyParamBound> {
2072-
let mut result = Vec::new();
2073-
2074-
for ast_bound in ast_bounds.iter() {
2075-
result.push(ast_bound);
2076-
}
2077-
2078-
for predicate in where_clause.predicates.iter() {
2079-
match predicate {
2080-
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
2081-
let predicate_param_id =
2082-
tcx.def_map
2083-
.borrow()
2084-
.get(&bound_pred.id)
2085-
.expect("merge_param_bounds(): resolve didn't resolve the \
2086-
type parameter identifier in a `where` clause")
2087-
.def_id();
2088-
if param_ty.def_id != predicate_param_id {
2089-
continue
2090-
}
2091-
for bound in bound_pred.bounds.iter() {
2092-
result.push(bound);
2093-
}
2094-
}
2095-
&ast::WherePredicate::EqPredicate(_) => panic!("not implemented")
2096-
}
2097-
}
2098-
2099-
result
2100-
}
2101-
21022102
pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
21032103
decl: &ast::FnDecl,
21042104
def_id: ast::DefId,

src/librustdoc/clean/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ impl Clean<Option<Lifetime>> for ty::Region {
693693

694694
#[deriving(Clone, Encodable, Decodable, PartialEq)]
695695
pub struct WherePredicate {
696-
pub name: String,
696+
pub ty: Type,
697697
pub bounds: Vec<TyParamBound>
698698
}
699699

@@ -702,11 +702,12 @@ impl Clean<WherePredicate> for ast::WherePredicate {
702702
match *self {
703703
ast::WherePredicate::BoundPredicate(ref wbp) => {
704704
WherePredicate {
705-
name: wbp.ident.clean(cx),
705+
ty: wbp.bounded_ty.clean(cx),
706706
bounds: wbp.bounds.clean(cx)
707707
}
708708
}
709-
ast::WherePredicate::EqPredicate(_) => {
709+
// FIXME(#20048)
710+
_ => {
710711
unimplemented!();
711712
}
712713
}

src/librustdoc/html/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<'a> fmt::Show for WhereClause<'a> {
129129
try!(f.write(", ".as_bytes()));
130130
}
131131
let bounds = pred.bounds.as_slice();
132-
try!(write!(f, "{}: {}", pred.name, TyParamBounds(bounds)));
132+
try!(write!(f, "{}: {}", pred.ty, TyParamBounds(bounds)));
133133
}
134134
Ok(())
135135
}

src/libsyntax/ast.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -415,17 +415,26 @@ pub struct WhereClause {
415415
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
416416
pub enum WherePredicate {
417417
BoundPredicate(WhereBoundPredicate),
418+
RegionPredicate(WhereRegionPredicate),
418419
EqPredicate(WhereEqPredicate)
419420
}
420421

421422
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
422423
pub struct WhereBoundPredicate {
423-
pub id: NodeId,
424424
pub span: Span,
425-
pub ident: Ident,
425+
pub bounded_ty: P<Ty>,
426426
pub bounds: OwnedSlice<TyParamBound>,
427427
}
428428

429+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
430+
pub struct WhereRegionPredicate {
431+
pub span: Span,
432+
pub lifetime: Lifetime,
433+
pub bound: Lifetime
434+
}
435+
436+
impl Copy for WhereRegionPredicate {}
437+
429438
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
430439
pub struct WhereEqPredicate {
431440
pub id: NodeId,

src/libsyntax/ext/deriving/generic/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -426,12 +426,18 @@ impl<'a> TraitDef<'a> {
426426
match *clause {
427427
ast::WherePredicate::BoundPredicate(ref wb) => {
428428
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
429-
id: ast::DUMMY_NODE_ID,
430429
span: self.span,
431-
ident: wb.ident,
430+
bounded_ty: wb.bounded_ty.clone(),
432431
bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect())
433432
})
434433
}
434+
ast::WherePredicate::RegionPredicate(ref rb) => {
435+
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
436+
span: self.span,
437+
lifetime: rb.lifetime,
438+
bound: rb.bound
439+
})
440+
}
435441
ast::WherePredicate::EqPredicate(ref we) => {
436442
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
437443
id: ast::DUMMY_NODE_ID,

0 commit comments

Comments
 (0)