librustc: Allow trait bounds on structures and enumerations, and check

them during kind checking.

This implements RFC #11.

Closes #15759.
This commit is contained in:
Patrick Walton 2014-08-11 17:12:01 -07:00
parent cb9c1e0e70
commit 086a5ca7d2
26 changed files with 622 additions and 43 deletions

View File

@ -1456,13 +1456,24 @@ pub mod types {
pub Data4: [BYTE, ..8],
}
// NOTE(pcwalton, stage0): Remove after snapshot (typeck bug
// workaround).
#[cfg(stage0)]
pub struct WSAPROTOCOLCHAIN {
pub ChainLen: c_int,
pub ChainEntries: [DWORD, ..MAX_PROTOCOL_CHAIN],
}
#[cfg(not(stage0))]
pub struct WSAPROTOCOLCHAIN {
pub ChainLen: c_int,
pub ChainEntries: [DWORD, ..MAX_PROTOCOL_CHAIN as uint],
}
pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
// NOTE(pcwalton, stage0): Remove after snapshot (typeck bug
// workaround).
#[cfg(stage0)]
pub struct WSAPROTOCOL_INFO {
pub dwServiceFlags1: DWORD,
pub dwServiceFlags2: DWORD,
@ -1485,6 +1496,29 @@ pub mod types {
pub dwProviderReserved: DWORD,
pub szProtocol: [u8, ..WSAPROTOCOL_LEN+1],
}
#[cfg(not(stage0))]
pub struct WSAPROTOCOL_INFO {
pub dwServiceFlags1: DWORD,
pub dwServiceFlags2: DWORD,
pub dwServiceFlags3: DWORD,
pub dwServiceFlags4: DWORD,
pub dwProviderFlags: DWORD,
pub ProviderId: GUID,
pub dwCatalogEntryId: DWORD,
pub ProtocolChain: WSAPROTOCOLCHAIN,
pub iVersion: c_int,
pub iAddressFamily: c_int,
pub iMaxSockAddr: c_int,
pub iMinSockAddr: c_int,
pub iSocketType: c_int,
pub iProtocol: c_int,
pub iProtocolMaxOffset: c_int,
pub iNetworkByteOrder: c_int,
pub iSecurityScheme: c_int,
pub dwMessageSize: DWORD,
pub dwProviderReserved: DWORD,
pub szProtocol: [u8, ..(WSAPROTOCOL_LEN as uint) + 1u],
}
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;

View File

@ -17,6 +17,7 @@ use middle::def;
use middle::pat_util::def_to_path;
use middle::ty;
use middle::typeck::astconv;
use middle::typeck::check;
use util::nodemap::{DefIdMap};
use syntax::ast::*;
@ -274,6 +275,17 @@ impl<'a> ConstEvalVisitor<'a> {
}
impl<'a> Visitor<()> for ConstEvalVisitor<'a> {
fn visit_ty(&mut self, t: &Ty, _: ()) {
match t.node {
TyFixedLengthVec(_, expr) => {
check::check_const_in_type(self.tcx, &*expr, ty::mk_uint());
}
_ => {}
}
visit::walk_ty(self, t, ());
}
fn visit_expr_post(&mut self, e: &Expr, _: ()) {
self.classify(e);
}

View File

@ -12,20 +12,24 @@
use middle::freevars::freevar_entry;
use middle::freevars;
use middle::subst;
use middle::ty::ParameterEnvironment;
use middle::ty;
use middle::ty_fold;
use middle::ty_fold::TypeFoldable;
use middle::typeck;
use middle::ty_fold;
use middle::typeck::check::vtable;
use middle::typeck::{MethodCall, NoAdjustment};
use middle::typeck;
use util::ppaux::{Repr, ty_to_string};
use util::ppaux::UserString;
use std::collections::HashSet;
use syntax::ast::*;
use syntax::ast_util;
use syntax::attr;
use syntax::codemap::Span;
use syntax::print::pprust::{expr_to_string, ident_to_string};
use syntax::{visit};
use syntax::visit::Visitor;
use syntax::visit;
// Kind analysis pass.
//
@ -47,13 +51,13 @@ use syntax::visit::Visitor;
// primitives in the stdlib are explicitly annotated to only take sendable
// types.
#[deriving(Clone)]
pub struct Context<'a> {
tcx: &'a ty::ctxt,
struct_and_enum_bounds_checked: HashSet<ty::t>,
parameter_environments: Vec<ParameterEnvironment>,
}
impl<'a> Visitor<()> for Context<'a> {
fn visit_expr(&mut self, ex: &Expr, _: ()) {
check_expr(self, ex);
}
@ -74,12 +78,18 @@ impl<'a> Visitor<()> for Context<'a> {
fn visit_pat(&mut self, p: &Pat, _: ()) {
check_pat(self, p);
}
fn visit_local(&mut self, l: &Local, _: ()) {
check_local(self, l);
}
}
pub fn check_crate(tcx: &ty::ctxt,
krate: &Crate) {
let mut ctx = Context {
tcx: tcx,
struct_and_enum_bounds_checked: HashSet::new(),
parameter_environments: Vec::new(),
};
visit::walk_crate(&mut ctx, krate, ());
tcx.sess.abort_if_errors();
@ -165,12 +175,90 @@ fn check_item(cx: &mut Context, item: &Item) {
match item.node {
ItemImpl(_, Some(ref trait_ref), ref self_type, _) => {
check_impl_of_trait(cx, item, trait_ref, &**self_type);
let parameter_environment =
ParameterEnvironment::for_item(cx.tcx, item.id);
cx.parameter_environments.push(parameter_environment);
// Check bounds on the `self` type.
check_bounds_on_structs_or_enums_in_type_if_possible(
cx,
item.span,
ty::node_id_to_type(cx.tcx, item.id));
// Check bounds on the trait ref.
match ty::impl_trait_ref(cx.tcx,
ast_util::local_def(item.id)) {
None => {}
Some(trait_ref) => {
check_bounds_on_structs_or_enums_in_trait_ref(
cx,
item.span,
&*trait_ref);
}
}
drop(cx.parameter_environments.pop());
}
ItemEnum(..) => {
let parameter_environment =
ParameterEnvironment::for_item(cx.tcx, item.id);
cx.parameter_environments.push(parameter_environment);
let def_id = ast_util::local_def(item.id);
for variant in ty::enum_variants(cx.tcx, def_id).iter() {
for arg in variant.args.iter() {
check_bounds_on_structs_or_enums_in_type_if_possible(
cx,
item.span,
*arg)
}
}
drop(cx.parameter_environments.pop());
}
ItemStruct(..) => {
let parameter_environment =
ParameterEnvironment::for_item(cx.tcx, item.id);
cx.parameter_environments.push(parameter_environment);
let def_id = ast_util::local_def(item.id);
for field in ty::lookup_struct_fields(cx.tcx, def_id).iter() {
check_bounds_on_structs_or_enums_in_type_if_possible(
cx,
item.span,
ty::node_id_to_type(cx.tcx, field.id.node))
}
drop(cx.parameter_environments.pop());
}
ItemStatic(..) => {
let parameter_environment =
ParameterEnvironment::for_item(cx.tcx, item.id);
cx.parameter_environments.push(parameter_environment);
check_bounds_on_structs_or_enums_in_type_if_possible(
cx,
item.span,
ty::node_id_to_type(cx.tcx, item.id));
drop(cx.parameter_environments.pop());
}
_ => {}
}
}
visit::walk_item(cx, item, ());
visit::walk_item(cx, item, ())
}
fn check_local(cx: &mut Context, local: &Local) {
check_bounds_on_structs_or_enums_in_type_if_possible(
cx,
local.span,
ty::node_id_to_type(cx.tcx, local.id));
visit::walk_local(cx, local, ())
}
// Yields the appropriate function to check the kind of closed over
@ -254,7 +342,25 @@ fn check_fn(
});
});
visit::walk_fn(cx, fk, decl, body, sp, ());
match *fk {
visit::FkFnBlock(..) => {
let ty = ty::node_id_to_type(cx.tcx, fn_id);
check_bounds_on_structs_or_enums_in_type_if_possible(cx, sp, ty);
visit::walk_fn(cx, fk, decl, body, sp, ())
}
visit::FkItemFn(..) | visit::FkMethod(..) => {
let parameter_environment = ParameterEnvironment::for_item(cx.tcx,
fn_id);
cx.parameter_environments.push(parameter_environment);
let ty = ty::node_id_to_type(cx.tcx, fn_id);
check_bounds_on_structs_or_enums_in_type_if_possible(cx, sp, ty);
visit::walk_fn(cx, fk, decl, body, sp, ());
drop(cx.parameter_environments.pop());
}
}
}
pub fn check_expr(cx: &mut Context, e: &Expr) {
@ -263,6 +369,13 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
// Handle any kind bounds on type parameters
check_bounds_on_type_parameters(cx, e);
// Check bounds on structures or enumerations in the type of the
// expression.
let expression_type = ty::expr_ty(cx.tcx, e);
check_bounds_on_structs_or_enums_in_type_if_possible(cx,
e.span,
expression_type);
match e.node {
ExprBox(ref loc, ref interior) => {
let def = ty::resolve_expr(cx.tcx, &**loc);
@ -483,6 +596,7 @@ fn check_ty(cx: &mut Context, aty: &Ty) {
}
_ => {}
}
visit::walk_ty(cx, aty, ());
}
@ -519,6 +633,76 @@ pub fn check_typaram_bounds(cx: &Context,
});
}
fn check_bounds_on_structs_or_enums_in_type_if_possible(cx: &mut Context,
span: Span,
ty: ty::t) {
// If we aren't in a function, structure, or enumeration context, we don't
// have enough information to ensure that bounds on structures or
// enumerations are satisfied. So we don't perform the check.
if cx.parameter_environments.len() == 0 {
return
}
// If we've already checked for this type, don't do it again. This
// massively speeds up kind checking.
if cx.struct_and_enum_bounds_checked.contains(&ty) {
return
}
cx.struct_and_enum_bounds_checked.insert(ty);
ty::walk_ty(ty, |ty| {
match ty::get(ty).sty {
ty::ty_struct(type_id, ref substs) |
ty::ty_enum(type_id, ref substs) => {
let polytype = ty::lookup_item_type(cx.tcx, type_id);
// Check builtin bounds.
for (ty, type_param_def) in substs.types
.iter()
.zip(polytype.generics
.types
.iter()) {
check_typaram_bounds(cx, span, *ty, type_param_def)
}
// Check trait bounds.
let parameter_environment =
cx.parameter_environments.get(cx.parameter_environments
.len() - 1);
debug!(
"check_bounds_on_structs_or_enums_in_type_if_possible(): \
checking {}",
ty.repr(cx.tcx));
vtable::check_param_bounds(cx.tcx,
span,
parameter_environment,
&polytype.generics.types,
substs,
|missing| {
cx.tcx
.sess
.span_err(span,
format!("instantiating a type parameter with \
an incompatible type `{}`, which \
does not fulfill `{}`",
ty_to_string(cx.tcx, ty),
missing.user_string(
cx.tcx)).as_slice());
})
}
_ => {}
}
});
}
fn check_bounds_on_structs_or_enums_in_trait_ref(cx: &mut Context,
span: Span,
trait_ref: &ty::TraitRef) {
for ty in trait_ref.substs.types.iter() {
check_bounds_on_structs_or_enums_in_type_if_possible(cx, span, *ty)
}
}
pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t,
bounds: ty::BuiltinBounds, referenced_ty: Option<ty::t>)
{

View File

@ -55,7 +55,7 @@ use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE};
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
use syntax::ast::{Visibility};
use syntax::ast_util::{is_local, lit_is_str};
use syntax::ast_util::{PostExpansionMethod, is_local, lit_is_str};
use syntax::ast_util;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
@ -1083,6 +1083,84 @@ pub struct ParameterEnvironment {
pub bounds: VecPerParamSpace<ParamBounds>,
}
impl ParameterEnvironment {
pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
match cx.map.find(id) {
Some(ast_map::NodeImplItem(ref impl_item)) => {
match **impl_item {
ast::MethodImplItem(ref method) => {
let method_def_id = ast_util::local_def(id);
match ty::impl_or_trait_item(cx, method_def_id) {
MethodTraitItem(ref method_ty) => {
let method_generics = &method_ty.generics;
construct_parameter_environment(
cx,
method_generics,
method.pe_body().id)
}
}
}
}
}
Some(ast_map::NodeTraitItem(trait_method)) => {
match *trait_method {
ast::RequiredMethod(ref required) => {
cx.sess.span_bug(required.span,
"ParameterEnvironment::from_item():
can't create a parameter \
environment for required trait \
methods")
}
ast::ProvidedMethod(ref method) => {
let method_def_id = ast_util::local_def(id);
match ty::impl_or_trait_item(cx, method_def_id) {
MethodTraitItem(ref method_ty) => {
let method_generics = &method_ty.generics;
construct_parameter_environment(
cx,
method_generics,
method.pe_body().id)
}
}
}
}
}
Some(ast_map::NodeItem(item)) => {
match item.node {
ast::ItemFn(_, _, _, _, ref body) => {
// We assume this is a function.
let fn_def_id = ast_util::local_def(id);
let fn_pty = ty::lookup_item_type(cx, fn_def_id);
construct_parameter_environment(cx,
&fn_pty.generics,
body.id)
}
ast::ItemEnum(..) |
ast::ItemStruct(..) |
ast::ItemImpl(..) |
ast::ItemStatic(..) => {
let def_id = ast_util::local_def(id);
let pty = ty::lookup_item_type(cx, def_id);
construct_parameter_environment(cx, &pty.generics, id)
}
_ => {
cx.sess.span_bug(item.span,
"ParameterEnvironment::from_item():
can't create a parameter \
environment for this kind of item")
}
}
}
_ => {
cx.sess.bug(format!("ParameterEnvironment::from_item(): \
`{}` is not an item",
cx.map.node_to_string(id)).as_slice())
}
}
}
}
/// A polytype.
///
/// - `generics`: the set of type parameters and their bounds

View File

@ -879,7 +879,6 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
}
}
ast::TyFixedLengthVec(ty, e) => {
typeck::write_ty_to_tcx(tcx, e.id, ty::mk_uint());
match const_eval::eval_const_expr_partial(tcx, &*e) {
Ok(ref r) => {
match *r {

View File

@ -86,7 +86,7 @@ use middle::subst;
use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
use middle::ty::{FnSig, VariantInfo};
use middle::ty::{Polytype};
use middle::ty::{ParamTy, Disr, ExprTyProvider};
use middle::ty::{Disr, ExprTyProvider, ParamTy, ParameterEnvironment};
use middle::ty;
use middle::ty_fold::TypeFolder;
use middle::typeck::astconv::AstConv;
@ -281,7 +281,8 @@ impl<'a> Inherited<'a> {
}
// Used by check_const and check_enum_variants
fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
pub fn blank_fn_ctxt<'a>(
ccx: &'a CrateCtxt<'a>,
inh: &'a Inherited<'a>,
rty: ty::t,
region_bnd: ast::NodeId)
@ -673,11 +674,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
}
ast::ItemFn(ref decl, _, _, _, ref body) => {
let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
let param_env = ty::construct_parameter_environment(ccx.tcx,
&fn_pty.generics,
body.id);
let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
}
ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
@ -773,15 +770,7 @@ fn check_method_body(ccx: &CrateCtxt,
debug!("check_method_body(item_generics={}, method.id={})",
item_generics.repr(ccx.tcx),
method.id);
let method_def_id = local_def(method.id);
let method_ty = match ty::impl_or_trait_item(ccx.tcx, method_def_id) {
ty::MethodTraitItem(ref method_ty) => (*method_ty).clone(),
};
let method_generics = &method_ty.generics;
let param_env = ty::construct_parameter_environment(ccx.tcx,
method_generics,
method.pe_body().id);
let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
let fty = ty::node_id_to_type(ccx.tcx, method.id);
@ -3971,6 +3960,24 @@ fn check_block_with_expected(fcx: &FnCtxt,
*fcx.ps.borrow_mut() = prev;
}
/// Checks a constant appearing in a type. At the moment this is just the
/// length expression in a fixed-length vector, but someday it might be
/// extended to type-level numeric literals.
pub fn check_const_in_type(tcx: &ty::ctxt,
expr: &ast::Expr,
expected_type: ty::t) {
// Synthesize a crate context. The trait map is not needed here (though I
// imagine it will be if we have associated statics --pcwalton), so we
// leave it blank.
let ccx = CrateCtxt {
trait_map: NodeMap::new(),
tcx: tcx,
};
let inh = blank_inherited_fields(&ccx);
let fcx = blank_fn_ctxt(&ccx, &inh, expected_type, expr.id);
check_const_with_ty(&fcx, expr.span, expr, expected_type);
}
pub fn check_const(ccx: &CrateCtxt,
sp: Span,
e: &ast::Expr,

View File

@ -66,8 +66,8 @@ use syntax::visit::Visitor;
// It may be better to do something more clever, like processing fully
// resolved types first.
/// A vtable context includes an inference context, a crate context, and a
/// callback function to call in case of type error.
/// A vtable context includes an inference context, a parameter environment,
/// and a list of unboxed closure types.
pub struct VtableContext<'a> {
pub infcx: &'a infer::InferCtxt<'a>,
pub param_env: &'a ty::ParameterEnvironment,
@ -83,8 +83,7 @@ fn lookup_vtables(vcx: &VtableContext,
type_param_defs: &VecPerParamSpace<ty::TypeParameterDef>,
substs: &subst::Substs,
is_early: bool)
-> VecPerParamSpace<vtable_param_res>
{
-> VecPerParamSpace<vtable_param_res> {
debug!("lookup_vtables(\
type_param_defs={}, \
substs={}",
@ -154,11 +153,12 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
match lookup_vtable(vcx, span, ty, trait_ref.clone(), is_early) {
Some(vtable) => param_result.push(vtable),
None => {
vcx.tcx().sess.span_fatal(span,
vcx.tcx().sess.span_err(span,
format!("failed to find an implementation of \
trait {} for {}",
vcx.infcx.trait_ref_to_string(&*trait_ref),
vcx.infcx.ty_to_string(ty)).as_slice());
param_result.push(vtable_error)
}
}
true
@ -583,10 +583,11 @@ fn fixup_ty(vcx: &VtableContext,
match resolve_type(vcx.infcx, Some(span), ty, resolve_and_force_all_but_regions) {
Ok(new_type) => Some(new_type),
Err(e) if !is_early => {
tcx.sess.span_fatal(span,
tcx.sess.span_err(span,
format!("cannot determine a type for this bounded type \
parameter: {}",
fixup_err_to_string(e)).as_slice())
fixup_err_to_string(e)).as_slice());
Some(ty::mk_err())
}
Err(_) => {
None
@ -974,3 +975,38 @@ impl<'a, 'b> visit::Visitor<()> for &'a FnCtxt<'b> {
pub fn resolve_in_block(mut fcx: &FnCtxt, bl: &ast::Block) {
visit::walk_block(&mut fcx, bl, ());
}
/// Used in the kind checker after typechecking has finished. Calls
/// `any_missing` if any bounds were missing.
pub fn check_param_bounds(tcx: &ty::ctxt,
span: Span,
parameter_environment: &ty::ParameterEnvironment,
type_param_defs:
&VecPerParamSpace<ty::TypeParameterDef>,
substs: &subst::Substs,
any_missing: |&ty::TraitRef|) {
let unboxed_closures = RefCell::new(DefIdMap::new());
let vcx = VtableContext {
infcx: &infer::new_infer_ctxt(tcx),
param_env: parameter_environment,
unboxed_closures: &unboxed_closures,
};
let vtable_param_results =
lookup_vtables(&vcx, span, type_param_defs, substs, false);
for (vtable_param_result, type_param_def) in
vtable_param_results.iter().zip(type_param_defs.iter()) {
for (vtable_result, trait_ref) in
vtable_param_result.iter()
.zip(type_param_def.bounds
.trait_bounds
.iter()) {
match *vtable_result {
vtable_error => any_missing(&**trait_ref),
vtable_static(..) |
vtable_param(..) |
vtable_unboxed_closure(..) => {}
}
}
}
}

View File

@ -462,7 +462,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
// These don't define types.
ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
ast::ItemEnum(ref enum_definition, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
let pty = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, pty.ty);
get_enum_variant_types(ccx,
@ -559,9 +558,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
// static trait methods. This is somewhat unfortunate.
ensure_trait_methods(ccx, it.id, &*trait_def);
},
ast::ItemStruct(struct_def, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
ast::ItemStruct(struct_def, _) => {
// Write the class type.
let pty = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, pty.ty);

View File

@ -0,0 +1,22 @@
// 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.
pub trait Trait {}
pub struct Foo<T:Trait> {
pub x: T,
}
pub enum Bar<T:Trait> {
ABar(int),
BBar(T),
CBar(uint),
}

View File

@ -16,9 +16,11 @@ extern crate rand;
struct Error;
#[deriving(Zero)]
#[deriving(Zero)] //~ ERROR failed to find an implementation
struct Struct {
x: Error //~ ERROR
x: Error //~ ERROR failed to find an implementation
//~^ ERROR failed to find an implementation
//~^^ ERROR type `Error` does not implement any method in scope
}
fn main() {}

View File

@ -16,9 +16,11 @@ extern crate rand;
struct Error;
#[deriving(Zero)]
#[deriving(Zero)] //~ ERROR failed to find an implementation
struct Struct(
Error //~ ERROR
//~^ ERROR failed to find an implementation
//~^^ ERROR type `Error` does not implement any method in scope
);
fn main() {}

View File

@ -18,4 +18,5 @@ fn main() {
//~^ ERROR cannot determine a type for this bounded type parameter: unconstrained type
println!("{}", y + 1);
//~^ ERROR binary operation `+` cannot be applied to type `Gc<int>`
//~^^ ERROR cannot determine a type for this bounded type parameter: unconstrained type
}

View File

@ -19,5 +19,5 @@ fn main() {
let x: Box<Map<int, int>> = x;
let y: Box<Map<uint, int>> = box x;
//~^ ERROR failed to find an implementation of trait collections::Map<uint,int>
// for ~collections::Map<int,int>:Send
//~^^ ERROR failed to find an implementation of trait core::collections::Collection
}

View File

@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-test
//
// Ignored because of an ICE at the moment.
// Check that non-constant exprs do fail as count in fixed length vec type
fn main() {

View File

@ -15,4 +15,5 @@
trait Foo {}
fn take_foo<F:Foo>(f: F) {}
fn take_object(f: Box<Foo>) { take_foo(f); } //~ ERROR failed to find an implementation of trait
//~^ ERROR failed to find an implementation
fn main() {}

View File

@ -44,6 +44,7 @@ fn main() {
// Can't do this copy
let x = box box box A {y: r(i)};
let _z = x.clone(); //~ ERROR failed to find an implementation
//~^ ERROR failed to find an implementation
println!("{:?}", x);
}
println!("{:?}", *i);

View 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.
trait Trait {}
struct Foo<T:Trait> {
x: T,
}
fn main() {
let foo = Foo {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
x: 3i
};
let baz: Foo<uint> = fail!();
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
}

View File

@ -0,0 +1,25 @@
// 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.
trait Trait {}
struct Foo<T:Trait> {
x: T,
}
static X: Foo<uint> = Foo {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
x: 1,
};
fn main() {
}

View File

@ -0,0 +1,36 @@
// 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.
// aux-build:trait_bounds_on_structs_and_enums_xc.rs
extern crate trait_bounds_on_structs_and_enums_xc;
use trait_bounds_on_structs_and_enums_xc::{Bar, Foo, Trait};
fn explode(x: Foo<uint>) {}
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
fn kaboom(y: Bar<f32>) {}
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
fn main() {
let foo = Foo {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
x: 3i
};
let bar: Bar<f64> = return;
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
let _ = bar;
}

View File

@ -0,0 +1,77 @@
// 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.
trait Trait {}
struct Foo<T:Trait> {
x: T,
}
enum Bar<T:Trait> {
ABar(int),
BBar(T),
CBar(uint),
}
fn explode(x: Foo<uint>) {}
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
fn kaboom(y: Bar<f32>) {}
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
impl<T> Foo<T> {
fn uhoh() {}
}
struct Baz {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
a: Foo<int>,
}
enum Boo {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
Quux(Bar<uint>),
}
struct Badness<T> {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
b: Foo<T>,
}
enum MoreBadness<T> {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
EvenMoreBadness(Bar<T>),
}
trait PolyTrait<T> {
fn whatever() {}
}
struct Struct;
impl PolyTrait<Foo<uint>> for Struct {
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
fn whatever() {}
}
fn main() {
let bar: Bar<f64> = return;
//~^ ERROR failed to find an implementation
//~^^ ERROR instantiating a type parameter with an incompatible type
let _ = bar;
}

View File

@ -21,5 +21,6 @@ impl Drop for r {
fn main() {
let i = box r { b: true };
let _j = i.clone(); //~ ERROR failed to find an implementation
//~^ ERROR failed to find an implementation
println!("{:?}", i);
}

View File

@ -37,6 +37,9 @@ fn main() {
let r2 = vec!(box r { i: i2 });
f(r1.clone(), r2.clone());
//~^ ERROR failed to find an implementation of
//~^^ ERROR failed to find an implementation of
//~^^^ ERROR failed to find an implementation of
//~^^^^ ERROR failed to find an implementation of
println!("{:?}", (r2, i1.get()));
println!("{:?}", (r1, i2.get()));
}

View File

@ -25,6 +25,7 @@ impl TraitB for int {
fn call_it<B:TraitB>(b: B) -> int {
let y = 4u;
b.gimme_an_a(y) //~ ERROR failed to find an implementation of trait TraitA
//~^ ERROR failed to find an implementation of trait TraitA
}
fn main() {

View File

@ -14,7 +14,10 @@ fn equal<T>(_: &T, _: &T) -> bool where T : Eq {
struct Struct;
fn main() {
equal(&Struct, &Struct)
//~^ ERROR failed to find an implementation of trait
drop(equal(&Struct, &Struct))
//~^ ERROR failed to find an implementation of trait core::cmp::Eq
//~^^ ERROR failed to find an implementation of trait core::cmp::PartialEq
//~^^^ ERROR failed to find an implementation of trait core::cmp::Eq
//~^^^^ ERROR failed to find an implementation of trait core::cmp::PartialEq
}

View File

@ -13,7 +13,7 @@
pub fn main() {
static FOO: int = 2;
static FOO: uint = 2;
let _v: [int, ..FOO*3];
}

View File

@ -0,0 +1,26 @@
// 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.
trait U {}
trait T<X: U> {}
trait S2<Y: U> {
fn m(x: Box<T<Y>>) {}
}
struct St<X: U> {
f: Box<T<X>>,
}
impl<X: U> St<X> {
fn blah() {}
}
fn main() {}