Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement parsing and conversion of generalized where clauses #20002

Merged
merged 2 commits into from
Dec 20, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
@@ -1505,6 +1505,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
self.check_ty_param_bound(bound_pred.span, bound)
}
}
&ast::WherePredicate::RegionPredicate(_) => {}
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
self.visit_ty(&*eq_pred.ty);
}
28 changes: 24 additions & 4 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
@@ -206,13 +206,21 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
}
for predicate in generics.where_clause.predicates.iter() {
match predicate {
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ident,
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ref bounded_ty,
ref bounds,
span,
.. }) => {
self.visit_ident(span, ident);
self.visit_ty(&**bounded_ty);
visit::walk_ty_param_bounds_helper(self, bounds);
}
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
ref bounds,
.. }) => {

self.visit_lifetime_ref(lifetime);
for bound in bounds.iter() {
self.visit_lifetime_ref(bound);
}
}
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
ref path,
ref ty,
@@ -545,9 +553,21 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
}
for predicate in generics.where_clause.predicates.iter() {
match predicate {
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => {
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds,
ref bounded_ty,
..}) => {
collector.visit_ty(&**bounded_ty);
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
}
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
collector.visit_lifetime_ref(lifetime);

for bound in bounds.iter() {
collector.visit_lifetime_ref(bound);
}
}
&ast::WherePredicate::EqPredicate(_) => unimplemented!()
}
}
19 changes: 3 additions & 16 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
@@ -4360,27 +4360,14 @@ impl<'a> Resolver<'a> {
for predicate in where_clause.predicates.iter() {
match predicate {
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
match self.resolve_identifier(bound_pred.ident,
TypeNS,
true,
bound_pred.span) {
Some((def @ DefTyParam(..), last_private)) => {
self.record_def(bound_pred.id, (def, last_private));
}
_ => {
self.resolve_error(
bound_pred.span,
format!("undeclared type parameter `{}`",
token::get_ident(
bound_pred.ident)).as_slice());
}
}
self.resolve_type(&*bound_pred.bounded_ty);

for bound in bound_pred.bounds.iter() {
self.resolve_type_parameter_bound(bound_pred.id, bound,
self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound,
TraitBoundingTypeParameter);
}
}
&ast::WherePredicate::RegionPredicate(_) => {}
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
Some((def @ DefTyParam(..), last_private)) => {
10 changes: 3 additions & 7 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -1437,11 +1437,8 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
ast_bounds: &[ast::TyParamBound])
-> ty::ExistentialBounds
{
let ast_bound_refs: Vec<&ast::TyParamBound> =
ast_bounds.iter().collect();

let partitioned_bounds =
partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
partition_bounds(this.tcx(), span, ast_bounds);

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

let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
@@ -1620,14 +1616,14 @@ pub struct PartitionedBounds<'a> {
/// general trait bounds, and region bounds.
pub fn partition_bounds<'a>(tcx: &ty::ctxt,
_span: Span,
ast_bounds: &'a [&ast::TyParamBound])
ast_bounds: &'a [ast::TyParamBound])
-> PartitionedBounds<'a>
{
let mut builtin_bounds = ty::empty_builtin_bounds();
let mut region_bounds = Vec::new();
let mut trait_bounds = Vec::new();
let mut trait_def_ids = DefIdMap::new();
for &ast_bound in ast_bounds.iter() {
for ast_bound in ast_bounds.iter() {
match *ast_bound {
ast::TraitTyParamBound(ref b) => {
match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
110 changes: 56 additions & 54 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
@@ -1364,8 +1364,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
self_param_ty,
bounds.as_slice(),
unbound,
it.span,
&generics.where_clause);
it.span);

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

// Add the bounds not associated with a type parameter
for predicate in where_clause.predicates.iter() {
match predicate {
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
let ty = ast_ty_to_ty(this, &ExplicitRscope, &*bound_pred.bounded_ty);

for bound in bound_pred.bounds.iter() {
match bound {
&ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref) => {
let trait_ref = astconv::instantiate_poly_trait_ref(
this,
&ExplicitRscope,
//@jroesch: for now trait_ref, poly_trait_ref?
poly_trait_ref,
Some(ty),
AllowEqConstraints::Allow
);

result.predicates.push(space, ty::Predicate::Trait(trait_ref));
}

&ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
let region = ast_region_to_region(this.tcx(), lifetime);
let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
}
}
}
}

&ast::WherePredicate::RegionPredicate(ref region_pred) => {
let r1 = ast_region_to_region(this.tcx(), &region_pred.lifetime);
for bound in region_pred.bounds.iter() {
let r2 = ast_region_to_region(this.tcx(), bound);
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
}
}

&ast::WherePredicate::EqPredicate(ref eq_pred) => {
// FIXME(#20041)
this.tcx().sess.span_bug(eq_pred.span,
"Equality constraints are not yet \
implemented (#20041)")
}
}
}

return result;

fn create_type_parameters_for_associated_types<'tcx, AC>(
@@ -1915,7 +1960,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
space: subst::ParamSpace,
param: &ast::TyParam,
index: uint,
where_clause: &ast::WhereClause,
associated_with: Option<ast::DefId>)
-> ty::TypeParameterDef<'tcx>
where AC: AstConv<'tcx>
@@ -1931,8 +1975,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
param_ty,
param.bounds.as_slice(),
&param.unbound,
param.span,
where_clause);
param.span);
let default = match param.default {
None => None,
Some(ref path) => {
@@ -1977,15 +2020,13 @@ fn compute_bounds<'tcx,AC>(this: &AC,
param_ty: ty::ParamTy,
ast_bounds: &[ast::TyParamBound],
unbound: &Option<ast::TraitRef>,
span: Span,
where_clause: &ast::WhereClause)
span: Span)
-> ty::ParamBounds<'tcx>
where AC: AstConv<'tcx> {
let mut param_bounds = conv_param_bounds(this,
span,
param_ty,
ast_bounds,
where_clause);
ast_bounds);


add_unsized_bound(this,
@@ -2031,16 +2072,14 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
fn conv_param_bounds<'tcx,AC>(this: &AC,
span: Span,
param_ty: ty::ParamTy,
ast_bounds: &[ast::TyParamBound],
where_clause: &ast::WhereClause)
ast_bounds: &[ast::TyParamBound])
-> ty::ParamBounds<'tcx>
where AC: AstConv<'tcx> {
let all_bounds =
merge_param_bounds(this.tcx(), param_ty, ast_bounds, where_clause);
where AC: AstConv<'tcx>
{
let astconv::PartitionedBounds { builtin_bounds,
trait_bounds,
region_bounds } =
astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice());
let trait_bounds: Vec<Rc<ty::PolyTraitRef>> =
trait_bounds.into_iter()
.map(|bound| {
@@ -2062,43 +2101,6 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
}
}

/// Merges the bounds declared on a type parameter with those found from where clauses into a
/// single list.
fn merge_param_bounds<'a>(tcx: &ty::ctxt,
param_ty: ty::ParamTy,
ast_bounds: &'a [ast::TyParamBound],
where_clause: &'a ast::WhereClause)
-> Vec<&'a ast::TyParamBound> {
let mut result = Vec::new();

for ast_bound in ast_bounds.iter() {
result.push(ast_bound);
}

for predicate in where_clause.predicates.iter() {
match predicate {
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
let predicate_param_id =
tcx.def_map
.borrow()
.get(&bound_pred.id)
.expect("merge_param_bounds(): resolve didn't resolve the \
type parameter identifier in a `where` clause")
.def_id();
if param_ty.def_id != predicate_param_id {
continue
}
for bound in bound_pred.bounds.iter() {
result.push(bound);
}
}
&ast::WherePredicate::EqPredicate(_) => panic!("not implemented")
}
}

result
}

pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
decl: &ast::FnDecl,
def_id: ast::DefId,
7 changes: 4 additions & 3 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -693,7 +693,7 @@ impl Clean<Option<Lifetime>> for ty::Region {

#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct WherePredicate {
pub name: String,
pub ty: Type,
pub bounds: Vec<TyParamBound>
}

@@ -702,11 +702,12 @@ impl Clean<WherePredicate> for ast::WherePredicate {
match *self {
ast::WherePredicate::BoundPredicate(ref wbp) => {
WherePredicate {
name: wbp.ident.clean(cx),
ty: wbp.bounded_ty.clean(cx),
bounds: wbp.bounds.clean(cx)
}
}
ast::WherePredicate::EqPredicate(_) => {
// FIXME(#20048)
_ => {
unimplemented!();
}
}
2 changes: 1 addition & 1 deletion src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
@@ -129,7 +129,7 @@ impl<'a> fmt::Show for WhereClause<'a> {
try!(f.write(", ".as_bytes()));
}
let bounds = pred.bounds.as_slice();
try!(write!(f, "{}: {}", pred.name, TyParamBounds(bounds)));
try!(write!(f, "{}: {}", pred.ty, TyParamBounds(bounds)));
}
Ok(())
}
11 changes: 9 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
@@ -415,17 +415,24 @@ pub struct WhereClause {
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub enum WherePredicate {
BoundPredicate(WhereBoundPredicate),
RegionPredicate(WhereRegionPredicate),
EqPredicate(WhereEqPredicate)
}

#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct WhereBoundPredicate {
pub id: NodeId,
pub span: Span,
pub ident: Ident,
pub bounded_ty: P<Ty>,
pub bounds: OwnedSlice<TyParamBound>,
}

#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct WhereRegionPredicate {
pub span: Span,
pub lifetime: Lifetime,
pub bounds: Vec<Lifetime>,
}

#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct WhereEqPredicate {
pub id: NodeId,
10 changes: 8 additions & 2 deletions src/libsyntax/ext/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
@@ -426,12 +426,18 @@ impl<'a> TraitDef<'a> {
match *clause {
ast::WherePredicate::BoundPredicate(ref wb) => {
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
id: ast::DUMMY_NODE_ID,
span: self.span,
ident: wb.ident,
bounded_ty: wb.bounded_ty.clone(),
bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect())
})
}
ast::WherePredicate::RegionPredicate(ref rb) => {
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
span: self.span,
lifetime: rb.lifetime,
bounds: rb.bounds.iter().map(|b| b.clone()).collect()
})
}
ast::WherePredicate::EqPredicate(ref we) => {
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
id: ast::DUMMY_NODE_ID,
Loading