Skip to content

librustc: Implement simple where clauses. #16424

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

Merged
merged 1 commit into from
Aug 15, 2014
Merged
Show file tree
Hide file tree
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
31 changes: 31 additions & 0 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3671,6 +3671,7 @@ impl<'a> Resolver<'a> {
ItemRibKind),
|this| {
this.resolve_type_parameters(&generics.ty_params);
this.resolve_where_clause(&generics.where_clause);
visit::walk_item(this, item, ());
});
}
Expand Down Expand Up @@ -3713,6 +3714,7 @@ impl<'a> Resolver<'a> {
NormalRibKind),
|this| {
this.resolve_type_parameters(&generics.ty_params);
this.resolve_where_clause(&generics.where_clause);

// Resolve derived traits.
for trt in traits.iter() {
Expand Down Expand Up @@ -3744,6 +3746,8 @@ impl<'a> Resolver<'a> {
// parameters.
this.resolve_type_parameters(
&ty_m.generics.ty_params);
this.resolve_where_clause(&ty_m.generics
.where_clause);

for argument in ty_m.decl.inputs.iter() {
this.resolve_type(&*argument.ty);
Expand Down Expand Up @@ -3907,6 +3911,7 @@ impl<'a> Resolver<'a> {
}
HasTypeParameters(ref generics, _, _, _) => {
this.resolve_type_parameters(&generics.ty_params);
this.resolve_where_clause(&generics.where_clause);
}
}

Expand Down Expand Up @@ -4022,6 +4027,30 @@ impl<'a> Resolver<'a> {
}
}

fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
for predicate in where_clause.predicates.iter() {
match self.resolve_identifier(predicate.ident,
TypeNS,
true,
predicate.span) {
Some((def @ DefTyParam(_, _, _), last_private)) => {
self.record_def(predicate.id, (def, last_private));
}
_ => {
self.resolve_error(
predicate.span,
format!("undeclared type parameter `{}`",
token::get_ident(
predicate.ident)).as_slice());
}
}

for bound in predicate.bounds.iter() {
self.resolve_type_parameter_bound(predicate.id, bound);
}
}
}

fn resolve_struct(&mut self,
id: NodeId,
generics: &Generics,
Expand All @@ -4035,6 +4064,7 @@ impl<'a> Resolver<'a> {
|this| {
// Resolve the type parameters.
this.resolve_type_parameters(&generics.ty_params);
this.resolve_where_clause(&generics.where_clause);

// Resolve the super struct.
match super_struct {
Expand Down Expand Up @@ -4146,6 +4176,7 @@ impl<'a> Resolver<'a> {
|this| {
// Resolve the type parameters.
this.resolve_type_parameters(&generics.ty_params);
this.resolve_where_clause(&generics.where_clause);

// Resolve the trait reference, if necessary.
this.with_optional_trait_ref(id, opt_trait_reference, |this| {
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ use syntax::util::interner::Interner;
use syntax::codemap::{Span, Pos};
use syntax::{abi, ast, codemap, ast_util, ast_map};
use syntax::ast_util::PostExpansionMethod;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token;
use syntax::parse::token::special_idents;

Expand Down Expand Up @@ -1123,8 +1122,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
}

let empty_generics = ast::Generics { lifetimes: Vec::new(),
ty_params: OwnedSlice::empty() };
let empty_generics = ast_util::empty_generics();

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

Expand Down
173 changes: 107 additions & 66 deletions src/librustc/middle/typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -987,20 +987,26 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,

fn ty_generics_for_type(ccx: &CrateCtxt,
generics: &ast::Generics)
-> ty::Generics
{
ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
&generics.ty_params, ty::Generics::empty())
-> ty::Generics {
ty_generics(ccx,
subst::TypeSpace,
&generics.lifetimes,
&generics.ty_params,
ty::Generics::empty(),
&generics.where_clause)
}

fn ty_generics_for_trait(ccx: &CrateCtxt,
trait_id: ast::NodeId,
substs: &subst::Substs,
generics: &ast::Generics)
-> ty::Generics
{
let mut generics = ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
&generics.ty_params, ty::Generics::empty());
-> ty::Generics {
let mut generics = ty_generics(ccx,
subst::TypeSpace,
&generics.lifetimes,
&generics.ty_params,
ty::Generics::empty(),
&generics.where_clause);

// Something of a hack: use the node id for the trait, also as
// the node id for the Self type parameter.
Expand Down Expand Up @@ -1032,11 +1038,14 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
generics: &ast::Generics,
base_generics: ty::Generics)
-> ty::Generics
{
-> ty::Generics {
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
ty_generics(ccx, subst::FnSpace, &early_lifetimes,
&generics.ty_params, base_generics)
ty_generics(ccx,
subst::FnSpace,
&early_lifetimes,
&generics.ty_params,
base_generics,
&generics.where_clause)
}

// Add the Sized bound, unless the type parameter is marked as `Sized?`.
Expand Down Expand Up @@ -1080,9 +1089,9 @@ fn ty_generics(ccx: &CrateCtxt,
space: subst::ParamSpace,
lifetimes: &Vec<ast::LifetimeDef>,
types: &OwnedSlice<ast::TyParam>,
base_generics: ty::Generics)
-> ty::Generics
{
base_generics: ty::Generics,
where_clause: &ast::WhereClause)
-> ty::Generics {
let mut result = base_generics;

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

for (i, param) in types.iter().enumerate() {
let def = get_or_create_type_parameter_def(ccx, space, param, i);
let def = get_or_create_type_parameter_def(ccx,
space,
param,
i,
where_clause);
debug!("ty_generics: def for type param: {}", def.repr(ccx.tcx));
result.types.push(space, def);
}
Expand All @@ -1105,9 +1118,9 @@ fn ty_generics(ccx: &CrateCtxt,
fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
space: subst::ParamSpace,
param: &ast::TyParam,
index: uint)
-> ty::TypeParameterDef
{
index: uint,
where_clause: &ast::WhereClause)
-> ty::TypeParameterDef {
match ccx.tcx.ty_param_defs.borrow().find(&param.id) {
Some(d) => { return (*d).clone(); }
None => { }
Expand All @@ -1121,7 +1134,8 @@ fn ty_generics(ccx: &CrateCtxt,
&param.bounds,
&param.unbound,
param.ident,
param.span));
param.span,
where_clause));
let default = param.default.map(|path| {
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*path);
let cur_idx = param_ty.idx;
Expand Down Expand Up @@ -1154,14 +1168,14 @@ fn ty_generics(ccx: &CrateCtxt,
def
}

fn compute_bounds(
ccx: &CrateCtxt,
param_ty: ty::ParamTy,
ast_bounds: &OwnedSlice<ast::TyParamBound>,
unbound: &Option<ast::TyParamBound>,
ident: ast::Ident,
span: Span) -> ty::ParamBounds
{
fn compute_bounds(ccx: &CrateCtxt,
param_ty: ty::ParamTy,
ast_bounds: &OwnedSlice<ast::TyParamBound>,
unbound: &Option<ast::TyParamBound>,
ident: ast::Ident,
span: Span,
where_clause: &ast::WhereClause)
-> ty::ParamBounds {
/*!
* Translate the AST's notion of ty param bounds (which are an
* enum consisting of a newtyped Ty or a region) to ty's
Expand All @@ -1174,44 +1188,23 @@ fn ty_generics(ccx: &CrateCtxt,
trait_bounds: Vec::new()
};
for ast_bound in ast_bounds.iter() {
match *ast_bound {
TraitTyParamBound(ref b) => {
let ty = ty::mk_param(ccx.tcx, param_ty.space,
param_ty.idx, param_ty.def_id);
let trait_ref = instantiate_trait_ref(ccx, b, ty);
if !ty::try_add_builtin_trait(
ccx.tcx, trait_ref.def_id,
&mut param_bounds.builtin_bounds) {
// Must be a user-defined trait
param_bounds.trait_bounds.push(trait_ref);
}
}

StaticRegionTyParamBound => {
param_bounds.builtin_bounds.add(ty::BoundStatic);
}

UnboxedFnTyParamBound(ref unboxed_function) => {
let rscope = ExplicitRscope;
let self_ty = ty::mk_param(ccx.tcx,
param_ty.space,
param_ty.idx,
param_ty.def_id);
let trait_ref =
astconv::trait_ref_for_unboxed_function(ccx,
&rscope,
unboxed_function,
Some(self_ty));
param_bounds.trait_bounds.push(Rc::new(trait_ref));
}

OtherRegionTyParamBound(span) => {
if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
ccx.tcx.sess.span_err(
span,
"only the 'static lifetime is accepted here.");
}
}
compute_bound(ccx, &mut param_bounds, param_ty, ast_bound);
}
for predicate in where_clause.predicates.iter() {
let predicate_param_id = ccx.tcx
.def_map
.borrow()
.find(&predicate.id)
.expect("compute_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 predicate.bounds.iter() {
compute_bound(ccx, &mut param_bounds, param_ty, bound);
}
}

Expand All @@ -1228,6 +1221,54 @@ fn ty_generics(ccx: &CrateCtxt,
param_bounds
}

/// Translates the AST's notion of a type parameter bound to
/// typechecking's notion of the same, and pushes the resulting bound onto
/// the appropriate section of `param_bounds`.
fn compute_bound(ccx: &CrateCtxt,
param_bounds: &mut ty::ParamBounds,
param_ty: ty::ParamTy,
ast_bound: &ast::TyParamBound) {
match *ast_bound {
TraitTyParamBound(ref b) => {
let ty = ty::mk_param(ccx.tcx, param_ty.space,
param_ty.idx, param_ty.def_id);
let trait_ref = instantiate_trait_ref(ccx, b, ty);
if !ty::try_add_builtin_trait(
ccx.tcx, trait_ref.def_id,
&mut param_bounds.builtin_bounds) {
// Must be a user-defined trait
param_bounds.trait_bounds.push(trait_ref);
}
}

StaticRegionTyParamBound => {
param_bounds.builtin_bounds.add(ty::BoundStatic);
}

UnboxedFnTyParamBound(ref unboxed_function) => {
let rscope = ExplicitRscope;
let self_ty = ty::mk_param(ccx.tcx,
param_ty.space,
param_ty.idx,
param_ty.def_id);
let trait_ref =
astconv::trait_ref_for_unboxed_function(ccx,
&rscope,
unboxed_function,
Some(self_ty));
param_bounds.trait_bounds.push(Rc::new(trait_ref));
}

OtherRegionTyParamBound(span) => {
if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
ccx.tcx.sess.span_err(
span,
"only the 'static lifetime is accepted here.");
}
}
}
}

fn check_bounds_compatible(tcx: &ty::ctxt,
param_bounds: &ty::ParamBounds,
ident: ast::Ident,
Expand Down
13 changes: 8 additions & 5 deletions src/librustc/middle/typeck/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ impl<'a> Rebuilder<'a> {
let mut inputs = self.fn_decl.inputs.clone();
let mut output = self.fn_decl.output;
let mut ty_params = self.generics.ty_params.clone();
let where_clause = self.generics.where_clause.clone();
let mut kept_lifetimes = HashSet::new();
for sr in self.same_regions.iter() {
self.cur_anon.set(0);
Expand All @@ -807,7 +808,8 @@ impl<'a> Rebuilder<'a> {
&fresh_lifetimes,
&kept_lifetimes,
&all_region_names,
ty_params);
ty_params,
where_clause);
let new_fn_decl = ast::FnDecl {
inputs: inputs,
output: output,
Expand Down Expand Up @@ -981,7 +983,8 @@ impl<'a> Rebuilder<'a> {
add: &Vec<ast::Lifetime>,
keep: &HashSet<ast::Name>,
remove: &HashSet<ast::Name>,
ty_params: OwnedSlice<ast::TyParam>)
ty_params: OwnedSlice<ast::TyParam>,
where_clause: ast::WhereClause)
-> ast::Generics {
let mut lifetimes = Vec::new();
for lt in add.iter() {
Expand All @@ -990,14 +993,14 @@ impl<'a> Rebuilder<'a> {
}
for lt in generics.lifetimes.iter() {
if keep.contains(&lt.lifetime.name) ||
!remove.contains(&lt.lifetime.name)
{
!remove.contains(&lt.lifetime.name) {
lifetimes.push((*lt).clone());
}
}
ast::Generics {
lifetimes: lifetimes,
ty_params: ty_params
ty_params: ty_params,
where_clause: where_clause,
}
}

Expand Down
Loading