auto merge of #20572 : nikomatsakis/rust/assoc-supertrait-stuff, r=brson
The first few commits in the PR are just general refactoring. I was intending them for some other code I didn't get around to writing yet, but might as well land them now. cc @japaric Fixes #19541
This commit is contained in:
commit
f11f3e7bae
@ -53,7 +53,8 @@ use middle::def;
|
||||
use middle::resolve_lifetime as rl;
|
||||
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
||||
use middle::subst::{VecPerParamSpace};
|
||||
use middle::ty::{self, RegionEscape, Ty};
|
||||
use middle::traits;
|
||||
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
|
||||
use rscope::{self, UnelidableRscope, RegionScope, SpecificRscope,
|
||||
ShiftedRscope, BindingRscope};
|
||||
use TypeAndSubsts;
|
||||
@ -70,7 +71,9 @@ use syntax::print::pprust;
|
||||
|
||||
pub trait AstConv<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
||||
|
||||
fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx>;
|
||||
|
||||
fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
|
||||
|
||||
/// Return an (optional) substitution to convert bound type parameters that
|
||||
@ -162,9 +165,9 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
|
||||
r
|
||||
}
|
||||
|
||||
pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn opt_ast_region_to_region<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
default_span: Span,
|
||||
opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
|
||||
{
|
||||
@ -241,13 +244,12 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
|
||||
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
|
||||
/// returns an appropriate set of substitutions for this particular reference to `I`.
|
||||
fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
fn ast_path_substs_for_ty<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
path: &ast::Path)
|
||||
-> Substs<'tcx>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
|
||||
@ -285,16 +287,15 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||
regions)
|
||||
}
|
||||
|
||||
fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
fn create_substs_for_ast_path<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
types: Vec<Ty<'tcx>>,
|
||||
regions: Vec<ty::Region>)
|
||||
-> Substs<'tcx>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
-> Substs<'tcx>
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
|
||||
@ -408,13 +409,12 @@ struct ConvertedBinding<'tcx> {
|
||||
span: Span,
|
||||
}
|
||||
|
||||
fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
data: &ast::AngleBracketedParameterData)
|
||||
-> (Vec<ty::Region>,
|
||||
Vec<Ty<'tcx>>,
|
||||
Vec<ConvertedBinding<'tcx>>)
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
data: &ast::AngleBracketedParameterData)
|
||||
-> (Vec<ty::Region>,
|
||||
Vec<Ty<'tcx>>,
|
||||
Vec<ConvertedBinding<'tcx>>)
|
||||
{
|
||||
let regions: Vec<_> =
|
||||
data.lifetimes.iter()
|
||||
@ -468,12 +468,11 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
|
||||
(implied_output_region, lifetimes_for_params)
|
||||
}
|
||||
|
||||
fn convert_ty_with_lifetime_elision<'tcx,AC>(this: &AC,
|
||||
implied_output_region: Option<ty::Region>,
|
||||
param_lifetimes: Vec<(String, uint)>,
|
||||
ty: &ast::Ty)
|
||||
-> Ty<'tcx>
|
||||
where AC: AstConv<'tcx>
|
||||
fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>,
|
||||
implied_output_region: Option<ty::Region>,
|
||||
param_lifetimes: Vec<(String, uint)>,
|
||||
ty: &ast::Ty)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
match implied_output_region {
|
||||
Some(implied_output_region) => {
|
||||
@ -490,10 +489,9 @@ fn convert_ty_with_lifetime_elision<'tcx,AC>(this: &AC,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
|
||||
data: &ast::ParenthesizedParameterData)
|
||||
-> Vec<Ty<'tcx>>
|
||||
where AC: AstConv<'tcx>
|
||||
fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
|
||||
data: &ast::ParenthesizedParameterData)
|
||||
-> Vec<Ty<'tcx>>
|
||||
{
|
||||
let binding_rscope = BindingRscope::new();
|
||||
let inputs = data.inputs.iter()
|
||||
@ -517,14 +515,13 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
|
||||
vec![input_ty, output]
|
||||
}
|
||||
|
||||
pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn instantiate_poly_trait_ref<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
ast_trait_ref: &ast::PolyTraitRef,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
|
||||
-> ty::PolyTraitRef<'tcx>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
let mut projections = Vec::new();
|
||||
|
||||
@ -545,14 +542,13 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
|
||||
///
|
||||
/// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
|
||||
/// are disallowed. Otherwise, they are pushed onto the vector given.
|
||||
pub fn instantiate_trait_ref<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn instantiate_trait_ref<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
|
||||
-> Rc<ty::TraitRef<'tcx>>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
|
||||
def::DefTrait(trait_def_id) => {
|
||||
@ -573,15 +569,14 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(
|
||||
}
|
||||
}
|
||||
|
||||
fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
fn ast_path_to_trait_ref<'a,'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
trait_def_id: ast::DefId,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
path: &ast::Path,
|
||||
mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
|
||||
-> Rc<ty::TraitRef<'tcx>>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
debug!("ast_path_to_trait_ref {}", path);
|
||||
let trait_def = this.get_trait_def(trait_def_id);
|
||||
@ -632,7 +627,8 @@ fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
|
||||
}
|
||||
Some(ref mut v) => {
|
||||
for binding in assoc_bindings.iter() {
|
||||
match ast_type_binding_to_projection_predicate(this, trait_ref.clone(), binding) {
|
||||
match ast_type_binding_to_projection_predicate(this, trait_ref.clone(),
|
||||
self_ty, binding) {
|
||||
Ok(pp) => { v.push(pp); }
|
||||
Err(ErrorReported) => { }
|
||||
}
|
||||
@ -643,13 +639,15 @@ fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
|
||||
trait_ref
|
||||
}
|
||||
|
||||
pub fn ast_type_binding_to_projection_predicate<'tcx,AC>(
|
||||
this: &AC,
|
||||
trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||
fn ast_type_binding_to_projection_predicate<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
mut trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
binding: &ConvertedBinding<'tcx>)
|
||||
-> Result<ty::ProjectionPredicate<'tcx>, ErrorReported>
|
||||
where AC : AstConv<'tcx>
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
|
||||
// Given something like `U : SomeTrait<T=X>`, we want to produce a
|
||||
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
|
||||
// subtle in the event that `T` is defined in a supertrait of
|
||||
@ -666,29 +664,93 @@ pub fn ast_type_binding_to_projection_predicate<'tcx,AC>(
|
||||
//
|
||||
// We want to produce `<B as SuperTrait<int>>::T == foo`.
|
||||
|
||||
// FIXME(#19541): supertrait upcasting not actually impl'd :)
|
||||
// Simple case: X is defined in the current trait.
|
||||
if trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
|
||||
return Ok(ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy {
|
||||
trait_ref: trait_ref,
|
||||
item_name: binding.item_name,
|
||||
},
|
||||
ty: binding.ty,
|
||||
});
|
||||
}
|
||||
|
||||
if !trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
|
||||
this.tcx().sess.span_err(
|
||||
// Otherwise, we have to walk through the supertraits to find
|
||||
// those that do. This is complicated by the fact that, for an
|
||||
// object type, the `Self` type is not present in the
|
||||
// substitutions (after all, it's being constructed right now),
|
||||
// but the `supertraits` iterator really wants one. To handle
|
||||
// this, we currently insert a dummy type and then remove it
|
||||
// later. Yuck.
|
||||
|
||||
let dummy_self_ty = ty::mk_infer(tcx, ty::FreshTy(0));
|
||||
if self_ty.is_none() { // if converting for an object type
|
||||
let mut dummy_substs = trait_ref.substs.clone();
|
||||
assert!(dummy_substs.self_ty().is_none());
|
||||
dummy_substs.types.push(SelfSpace, dummy_self_ty);
|
||||
trait_ref = Rc::new(ty::TraitRef::new(trait_ref.def_id,
|
||||
tcx.mk_substs(dummy_substs)));
|
||||
}
|
||||
|
||||
let mut candidates: Vec<ty::PolyTraitRef> =
|
||||
traits::supertraits(tcx, trait_ref.to_poly_trait_ref())
|
||||
.filter(|r| trait_defines_associated_type_named(this, r.def_id(), binding.item_name))
|
||||
.collect();
|
||||
|
||||
// If converting for an object type, then remove the dummy-ty from `Self` now.
|
||||
// Yuckety yuck.
|
||||
if self_ty.is_none() {
|
||||
for candidate in candidates.iter_mut() {
|
||||
let mut dummy_substs = candidate.0.substs.clone();
|
||||
assert!(dummy_substs.self_ty() == Some(dummy_self_ty));
|
||||
dummy_substs.types.pop(SelfSpace);
|
||||
*candidate = ty::Binder(Rc::new(ty::TraitRef::new(candidate.def_id(),
|
||||
tcx.mk_substs(dummy_substs))));
|
||||
}
|
||||
}
|
||||
|
||||
if candidates.len() > 1 {
|
||||
tcx.sess.span_err(
|
||||
binding.span,
|
||||
format!("no associated type `{}` defined in `{}`",
|
||||
format!("ambiguous associated type: `{}` defined in multiple supertraits `{}`",
|
||||
token::get_name(binding.item_name),
|
||||
trait_ref.user_string(this.tcx())).as_slice());
|
||||
candidates.user_string(tcx)).as_slice());
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
let candidate = match candidates.pop() {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
tcx.sess.span_err(
|
||||
binding.span,
|
||||
format!("no associated type `{}` defined in `{}`",
|
||||
token::get_name(binding.item_name),
|
||||
trait_ref.user_string(tcx)).as_slice());
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
};
|
||||
|
||||
if ty::binds_late_bound_regions(tcx, &candidate) {
|
||||
tcx.sess.span_err(
|
||||
binding.span,
|
||||
format!("associated type `{}` defined in higher-ranked supertrait `{}`",
|
||||
token::get_name(binding.item_name),
|
||||
candidate.user_string(tcx)).as_slice());
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
Ok(ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy {
|
||||
trait_ref: trait_ref,
|
||||
trait_ref: candidate.0,
|
||||
item_name: binding.item_name,
|
||||
},
|
||||
ty: binding.ty,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn ast_path_to_ty<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
did: ast::DefId,
|
||||
path: &ast::Path)
|
||||
-> TypeAndSubsts<'tcx>
|
||||
@ -712,13 +774,12 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
/// and/or region variables are substituted.
|
||||
///
|
||||
/// This is used when checking the constructor in struct literals.
|
||||
pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn ast_path_to_ty_relaxed<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
did: ast::DefId,
|
||||
path: &ast::Path)
|
||||
-> TypeAndSubsts<'tcx>
|
||||
where AC : AstConv<'tcx>, RS : RegionScope
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
let ty::TypeScheme {
|
||||
@ -754,9 +815,9 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
|
||||
|
||||
/// Converts the given AST type to a built-in type. A "built-in type" is, at
|
||||
/// present, either a core numeric type, a string, or `Box`.
|
||||
pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn ast_ty_to_builtin_ty<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
ast_ty: &ast::Ty)
|
||||
-> Option<Ty<'tcx>> {
|
||||
match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
|
||||
@ -807,12 +868,11 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
|
||||
type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
|
||||
|
||||
fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
ty: &ast::Ty,
|
||||
bounds: &[ast::TyParamBound])
|
||||
-> Result<TraitAndProjections<'tcx>, ErrorReported>
|
||||
where AC : AstConv<'tcx>, RS : RegionScope
|
||||
fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
ty: &ast::Ty,
|
||||
bounds: &[ast::TyParamBound])
|
||||
-> Result<TraitAndProjections<'tcx>, ErrorReported>
|
||||
{
|
||||
/*!
|
||||
* In a type like `Foo + Send`, we want to wait to collect the
|
||||
@ -878,14 +938,13 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
span: Span,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
|
||||
bounds: &[ast::TyParamBound])
|
||||
-> Ty<'tcx>
|
||||
where AC : AstConv<'tcx>, RS : RegionScope
|
||||
fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
|
||||
bounds: &[ast::TyParamBound])
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
let existential_bounds = conv_existential_bounds(this,
|
||||
rscope,
|
||||
@ -909,6 +968,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
let ty_param_def_id = provenance.def_id();
|
||||
|
||||
let mut suitable_bounds: Vec<_>;
|
||||
let ty_param_name: ast::Name;
|
||||
{ // contain scope of refcell:
|
||||
@ -916,13 +976,9 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
let ty_param_def = &ty_param_defs[ty_param_def_id.node];
|
||||
ty_param_name = ty_param_def.name;
|
||||
|
||||
// FIXME(#19541): we should consider associated types in
|
||||
// super-traits. Probably by elaborating the bounds.
|
||||
|
||||
// FIXME(#20300) -- search where clauses, not bounds
|
||||
suitable_bounds =
|
||||
ty_param_def.bounds.trait_bounds // FIXME(#20300) -- search where clauses, not bounds
|
||||
.iter()
|
||||
.cloned()
|
||||
traits::transitive_bounds(tcx, ty_param_def.bounds.trait_bounds.as_slice())
|
||||
.filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
|
||||
.collect();
|
||||
}
|
||||
@ -963,12 +1019,11 @@ fn trait_defines_associated_type_named(this: &AstConv,
|
||||
trait_def.associated_type_names.contains(&assoc_name)
|
||||
}
|
||||
|
||||
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
ast_ty: &ast::Ty, // the TyQPath
|
||||
qpath: &ast::QPath)
|
||||
-> Ty<'tcx>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
ast_ty: &ast::Ty, // the TyQPath
|
||||
qpath: &ast::QPath)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
debug!("qpath_to_ty(ast_ty={})",
|
||||
ast_ty.repr(this.tcx()));
|
||||
@ -992,8 +1047,8 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
|
||||
// Parses the programmer's textual representation of a type into our
|
||||
// internal notion of a type.
|
||||
pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>
|
||||
pub fn ast_ty_to_ty<'tcx>(
|
||||
this: &AstConv<'tcx>, rscope: &RegionScope, ast_ty: &ast::Ty) -> Ty<'tcx>
|
||||
{
|
||||
debug!("ast_ty_to_ty(ast_ty={})",
|
||||
ast_ty.repr(this.tcx()));
|
||||
@ -1205,10 +1260,12 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
return typ;
|
||||
}
|
||||
|
||||
pub fn ty_of_arg<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(this: &AC, rscope: &RS,
|
||||
a: &ast::Arg,
|
||||
expected_ty: Option<Ty<'tcx>>)
|
||||
-> Ty<'tcx> {
|
||||
pub fn ty_of_arg<'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
a: &ast::Arg,
|
||||
expected_ty: Option<Ty<'tcx>>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
match a.ty.node {
|
||||
ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
|
||||
ast::TyInfer => this.ty_infer(a.ty.span),
|
||||
@ -1221,14 +1278,13 @@ struct SelfInfo<'a, 'tcx> {
|
||||
explicit_self: &'a ast::ExplicitSelf,
|
||||
}
|
||||
|
||||
pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
|
||||
this: &AC,
|
||||
unsafety: ast::Unsafety,
|
||||
untransformed_self_ty: Ty<'tcx>,
|
||||
explicit_self: &ast::ExplicitSelf,
|
||||
decl: &ast::FnDecl,
|
||||
abi: abi::Abi)
|
||||
-> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
|
||||
pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>,
|
||||
unsafety: ast::Unsafety,
|
||||
untransformed_self_ty: Ty<'tcx>,
|
||||
explicit_self: &ast::ExplicitSelf,
|
||||
decl: &ast::FnDecl,
|
||||
abi: abi::Abi)
|
||||
-> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
|
||||
let self_info = Some(SelfInfo {
|
||||
untransformed_self_ty: untransformed_self_ty,
|
||||
explicit_self: explicit_self,
|
||||
@ -1242,20 +1298,18 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
|
||||
(bare_fn_ty, optional_explicit_self_category.unwrap())
|
||||
}
|
||||
|
||||
pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, unsafety: ast::Unsafety, abi: abi::Abi,
|
||||
pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx>, unsafety: ast::Unsafety, abi: abi::Abi,
|
||||
decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> {
|
||||
let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl);
|
||||
bare_fn_ty
|
||||
}
|
||||
|
||||
fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
|
||||
this: &AC,
|
||||
unsafety: ast::Unsafety,
|
||||
abi: abi::Abi,
|
||||
opt_self_info: Option<SelfInfo<'a, 'tcx>>,
|
||||
decl: &ast::FnDecl)
|
||||
-> (ty::BareFnTy<'tcx>,
|
||||
Option<ty::ExplicitSelfCategory>)
|
||||
fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
|
||||
unsafety: ast::Unsafety,
|
||||
abi: abi::Abi,
|
||||
opt_self_info: Option<SelfInfo<'a, 'tcx>>,
|
||||
decl: &ast::FnDecl)
|
||||
-> (ty::BareFnTy<'tcx>, Option<ty::ExplicitSelfCategory>)
|
||||
{
|
||||
debug!("ty_of_method_or_bare_fn");
|
||||
|
||||
@ -1357,12 +1411,10 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
|
||||
}, explicit_self_category_result)
|
||||
}
|
||||
|
||||
fn determine_explicit_self_category<'a, 'tcx, AC: AstConv<'tcx>,
|
||||
RS:RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
self_info: &SelfInfo<'a, 'tcx>)
|
||||
-> ty::ExplicitSelfCategory
|
||||
fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
self_info: &SelfInfo<'a, 'tcx>)
|
||||
-> ty::ExplicitSelfCategory
|
||||
{
|
||||
return match self_info.explicit_self.node {
|
||||
ast::SelfStatic => ty::StaticExplicitSelfCategory,
|
||||
@ -1439,8 +1491,8 @@ fn determine_explicit_self_category<'a, 'tcx, AC: AstConv<'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
|
||||
this: &AC,
|
||||
pub fn ty_of_closure<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
unsafety: ast::Unsafety,
|
||||
onceness: ast::Onceness,
|
||||
bounds: ty::ExistentialBounds<'tcx>,
|
||||
@ -1501,9 +1553,9 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
|
||||
/// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent
|
||||
/// for closures. Eventually this should all be normalized, I think, so that there is no "main
|
||||
/// trait ref" and instead we just have a flat list of bounds as the existential type.
|
||||
pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn conv_existential_bounds<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
|
||||
projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
|
||||
@ -1517,13 +1569,12 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
|
||||
this, rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
|
||||
}
|
||||
|
||||
fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
fn conv_ty_poly_trait_ref<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
ast_bounds: &[ast::TyParamBound])
|
||||
-> Ty<'tcx>
|
||||
where AC: AstConv<'tcx>, RS:RegionScope
|
||||
{
|
||||
let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
|
||||
|
||||
@ -1556,15 +1607,14 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
|
||||
mut projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, // Empty for boxed closures
|
||||
partitioned_bounds: PartitionedBounds)
|
||||
-> ty::ExistentialBounds<'tcx>
|
||||
where AC: AstConv<'tcx>, RS:RegionScope
|
||||
{
|
||||
let PartitionedBounds { builtin_bounds,
|
||||
trait_bounds,
|
||||
@ -1657,9 +1707,9 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
/// A version of `compute_opt_region_bound` for use where some region bound is required
|
||||
/// (existential types, basically). Reports an error if no region bound can be derived and we are
|
||||
/// in an `rscope` that does not provide a default.
|
||||
fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
fn compute_region_bound<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
region_bounds: &[&ast::Lifetime],
|
||||
principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for closures
|
||||
|
@ -4939,7 +4939,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
|
||||
Some(i) => {
|
||||
span_err!(ccx.tcx.sess, v.span, E0081,
|
||||
"discriminant value `{}` already exists", disr_vals[i]);
|
||||
span_note!(ccx.tcx.sess, ccx.tcx().map.span(variants[i].id.node),
|
||||
span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
|
||||
"conflicting discriminant here")
|
||||
}
|
||||
None => {}
|
||||
|
@ -40,11 +40,12 @@ use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitCont
|
||||
use middle::ty::{self, RegionEscape, Ty, TypeScheme};
|
||||
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
|
||||
use middle::infer;
|
||||
use no_params;
|
||||
use rscope::*;
|
||||
use {CrateCtxt, no_params, write_ty_to_tcx};
|
||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
use util::ppaux;
|
||||
use util::ppaux::{Repr,UserString};
|
||||
use write_ty_to_tcx;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -61,13 +62,8 @@ use syntax::visit;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Main entry point
|
||||
|
||||
pub fn collect_item_types(ccx: &CrateCtxt) {
|
||||
fn collect_intrinsic_type(ccx: &CrateCtxt,
|
||||
lang_item: ast::DefId) {
|
||||
let ty::TypeScheme { ty, .. } =
|
||||
ccx.get_item_type_scheme(lang_item);
|
||||
ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
|
||||
}
|
||||
pub fn collect_item_types(tcx: &ty::ctxt) {
|
||||
let ccx = &CollectCtxt { tcx: tcx };
|
||||
|
||||
match ccx.tcx.lang_items.ty_desc() {
|
||||
Some(id) => { collect_intrinsic_type(ccx, id); }
|
||||
@ -85,13 +81,29 @@ pub fn collect_item_types(ccx: &CrateCtxt) {
|
||||
visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CollectCtxt<'a,'tcx:'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Zeroth phase: collect types of intrinsics
|
||||
|
||||
fn collect_intrinsic_type(ccx: &CollectCtxt,
|
||||
lang_item: ast::DefId) {
|
||||
let ty::TypeScheme { ty, .. } =
|
||||
ccx.get_item_type_scheme(lang_item);
|
||||
ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// First phase: just collect *trait definitions* -- basically, the set
|
||||
// of type parameters and supertraits. This is information we need to
|
||||
// know later when parsing field defs.
|
||||
|
||||
struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
|
||||
ccx: &'a CrateCtxt<'a, 'tcx>
|
||||
ccx: &'a CollectCtxt<'a, 'tcx>
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
|
||||
@ -112,7 +124,7 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
|
||||
// Second phase: collection proper.
|
||||
|
||||
struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
|
||||
ccx: &'a CrateCtxt<'a, 'tcx>
|
||||
ccx: &'a CollectCtxt<'a, 'tcx>
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
|
||||
@ -133,13 +145,13 @@ pub trait ToTy<'tcx> {
|
||||
fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a,'tcx> ToTy<'tcx> for CrateCtxt<'a,'tcx> {
|
||||
impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> {
|
||||
fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
|
||||
ast_ty_to_ty(self, rs, ast_ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
|
||||
impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> {
|
||||
fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
|
||||
|
||||
fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
|
||||
@ -148,7 +160,9 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
match self.tcx.map.find(id.node) {
|
||||
Some(ast_map::NodeItem(item)) => ty_of_item(self, &*item),
|
||||
Some(ast_map::NodeItem(item)) => {
|
||||
ty_of_item(self, &*item)
|
||||
}
|
||||
Some(ast_map::NodeForeignItem(foreign_item)) => {
|
||||
let abi = self.tcx.map.get_foreign_abi(id.node);
|
||||
ty_of_foreign_item(self, &*foreign_item, abi)
|
||||
@ -181,7 +195,7 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
enum_ty: Ty<'tcx>,
|
||||
variants: &[P<ast::Variant>],
|
||||
generics: &ast::Generics) {
|
||||
@ -226,7 +240,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
trait_id: ast::NodeId,
|
||||
trait_def: &ty::TraitDef<'tcx>) {
|
||||
let tcx = ccx.tcx;
|
||||
@ -322,7 +336,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
|
||||
fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
|
||||
ccx.tcx.tcache.borrow_mut().insert(
|
||||
m.def_id,
|
||||
TypeScheme {
|
||||
@ -330,7 +344,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) });
|
||||
}
|
||||
|
||||
fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
trait_id: ast::NodeId,
|
||||
trait_generics: &ty::Generics<'tcx>,
|
||||
_trait_items: &[ast::TraitItem],
|
||||
@ -372,7 +386,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
struct_generics: &ty::Generics<'tcx>,
|
||||
v: &ast::StructField,
|
||||
origin: ast::DefId) -> ty::field_ty {
|
||||
@ -405,7 +419,7 @@ pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
trait_def: &ty::TraitDef<'tcx>,
|
||||
associated_type: &ast::AssociatedType)
|
||||
{
|
||||
@ -422,7 +436,7 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
ty::TypeTraitItem(associated_type));
|
||||
}
|
||||
|
||||
fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
container: ImplOrTraitItemContainer,
|
||||
mut ms: I,
|
||||
untransformed_rcvr_ty: Ty<'tcx>,
|
||||
@ -469,7 +483,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
.insert(mty.def_id, ty::MethodTraitItem(mty));
|
||||
}
|
||||
|
||||
fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
container: ImplOrTraitItemContainer,
|
||||
m: &ast::Method,
|
||||
untransformed_rcvr_ty: Ty<'tcx>,
|
||||
@ -506,7 +520,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
|
||||
fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
|
||||
span: Span,
|
||||
generics: &ast::Generics,
|
||||
thing: &'static str) {
|
||||
@ -535,7 +549,7 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
fn convert(ccx: &CollectCtxt, it: &ast::Item) {
|
||||
let tcx = ccx.tcx;
|
||||
debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
|
||||
match it.node {
|
||||
@ -636,7 +650,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
|
||||
debug!("trait_def: ident={} trait_def={}",
|
||||
it.ident.repr(ccx.tcx),
|
||||
trait_def.repr(ccx.tcx()));
|
||||
trait_def.repr(ccx.tcx));
|
||||
|
||||
for trait_method in trait_methods.iter() {
|
||||
let self_type = ty::mk_self_type(tcx);
|
||||
@ -706,7 +720,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
struct_def: &ast::StructDef,
|
||||
scheme: ty::TypeScheme<'tcx>,
|
||||
id: ast::NodeId) {
|
||||
@ -773,7 +787,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
|
||||
fn convert_foreign(ccx: &CollectCtxt, i: &ast::ForeignItem) {
|
||||
// As above, this call populates the type table with the converted
|
||||
// type of the foreign item. We simply write it into the node type
|
||||
// table.
|
||||
@ -790,7 +804,7 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
|
||||
ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
|
||||
}
|
||||
|
||||
fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
trait_id: ast::DefId)
|
||||
-> Rc<ty::TraitDef<'tcx>> {
|
||||
if trait_id.krate != ast::LOCAL_CRATE {
|
||||
@ -806,9 +820,9 @@ fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
it: &ast::Item)
|
||||
-> Rc<ty::TraitDef<'tcx>>
|
||||
fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
it: &ast::Item)
|
||||
-> Rc<ty::TraitDef<'tcx>>
|
||||
{
|
||||
let def_id = local_def(it.id);
|
||||
let tcx = ccx.tcx;
|
||||
@ -872,7 +886,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
return trait_def;
|
||||
|
||||
fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
generics: &ast::Generics)
|
||||
-> subst::Substs<'tcx>
|
||||
{
|
||||
@ -903,7 +917,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
|
||||
fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item)
|
||||
-> ty::TypeScheme<'tcx> {
|
||||
let def_id = local_def(it.id);
|
||||
let tcx = ccx.tcx;
|
||||
@ -985,7 +999,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn ty_of_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
it: &ast::ForeignItem,
|
||||
abi: abi::Abi) -> ty::TypeScheme<'tcx>
|
||||
{
|
||||
@ -1006,7 +1020,7 @@ pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
generics: &ast::Generics)
|
||||
-> ty::Generics<'tcx> {
|
||||
ty_generics(ccx,
|
||||
@ -1017,7 +1031,7 @@ fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
&generics.where_clause)
|
||||
}
|
||||
|
||||
fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
trait_id: ast::NodeId,
|
||||
substs: &'tcx subst::Substs<'tcx>,
|
||||
ast_generics: &ast::Generics,
|
||||
@ -1077,7 +1091,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
return generics;
|
||||
|
||||
fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
|
||||
trait_items: &[ast::TraitItem])
|
||||
-> Vec<ty::Predicate<'tcx>>
|
||||
@ -1108,14 +1122,13 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_generics_for_fn_or_method<'tcx,AC>(
|
||||
this: &AC,
|
||||
generics: &ast::Generics,
|
||||
base_generics: ty::Generics<'tcx>)
|
||||
-> ty::Generics<'tcx>
|
||||
where AC: AstConv<'tcx> {
|
||||
fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
|
||||
generics: &ast::Generics,
|
||||
base_generics: ty::Generics<'tcx>)
|
||||
-> ty::Generics<'tcx>
|
||||
{
|
||||
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
|
||||
ty_generics(this,
|
||||
ty_generics(ccx,
|
||||
subst::FnSpace,
|
||||
early_lifetimes[],
|
||||
generics.ty_params[],
|
||||
@ -1124,11 +1137,11 @@ fn ty_generics_for_fn_or_method<'tcx,AC>(
|
||||
}
|
||||
|
||||
// Add the Sized bound, unless the type parameter is marked as `?Sized`.
|
||||
fn add_unsized_bound<'tcx,AC>(this: &AC,
|
||||
fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
|
||||
bounds: &mut ty::BuiltinBounds,
|
||||
ast_bounds: &[ast::TyParamBound],
|
||||
span: Span)
|
||||
where AC: AstConv<'tcx> {
|
||||
{
|
||||
// Try to find an unbound in bounds.
|
||||
let mut unbound = None;
|
||||
for ab in ast_bounds.iter() {
|
||||
@ -1137,24 +1150,24 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
|
||||
assert!(ptr.bound_lifetimes.is_empty());
|
||||
unbound = Some(ptr.trait_ref.clone());
|
||||
} else {
|
||||
this.tcx().sess.span_err(span, "type parameter has more than one relaxed default \
|
||||
ccx.tcx.sess.span_err(span, "type parameter has more than one relaxed default \
|
||||
bound, only one is supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
|
||||
let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
|
||||
match unbound {
|
||||
Some(ref tpb) => {
|
||||
// FIXME(#8559) currently requires the unbound to be built-in.
|
||||
let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
|
||||
let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
|
||||
match kind_id {
|
||||
Ok(kind_id) if trait_def_id != kind_id => {
|
||||
this.tcx().sess.span_warn(span,
|
||||
ccx.tcx.sess.span_warn(span,
|
||||
"default bound relaxed for a type parameter, but \
|
||||
this does nothing because the given bound is not \
|
||||
a default. Only `?Sized` is supported");
|
||||
ty::try_add_builtin_trait(this.tcx(),
|
||||
ty::try_add_builtin_trait(ccx.tcx,
|
||||
kind_id,
|
||||
bounds);
|
||||
}
|
||||
@ -1162,27 +1175,26 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
|
||||
}
|
||||
}
|
||||
_ if kind_id.is_ok() => {
|
||||
ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
|
||||
ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
|
||||
}
|
||||
// No lang item for Sized, so we can't add it as a bound.
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_generics<'tcx,AC>(this: &AC,
|
||||
fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
|
||||
space: subst::ParamSpace,
|
||||
lifetime_defs: &[ast::LifetimeDef],
|
||||
types: &[ast::TyParam],
|
||||
base_generics: ty::Generics<'tcx>,
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::Generics<'tcx>
|
||||
where AC: AstConv<'tcx>
|
||||
{
|
||||
let mut result = base_generics;
|
||||
|
||||
for (i, l) in lifetime_defs.iter().enumerate() {
|
||||
let bounds = l.bounds.iter()
|
||||
.map(|l| ast_region_to_region(this.tcx(), l))
|
||||
.map(|l| ast_region_to_region(ccx.tcx, l))
|
||||
.collect();
|
||||
let def = ty::RegionParameterDef { name: l.lifetime.name,
|
||||
space: space,
|
||||
@ -1197,25 +1209,25 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
|
||||
// Now create the real type parameters.
|
||||
for (i, param) in types.iter().enumerate() {
|
||||
let def = get_or_create_type_parameter_def(this,
|
||||
let def = get_or_create_type_parameter_def(ccx,
|
||||
space,
|
||||
param,
|
||||
i as u32);
|
||||
debug!("ty_generics: def for type param: {}, {}",
|
||||
def.repr(this.tcx()),
|
||||
def.repr(ccx.tcx),
|
||||
space);
|
||||
result.types.push(space, def);
|
||||
}
|
||||
|
||||
// Just for fun, also push the bounds from the type parameters
|
||||
// into the predicates list. This is currently kind of non-DRY.
|
||||
create_predicates(this.tcx(), &mut result, space);
|
||||
create_predicates(ccx.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);
|
||||
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
|
||||
|
||||
for bound in bound_pred.bounds.iter() {
|
||||
match bound {
|
||||
@ -1223,7 +1235,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
let mut projections = Vec::new();
|
||||
|
||||
let trait_ref = astconv::instantiate_poly_trait_ref(
|
||||
this,
|
||||
ccx,
|
||||
&ExplicitRscope,
|
||||
poly_trait_ref,
|
||||
Some(ty),
|
||||
@ -1238,7 +1250,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
}
|
||||
|
||||
&ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
|
||||
let region = ast_region_to_region(this.tcx(), lifetime);
|
||||
let region = ast_region_to_region(ccx.tcx, lifetime);
|
||||
let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
|
||||
result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
|
||||
}
|
||||
@ -1247,9 +1259,9 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
}
|
||||
|
||||
&ast::WherePredicate::RegionPredicate(ref region_pred) => {
|
||||
let r1 = ast_region_to_region(this.tcx(), ®ion_pred.lifetime);
|
||||
let r1 = ast_region_to_region(ccx.tcx, ®ion_pred.lifetime);
|
||||
for bound in region_pred.bounds.iter() {
|
||||
let r2 = ast_region_to_region(this.tcx(), bound);
|
||||
let r2 = ast_region_to_region(ccx.tcx, bound);
|
||||
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
|
||||
result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
|
||||
}
|
||||
@ -1257,7 +1269,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
|
||||
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
|
||||
// FIXME(#20041)
|
||||
this.tcx().sess.span_bug(eq_pred.span,
|
||||
ccx.tcx.sess.span_bug(eq_pred.span,
|
||||
"Equality constraints are not yet \
|
||||
implemented (#20041)")
|
||||
}
|
||||
@ -1292,34 +1304,33 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
|
||||
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
|
||||
space: subst::ParamSpace,
|
||||
param: &ast::TyParam,
|
||||
index: u32)
|
||||
-> ty::TypeParameterDef<'tcx>
|
||||
where AC: AstConv<'tcx>
|
||||
{
|
||||
match this.tcx().ty_param_defs.borrow().get(¶m.id) {
|
||||
match ccx.tcx.ty_param_defs.borrow().get(¶m.id) {
|
||||
Some(d) => { return (*d).clone(); }
|
||||
None => { }
|
||||
}
|
||||
|
||||
let param_ty = ty::ParamTy::new(space, index, param.ident.name);
|
||||
let bounds = compute_bounds(this,
|
||||
param_ty.to_ty(this.tcx()),
|
||||
let bounds = compute_bounds(ccx,
|
||||
param_ty.to_ty(ccx.tcx),
|
||||
param.bounds[],
|
||||
SizedByDefault::Yes,
|
||||
param.span);
|
||||
let default = match param.default {
|
||||
None => None,
|
||||
Some(ref path) => {
|
||||
let ty = ast_ty_to_ty(this, &ExplicitRscope, &**path);
|
||||
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
|
||||
let cur_idx = index;
|
||||
|
||||
ty::walk_ty(ty, |t| {
|
||||
match t.sty {
|
||||
ty::ty_param(p) => if p.idx > cur_idx {
|
||||
span_err!(this.tcx().sess, path.span, E0128,
|
||||
span_err!(ccx.tcx.sess, path.span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers");
|
||||
},
|
||||
@ -1340,7 +1351,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
|
||||
default: default
|
||||
};
|
||||
|
||||
this.tcx().ty_param_defs.borrow_mut().insert(param.id, def.clone());
|
||||
ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
|
||||
|
||||
def
|
||||
}
|
||||
@ -1350,26 +1361,25 @@ enum SizedByDefault { Yes, No }
|
||||
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
|
||||
/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
|
||||
/// built-in trait (formerly known as kind): Send.
|
||||
fn compute_bounds<'tcx,AC>(this: &AC,
|
||||
fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
|
||||
param_ty: ty::Ty<'tcx>,
|
||||
ast_bounds: &[ast::TyParamBound],
|
||||
sized_by_default: SizedByDefault,
|
||||
span: Span)
|
||||
-> ty::ParamBounds<'tcx>
|
||||
where AC: AstConv<'tcx>
|
||||
{
|
||||
let mut param_bounds = conv_param_bounds(this,
|
||||
let mut param_bounds = conv_param_bounds(ccx,
|
||||
span,
|
||||
param_ty,
|
||||
ast_bounds);
|
||||
|
||||
if let SizedByDefault::Yes = sized_by_default {
|
||||
add_unsized_bound(this,
|
||||
add_unsized_bound(ccx,
|
||||
&mut param_bounds.builtin_bounds,
|
||||
ast_bounds,
|
||||
span);
|
||||
|
||||
check_bounds_compatible(this.tcx(),
|
||||
check_bounds_compatible(ccx.tcx,
|
||||
param_ty,
|
||||
¶m_bounds,
|
||||
span);
|
||||
@ -1404,24 +1414,23 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
|
||||
span: Span,
|
||||
param_ty: ty::Ty<'tcx>,
|
||||
ast_bounds: &[ast::TyParamBound])
|
||||
-> ty::ParamBounds<'tcx>
|
||||
where AC: AstConv<'tcx>
|
||||
{
|
||||
let astconv::PartitionedBounds { builtin_bounds,
|
||||
trait_bounds,
|
||||
region_bounds } =
|
||||
astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice());
|
||||
astconv::partition_bounds(ccx.tcx, span, ast_bounds.as_slice());
|
||||
|
||||
let mut projection_bounds = Vec::new();
|
||||
|
||||
let trait_bounds: Vec<ty::PolyTraitRef> =
|
||||
trait_bounds.into_iter()
|
||||
.map(|bound| {
|
||||
astconv::instantiate_poly_trait_ref(this,
|
||||
astconv::instantiate_poly_trait_ref(ccx,
|
||||
&ExplicitRscope,
|
||||
bound,
|
||||
Some(param_ty),
|
||||
@ -1430,7 +1439,7 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
.collect();
|
||||
let region_bounds: Vec<ty::Region> =
|
||||
region_bounds.into_iter()
|
||||
.map(|r| ast_region_to_region(this.tcx(), r))
|
||||
.map(|r| ast_region_to_region(ccx.tcx, r))
|
||||
.collect();
|
||||
ty::ParamBounds {
|
||||
region_bounds: region_bounds,
|
||||
@ -1440,7 +1449,7 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
decl: &ast::FnDecl,
|
||||
def_id: ast::DefId,
|
||||
ast_generics: &ast::Generics,
|
||||
@ -1492,9 +1501,9 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
return scheme;
|
||||
}
|
||||
|
||||
pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
ty_generics: &ty::Generics<'tcx>)
|
||||
-> subst::Substs<'tcx>
|
||||
fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
|
||||
ty_generics: &ty::Generics<'tcx>)
|
||||
-> subst::Substs<'tcx>
|
||||
{
|
||||
let types =
|
||||
ty_generics.types.map(
|
||||
@ -1514,14 +1523,14 @@ pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
/// comes back to check after the fact that explicit type the user
|
||||
/// wrote actually matches what the pre-defined option said.
|
||||
fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
crate_context: &CrateCtxt<'a, 'tcx>,
|
||||
ccx: &CollectCtxt<'a, 'tcx>,
|
||||
rs: &RS,
|
||||
required_type: Ty<'tcx>,
|
||||
explicit_self: &ast::ExplicitSelf,
|
||||
body_id: ast::NodeId)
|
||||
{
|
||||
if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
|
||||
let typ = crate_context.to_ty(rs, &**ast_type);
|
||||
let typ = ccx.to_ty(rs, &**ast_type);
|
||||
let base_type = match typ.sty {
|
||||
ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
|
||||
ty::ty_uniq(typ) => typ,
|
||||
@ -1537,27 +1546,27 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
assert!(!base_type.has_regions_escaping_depth(1));
|
||||
let required_type_free =
|
||||
liberate_early_bound_regions(
|
||||
crate_context.tcx, body_scope,
|
||||
ccx.tcx, body_scope,
|
||||
&ty::liberate_late_bound_regions(
|
||||
crate_context.tcx, body_scope, &ty::Binder(required_type)));
|
||||
ccx.tcx, body_scope, &ty::Binder(required_type)));
|
||||
|
||||
// The "base type" comes from the impl. It too may have late-bound
|
||||
// regions from the method.
|
||||
assert!(!base_type.has_regions_escaping_depth(1));
|
||||
let base_type_free =
|
||||
liberate_early_bound_regions(
|
||||
crate_context.tcx, body_scope,
|
||||
ccx.tcx, body_scope,
|
||||
&ty::liberate_late_bound_regions(
|
||||
crate_context.tcx, body_scope, &ty::Binder(base_type)));
|
||||
ccx.tcx, body_scope, &ty::Binder(base_type)));
|
||||
|
||||
debug!("required_type={} required_type_free={} \
|
||||
base_type={} base_type_free={}",
|
||||
required_type.repr(crate_context.tcx),
|
||||
required_type_free.repr(crate_context.tcx),
|
||||
base_type.repr(crate_context.tcx),
|
||||
base_type_free.repr(crate_context.tcx));
|
||||
let infcx = infer::new_infer_ctxt(crate_context.tcx);
|
||||
drop(::require_same_types(crate_context.tcx,
|
||||
required_type.repr(ccx.tcx),
|
||||
required_type_free.repr(ccx.tcx),
|
||||
base_type.repr(ccx.tcx),
|
||||
base_type_free.repr(ccx.tcx));
|
||||
let infcx = infer::new_infer_ctxt(ccx.tcx);
|
||||
drop(::require_same_types(ccx.tcx,
|
||||
Some(&infcx),
|
||||
false,
|
||||
explicit_self.span,
|
||||
@ -1565,7 +1574,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
required_type_free,
|
||||
|| {
|
||||
format!("mismatched self type: expected `{}`",
|
||||
ppaux::ty_to_string(crate_context.tcx, required_type))
|
||||
ppaux::ty_to_string(ccx.tcx, required_type))
|
||||
}));
|
||||
infcx.resolve_regions_and_report_errors(body_id);
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ struct TypeAndSubsts<'tcx> {
|
||||
struct CrateCtxt<'a, 'tcx: 'a> {
|
||||
// A mapping from method call sites to traits that have that method.
|
||||
trait_map: ty::TraitMap,
|
||||
tcx: &'a ty::ctxt<'tcx>
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
}
|
||||
|
||||
// Functions that write types into the node type table
|
||||
@ -320,7 +320,7 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
|
||||
};
|
||||
|
||||
time(time_passes, "type collecting", (), |_|
|
||||
collect::collect_item_types(&ccx));
|
||||
collect::collect_item_types(tcx));
|
||||
|
||||
// this ensures that later parts of type checking can assume that items
|
||||
// have valid types and not error
|
||||
|
@ -0,0 +1,47 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test equality constraints in a where clause where the type being
|
||||
// equated appears in a supertrait.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait Vehicle {
|
||||
type Color;
|
||||
|
||||
fn go(&self) { }
|
||||
}
|
||||
|
||||
pub trait Box {
|
||||
type Color;
|
||||
|
||||
fn mail(&self) { }
|
||||
}
|
||||
|
||||
pub trait BoxCar : Box + Vehicle {
|
||||
}
|
||||
|
||||
fn dent<C:BoxCar>(c: C, color: C::Color) {
|
||||
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
|
||||
//~| NOTE could derive from `Vehicle`
|
||||
//~| NOTE could derive from `Box`
|
||||
}
|
||||
|
||||
fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
|
||||
//~^ ERROR ambiguous associated type
|
||||
}
|
||||
|
||||
fn paint<C:BoxCar>(c: C, d: C::Color) {
|
||||
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
|
||||
//~| NOTE could derive from `Vehicle`
|
||||
//~| NOTE could derive from `Box`
|
||||
}
|
||||
|
||||
pub fn main() { }
|
@ -0,0 +1,56 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test equality constraints in a where clause where the type being
|
||||
// equated appears in a supertrait.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait Vehicle {
|
||||
type Color;
|
||||
|
||||
fn go(&self) { }
|
||||
}
|
||||
|
||||
pub trait Car : Vehicle {
|
||||
fn honk(&self) { }
|
||||
fn chip_paint(&self, c: Self::Color) { }
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Black;
|
||||
struct ModelT;
|
||||
impl Vehicle for ModelT { type Color = Black; }
|
||||
impl Car for ModelT { }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Blue;
|
||||
struct ModelU;
|
||||
impl Vehicle for ModelU { type Color = Blue; }
|
||||
impl Car for ModelU { }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
|
||||
fn a() { dent(ModelT, Black); }
|
||||
fn b() { dent(ModelT, Blue); } //~ ERROR type mismatch
|
||||
fn c() { dent(ModelU, Black); } //~ ERROR type mismatch
|
||||
fn d() { dent(ModelU, Blue); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn e() { ModelT.chip_paint(Black); }
|
||||
fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types
|
||||
fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types
|
||||
fn h() { ModelU.chip_paint(Blue); }
|
||||
|
||||
pub fn main() { }
|
@ -0,0 +1,53 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test equality constraints in a where clause where the type being
|
||||
// equated appears in a supertrait.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait Vehicle {
|
||||
type Color;
|
||||
|
||||
fn go(&self) { }
|
||||
}
|
||||
|
||||
pub trait Car : Vehicle {
|
||||
fn honk(&self) { }
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Black;
|
||||
struct ModelT;
|
||||
impl Vehicle for ModelT { type Color = Black; }
|
||||
impl Car for ModelT { }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Blue;
|
||||
struct ModelU;
|
||||
impl Vehicle for ModelU { type Color = Blue; }
|
||||
impl Car for ModelU { }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn black_car<C:Car<Color=Black>>(c: C) {
|
||||
}
|
||||
|
||||
fn blue_car<C:Car<Color=Blue>>(c: C) {
|
||||
}
|
||||
|
||||
fn a() { black_car(ModelT); }
|
||||
fn b() { blue_car(ModelT); } //~ ERROR type mismatch
|
||||
fn c() { black_car(ModelU); } //~ ERROR type mismatch
|
||||
fn d() { blue_car(ModelU); }
|
||||
|
||||
pub fn main() { }
|
@ -0,0 +1,27 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn pairwise_sub(mut t: Box<DoubleEndedIterator<Item=int>>) -> int {
|
||||
let mut result = 0;
|
||||
loop {
|
||||
let front = t.next();
|
||||
let back = t.next_back();
|
||||
match (front, back) {
|
||||
(Some(f), Some(b)) => { result += b - f; }
|
||||
_ => { return result; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = vec!(1, 2, 3, 4, 5, 6);
|
||||
let r = pairwise_sub(box v.into_iter());
|
||||
assert_eq!(r, 9);
|
||||
}
|
27
src/test/run-pass/associated-types-iterator-binding.rs
Normal file
27
src/test/run-pass/associated-types-iterator-binding.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn pairwise_sub<T:DoubleEndedIterator<Item=int>>(mut t: T) -> int {
|
||||
let mut result = 0;
|
||||
loop {
|
||||
let front = t.next();
|
||||
let back = t.next_back();
|
||||
match (front, back) {
|
||||
(Some(f), Some(b)) => { result += b - f; }
|
||||
_ => { return result; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = vec!(1, 2, 3, 4, 5, 6);
|
||||
let r =pairwise_sub(v.into_iter());
|
||||
assert_eq!(r, 9);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user