Skip to content

Commit 36db386

Browse files
committed
auto merge of #16424 : pcwalton/rust/where-clauses, r=nikomatsakis
These `where` clauses are accepted everywhere generics are currently accepted and desugar during type collection to the type parameter bounds we have today. A new keyword, `where`, has been added. Therefore, this is a breaking change. Change uses of `where` to other identifiers. [breaking-change] r? @nikomatsakis (or whoever)
2 parents bf0a925 + 604af3f commit 36db386

25 files changed

+626
-207
lines changed

src/librustc/middle/resolve.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3671,6 +3671,7 @@ impl<'a> Resolver<'a> {
36713671
ItemRibKind),
36723672
|this| {
36733673
this.resolve_type_parameters(&generics.ty_params);
3674+
this.resolve_where_clause(&generics.where_clause);
36743675
visit::walk_item(this, item, ());
36753676
});
36763677
}
@@ -3713,6 +3714,7 @@ impl<'a> Resolver<'a> {
37133714
NormalRibKind),
37143715
|this| {
37153716
this.resolve_type_parameters(&generics.ty_params);
3717+
this.resolve_where_clause(&generics.where_clause);
37163718

37173719
// Resolve derived traits.
37183720
for trt in traits.iter() {
@@ -3744,6 +3746,8 @@ impl<'a> Resolver<'a> {
37443746
// parameters.
37453747
this.resolve_type_parameters(
37463748
&ty_m.generics.ty_params);
3749+
this.resolve_where_clause(&ty_m.generics
3750+
.where_clause);
37473751

37483752
for argument in ty_m.decl.inputs.iter() {
37493753
this.resolve_type(&*argument.ty);
@@ -3907,6 +3911,7 @@ impl<'a> Resolver<'a> {
39073911
}
39083912
HasTypeParameters(ref generics, _, _, _) => {
39093913
this.resolve_type_parameters(&generics.ty_params);
3914+
this.resolve_where_clause(&generics.where_clause);
39103915
}
39113916
}
39123917

@@ -4022,6 +4027,30 @@ impl<'a> Resolver<'a> {
40224027
}
40234028
}
40244029

4030+
fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
4031+
for predicate in where_clause.predicates.iter() {
4032+
match self.resolve_identifier(predicate.ident,
4033+
TypeNS,
4034+
true,
4035+
predicate.span) {
4036+
Some((def @ DefTyParam(_, _, _), last_private)) => {
4037+
self.record_def(predicate.id, (def, last_private));
4038+
}
4039+
_ => {
4040+
self.resolve_error(
4041+
predicate.span,
4042+
format!("undeclared type parameter `{}`",
4043+
token::get_ident(
4044+
predicate.ident)).as_slice());
4045+
}
4046+
}
4047+
4048+
for bound in predicate.bounds.iter() {
4049+
self.resolve_type_parameter_bound(predicate.id, bound);
4050+
}
4051+
}
4052+
}
4053+
40254054
fn resolve_struct(&mut self,
40264055
id: NodeId,
40274056
generics: &Generics,
@@ -4035,6 +4064,7 @@ impl<'a> Resolver<'a> {
40354064
|this| {
40364065
// Resolve the type parameters.
40374066
this.resolve_type_parameters(&generics.ty_params);
4067+
this.resolve_where_clause(&generics.where_clause);
40384068

40394069
// Resolve the super struct.
40404070
match super_struct {
@@ -4146,6 +4176,7 @@ impl<'a> Resolver<'a> {
41464176
|this| {
41474177
// Resolve the type parameters.
41484178
this.resolve_type_parameters(&generics.ty_params);
4179+
this.resolve_where_clause(&generics.where_clause);
41494180

41504181
// Resolve the trait reference, if necessary.
41514182
this.with_optional_trait_ref(id, opt_trait_reference, |this| {

src/librustc/middle/trans/debuginfo.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ use syntax::util::interner::Interner;
208208
use syntax::codemap::{Span, Pos};
209209
use syntax::{abi, ast, codemap, ast_util, ast_map};
210210
use syntax::ast_util::PostExpansionMethod;
211-
use syntax::owned_slice::OwnedSlice;
212211
use syntax::parse::token;
213212
use syntax::parse::token::special_idents;
214213

@@ -1123,8 +1122,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
11231122
return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
11241123
}
11251124

1126-
let empty_generics = ast::Generics { lifetimes: Vec::new(),
1127-
ty_params: OwnedSlice::empty() };
1125+
let empty_generics = ast_util::empty_generics();
11281126

11291127
let fnitem = cx.tcx.map.get(fn_ast_id);
11301128

src/librustc/middle/typeck/collect.rs

Lines changed: 107 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -987,20 +987,26 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
987987

988988
fn ty_generics_for_type(ccx: &CrateCtxt,
989989
generics: &ast::Generics)
990-
-> ty::Generics
991-
{
992-
ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
993-
&generics.ty_params, ty::Generics::empty())
990+
-> ty::Generics {
991+
ty_generics(ccx,
992+
subst::TypeSpace,
993+
&generics.lifetimes,
994+
&generics.ty_params,
995+
ty::Generics::empty(),
996+
&generics.where_clause)
994997
}
995998

996999
fn ty_generics_for_trait(ccx: &CrateCtxt,
9971000
trait_id: ast::NodeId,
9981001
substs: &subst::Substs,
9991002
generics: &ast::Generics)
1000-
-> ty::Generics
1001-
{
1002-
let mut generics = ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
1003-
&generics.ty_params, ty::Generics::empty());
1003+
-> ty::Generics {
1004+
let mut generics = ty_generics(ccx,
1005+
subst::TypeSpace,
1006+
&generics.lifetimes,
1007+
&generics.ty_params,
1008+
ty::Generics::empty(),
1009+
&generics.where_clause);
10041010

10051011
// Something of a hack: use the node id for the trait, also as
10061012
// the node id for the Self type parameter.
@@ -1032,11 +1038,14 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
10321038
fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
10331039
generics: &ast::Generics,
10341040
base_generics: ty::Generics)
1035-
-> ty::Generics
1036-
{
1041+
-> ty::Generics {
10371042
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1038-
ty_generics(ccx, subst::FnSpace, &early_lifetimes,
1039-
&generics.ty_params, base_generics)
1043+
ty_generics(ccx,
1044+
subst::FnSpace,
1045+
&early_lifetimes,
1046+
&generics.ty_params,
1047+
base_generics,
1048+
&generics.where_clause)
10401049
}
10411050

10421051
// Add the Sized bound, unless the type parameter is marked as `Sized?`.
@@ -1080,9 +1089,9 @@ fn ty_generics(ccx: &CrateCtxt,
10801089
space: subst::ParamSpace,
10811090
lifetimes: &Vec<ast::LifetimeDef>,
10821091
types: &OwnedSlice<ast::TyParam>,
1083-
base_generics: ty::Generics)
1084-
-> ty::Generics
1085-
{
1092+
base_generics: ty::Generics,
1093+
where_clause: &ast::WhereClause)
1094+
-> ty::Generics {
10861095
let mut result = base_generics;
10871096

10881097
for (i, l) in lifetimes.iter().enumerate() {
@@ -1095,7 +1104,11 @@ fn ty_generics(ccx: &CrateCtxt,
10951104
}
10961105

10971106
for (i, param) in types.iter().enumerate() {
1098-
let def = get_or_create_type_parameter_def(ccx, space, param, i);
1107+
let def = get_or_create_type_parameter_def(ccx,
1108+
space,
1109+
param,
1110+
i,
1111+
where_clause);
10991112
debug!("ty_generics: def for type param: {}", def.repr(ccx.tcx));
11001113
result.types.push(space, def);
11011114
}
@@ -1105,9 +1118,9 @@ fn ty_generics(ccx: &CrateCtxt,
11051118
fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
11061119
space: subst::ParamSpace,
11071120
param: &ast::TyParam,
1108-
index: uint)
1109-
-> ty::TypeParameterDef
1110-
{
1121+
index: uint,
1122+
where_clause: &ast::WhereClause)
1123+
-> ty::TypeParameterDef {
11111124
match ccx.tcx.ty_param_defs.borrow().find(&param.id) {
11121125
Some(d) => { return (*d).clone(); }
11131126
None => { }
@@ -1121,7 +1134,8 @@ fn ty_generics(ccx: &CrateCtxt,
11211134
&param.bounds,
11221135
&param.unbound,
11231136
param.ident,
1124-
param.span));
1137+
param.span,
1138+
where_clause));
11251139
let default = param.default.map(|path| {
11261140
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*path);
11271141
let cur_idx = param_ty.idx;
@@ -1154,14 +1168,14 @@ fn ty_generics(ccx: &CrateCtxt,
11541168
def
11551169
}
11561170

1157-
fn compute_bounds(
1158-
ccx: &CrateCtxt,
1159-
param_ty: ty::ParamTy,
1160-
ast_bounds: &OwnedSlice<ast::TyParamBound>,
1161-
unbound: &Option<ast::TyParamBound>,
1162-
ident: ast::Ident,
1163-
span: Span) -> ty::ParamBounds
1164-
{
1171+
fn compute_bounds(ccx: &CrateCtxt,
1172+
param_ty: ty::ParamTy,
1173+
ast_bounds: &OwnedSlice<ast::TyParamBound>,
1174+
unbound: &Option<ast::TyParamBound>,
1175+
ident: ast::Ident,
1176+
span: Span,
1177+
where_clause: &ast::WhereClause)
1178+
-> ty::ParamBounds {
11651179
/*!
11661180
* Translate the AST's notion of ty param bounds (which are an
11671181
* enum consisting of a newtyped Ty or a region) to ty's
@@ -1174,44 +1188,23 @@ fn ty_generics(ccx: &CrateCtxt,
11741188
trait_bounds: Vec::new()
11751189
};
11761190
for ast_bound in ast_bounds.iter() {
1177-
match *ast_bound {
1178-
TraitTyParamBound(ref b) => {
1179-
let ty = ty::mk_param(ccx.tcx, param_ty.space,
1180-
param_ty.idx, param_ty.def_id);
1181-
let trait_ref = instantiate_trait_ref(ccx, b, ty);
1182-
if !ty::try_add_builtin_trait(
1183-
ccx.tcx, trait_ref.def_id,
1184-
&mut param_bounds.builtin_bounds) {
1185-
// Must be a user-defined trait
1186-
param_bounds.trait_bounds.push(trait_ref);
1187-
}
1188-
}
1189-
1190-
StaticRegionTyParamBound => {
1191-
param_bounds.builtin_bounds.add(ty::BoundStatic);
1192-
}
1193-
1194-
UnboxedFnTyParamBound(ref unboxed_function) => {
1195-
let rscope = ExplicitRscope;
1196-
let self_ty = ty::mk_param(ccx.tcx,
1197-
param_ty.space,
1198-
param_ty.idx,
1199-
param_ty.def_id);
1200-
let trait_ref =
1201-
astconv::trait_ref_for_unboxed_function(ccx,
1202-
&rscope,
1203-
unboxed_function,
1204-
Some(self_ty));
1205-
param_bounds.trait_bounds.push(Rc::new(trait_ref));
1206-
}
1207-
1208-
OtherRegionTyParamBound(span) => {
1209-
if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
1210-
ccx.tcx.sess.span_err(
1211-
span,
1212-
"only the 'static lifetime is accepted here.");
1213-
}
1214-
}
1191+
compute_bound(ccx, &mut param_bounds, param_ty, ast_bound);
1192+
}
1193+
for predicate in where_clause.predicates.iter() {
1194+
let predicate_param_id = ccx.tcx
1195+
.def_map
1196+
.borrow()
1197+
.find(&predicate.id)
1198+
.expect("compute_bounds(): resolve \
1199+
didn't resolve the type \
1200+
parameter identifier in a \
1201+
`where` clause")
1202+
.def_id();
1203+
if param_ty.def_id != predicate_param_id {
1204+
continue
1205+
}
1206+
for bound in predicate.bounds.iter() {
1207+
compute_bound(ccx, &mut param_bounds, param_ty, bound);
12151208
}
12161209
}
12171210

@@ -1228,6 +1221,54 @@ fn ty_generics(ccx: &CrateCtxt,
12281221
param_bounds
12291222
}
12301223

1224+
/// Translates the AST's notion of a type parameter bound to
1225+
/// typechecking's notion of the same, and pushes the resulting bound onto
1226+
/// the appropriate section of `param_bounds`.
1227+
fn compute_bound(ccx: &CrateCtxt,
1228+
param_bounds: &mut ty::ParamBounds,
1229+
param_ty: ty::ParamTy,
1230+
ast_bound: &ast::TyParamBound) {
1231+
match *ast_bound {
1232+
TraitTyParamBound(ref b) => {
1233+
let ty = ty::mk_param(ccx.tcx, param_ty.space,
1234+
param_ty.idx, param_ty.def_id);
1235+
let trait_ref = instantiate_trait_ref(ccx, b, ty);
1236+
if !ty::try_add_builtin_trait(
1237+
ccx.tcx, trait_ref.def_id,
1238+
&mut param_bounds.builtin_bounds) {
1239+
// Must be a user-defined trait
1240+
param_bounds.trait_bounds.push(trait_ref);
1241+
}
1242+
}
1243+
1244+
StaticRegionTyParamBound => {
1245+
param_bounds.builtin_bounds.add(ty::BoundStatic);
1246+
}
1247+
1248+
UnboxedFnTyParamBound(ref unboxed_function) => {
1249+
let rscope = ExplicitRscope;
1250+
let self_ty = ty::mk_param(ccx.tcx,
1251+
param_ty.space,
1252+
param_ty.idx,
1253+
param_ty.def_id);
1254+
let trait_ref =
1255+
astconv::trait_ref_for_unboxed_function(ccx,
1256+
&rscope,
1257+
unboxed_function,
1258+
Some(self_ty));
1259+
param_bounds.trait_bounds.push(Rc::new(trait_ref));
1260+
}
1261+
1262+
OtherRegionTyParamBound(span) => {
1263+
if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
1264+
ccx.tcx.sess.span_err(
1265+
span,
1266+
"only the 'static lifetime is accepted here.");
1267+
}
1268+
}
1269+
}
1270+
}
1271+
12311272
fn check_bounds_compatible(tcx: &ty::ctxt,
12321273
param_bounds: &ty::ParamBounds,
12331274
ident: ast::Ident,

src/librustc/middle/typeck/infer/error_reporting.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,7 @@ impl<'a> Rebuilder<'a> {
781781
let mut inputs = self.fn_decl.inputs.clone();
782782
let mut output = self.fn_decl.output;
783783
let mut ty_params = self.generics.ty_params.clone();
784+
let where_clause = self.generics.where_clause.clone();
784785
let mut kept_lifetimes = HashSet::new();
785786
for sr in self.same_regions.iter() {
786787
self.cur_anon.set(0);
@@ -807,7 +808,8 @@ impl<'a> Rebuilder<'a> {
807808
&fresh_lifetimes,
808809
&kept_lifetimes,
809810
&all_region_names,
810-
ty_params);
811+
ty_params,
812+
where_clause);
811813
let new_fn_decl = ast::FnDecl {
812814
inputs: inputs,
813815
output: output,
@@ -981,7 +983,8 @@ impl<'a> Rebuilder<'a> {
981983
add: &Vec<ast::Lifetime>,
982984
keep: &HashSet<ast::Name>,
983985
remove: &HashSet<ast::Name>,
984-
ty_params: OwnedSlice<ast::TyParam>)
986+
ty_params: OwnedSlice<ast::TyParam>,
987+
where_clause: ast::WhereClause)
985988
-> ast::Generics {
986989
let mut lifetimes = Vec::new();
987990
for lt in add.iter() {
@@ -990,14 +993,14 @@ impl<'a> Rebuilder<'a> {
990993
}
991994
for lt in generics.lifetimes.iter() {
992995
if keep.contains(&lt.lifetime.name) ||
993-
!remove.contains(&lt.lifetime.name)
994-
{
996+
!remove.contains(&lt.lifetime.name) {
995997
lifetimes.push((*lt).clone());
996998
}
997999
}
9981000
ast::Generics {
9991001
lifetimes: lifetimes,
1000-
ty_params: ty_params
1002+
ty_params: ty_params,
1003+
where_clause: where_clause,
10011004
}
10021005
}
10031006

0 commit comments

Comments
 (0)