From 32d5f742cb0bb8dd6c1f37a88b8ec6ad0595ae1b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 14 Apr 2015 08:42:48 +0200 Subject: [PATCH 1/3] typeck: Do high-level structural/signature checks before function body checks. This avoids various ICEs, e.g. premature calls to cat_expr that yield the dreaded "cat_expr Errd" ICE. --- src/librustc_typeck/check/mod.rs | 115 +++++++++++++++++++------------ 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 862c454a388..905ec691c77 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -441,10 +441,11 @@ fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>) } struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } +struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_item(&mut self, i: &'tcx ast::Item) { - check_item(self.ccx, i); + check_item_type(self.ccx, i); visit::walk_item(self, i); } @@ -460,6 +461,13 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { } } +impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { + fn visit_item(&mut self, i: &'tcx ast::Item) { + check_item_body(self.ccx, i); + visit::walk_item(self, i); + } +} + pub fn check_item_types(ccx: &CrateCtxt) { let krate = ccx.tcx.map.krate(); let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx); @@ -474,6 +482,11 @@ pub fn check_item_types(ccx: &CrateCtxt) { ccx.tcx.sess.abort_if_errors(); + let mut visit = CheckItemBodiesVisitor { ccx: ccx }; + visit::walk_crate(&mut visit, krate); + + ccx.tcx.sess.abort_if_errors(); + for drop_method_did in ccx.tcx.destructors.borrow().iter() { if drop_method_did.krate == ast::LOCAL_CRATE { let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node); @@ -713,13 +726,13 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { } } -pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { - debug!("check_item(it.id={}, it.ident={})", +pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { + debug!("check_item_type(it.id={}, it.ident={})", it.id, ty::item_path_str(ccx.tcx, local_def(it.id))); let _indenter = indenter(); - match it.node { + // Consts can play a role in type-checking, so they are included here. ast::ItemStatic(_, _, ref e) | ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id), ast::ItemEnum(ref enum_definition, _) => { @@ -728,16 +741,9 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { &enum_definition.variants, it.id); } - ast::ItemFn(ref decl, _, _, _, ref body) => { - let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); - let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id); - check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env); - } + ast::ItemFn(_, _, _, _, _) => {} // entirely within check_item_body ast::ItemImpl(_, _, _, _, _, ref impl_items) => { - debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); - - let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); - + debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) { Some(impl_trait_ref) => { check_impl_items_against_trait(ccx, @@ -747,39 +753,9 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { } None => { } } - - for impl_item in impl_items { - match impl_item.node { - ast::MethodImplItem(ref sig, ref body) => { - check_method_body(ccx, &impl_pty.generics, sig, body, - impl_item.id, impl_item.span); - } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => { - // Nothing to do here. - } - } - } - } - ast::ItemTrait(_, ref generics, _, ref trait_items) => { + ast::ItemTrait(_, ref generics, _, _) => { check_trait_on_unimplemented(ccx, generics, it); - let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); - for trait_item in trait_items { - match trait_item.node { - ast::MethodTraitItem(_, None) => { - // Nothing to do, since required methods don't have - // bodies to check. - } - ast::MethodTraitItem(ref sig, Some(ref body)) => { - check_method_body(ccx, &trait_def.generics, sig, body, - trait_item.id, trait_item.span); - } - ast::TypeTraitItem(..) => { - // Nothing to do. - } - } - } } ast::ItemStruct(..) => { check_struct(ccx, it.id, it.span); @@ -814,6 +790,57 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { } } +pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { + debug!("check_item_body(it.id={}, it.ident={})", + it.id, + ty::item_path_str(ccx.tcx, local_def(it.id))); + let _indenter = indenter(); + match it.node { + ast::ItemFn(ref decl, _, _, _, ref body) => { + let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); + let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id); + check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env); + } + ast::ItemImpl(_, _, _, _, _, ref impl_items) => { + debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); + + let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); + + for impl_item in impl_items { + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { + check_method_body(ccx, &impl_pty.generics, sig, body, + impl_item.id, impl_item.span); + } + ast::TypeImplItem(_) | + ast::MacImplItem(_) => { + // Nothing to do here. + } + } + } + } + ast::ItemTrait(_, _, _, ref trait_items) => { + let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); + for trait_item in trait_items { + match trait_item.node { + ast::MethodTraitItem(_, None) => { + // Nothing to do, since required methods don't have + // bodies to check. + } + ast::MethodTraitItem(ref sig, Some(ref body)) => { + check_method_body(ccx, &trait_def.generics, sig, body, + trait_item.id, trait_item.span); + } + ast::TypeTraitItem(..) => { + // Nothing to do. + } + } + } + } + _ => {/* nothing to do */ } + } +} + fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &ast::Generics, item: &ast::Item) { From 58dc3bb57534800ae2842cd249e2aa390e00bdd0 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 14 Apr 2015 12:49:26 +0200 Subject: [PATCH 2/3] Regression tests for issues that led me to revise typeck. Close #23729 Close #23827 Close #24356 --- src/test/compile-fail/issue-23729.rs | 43 ++++++++++++++++++++++++++++ src/test/compile-fail/issue-23827.rs | 43 ++++++++++++++++++++++++++++ src/test/compile-fail/issue-24356.rs | 40 ++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 src/test/compile-fail/issue-23729.rs create mode 100644 src/test/compile-fail/issue-23827.rs create mode 100644 src/test/compile-fail/issue-24356.rs diff --git a/src/test/compile-fail/issue-23729.rs b/src/test/compile-fail/issue-23729.rs new file mode 100644 index 00000000000..3d77d171ace --- /dev/null +++ b/src/test/compile-fail/issue-23729.rs @@ -0,0 +1,43 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #23729 + +fn main() { + let fib = { + struct Recurrence { + mem: [u64; 2], + pos: usize, + } + + impl Iterator for Recurrence { + //~^ ERROR not all trait items implemented, missing: `Item` [E0046] + #[inline] + fn next(&mut self) -> Option { + if self.pos < 2 { + let next_val = self.mem[self.pos]; + self.pos += 1; + Some(next_val) + } else { + let next_val = (self.mem[0] + self.mem[1]); + self.mem[0] = self.mem[1]; + self.mem[1] = next_val; + Some(next_val) + } + } + } + + Recurrence { mem: [0, 1], pos: 0 } + }; + + for e in fib.take(10) { + println!("{}", e) + } +} diff --git a/src/test/compile-fail/issue-23827.rs b/src/test/compile-fail/issue-23827.rs new file mode 100644 index 00000000000..6c42c88bee6 --- /dev/null +++ b/src/test/compile-fail/issue-23827.rs @@ -0,0 +1,43 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #23827 + +#![feature(core, unboxed_closures)] + +pub struct Prototype { + pub target: u32 +} + +trait Component { + fn apply(self, e: u32); +} + +impl Fn<(C,)> for Prototype { + extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype { + comp.apply(self.target); + *self + } +} + +impl FnMut<(C,)> for Prototype { + extern "rust-call" fn call_mut(&mut self, (comp,): (C,)) -> Prototype { + Fn::call(*&self, (comp,)) + } +} + +impl FnOnce<(C,)> for Prototype { + //~^ ERROR not all trait items implemented, missing: `Output` [E0046] + extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype { + Fn::call(&self, (comp,)) + } +} + +fn main() {} diff --git a/src/test/compile-fail/issue-24356.rs b/src/test/compile-fail/issue-24356.rs new file mode 100644 index 00000000000..22f71835336 --- /dev/null +++ b/src/test/compile-fail/issue-24356.rs @@ -0,0 +1,40 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #24356 + +// ignore-tidy-linelength + +fn main() { + { + use std::ops::Deref; + + struct Thing(i8); + + /* + // Correct impl + impl Deref for Thing { + type Target = i8; + fn deref(&self) -> &i8 { &self.0 } + } + */ + + // Causes ICE + impl Deref for Thing { + //~^ ERROR not all trait items implemented, missing: `Target` [E0046] + fn deref(&self) -> i8 { self.0 } + //~^ ERROR method `deref` has an incompatible type for trait: expected &-ptr, found i8 [E0053] + } + + let thing = Thing(72); + + *thing + }; +} From d82f9123b25ac9cf1b4b634f5b60358517d8998d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 14 Apr 2015 14:23:02 +0200 Subject: [PATCH 3/3] Fallout from this change. --- ...sociated-types-no-suitable-supertrait-2.rs | 31 +++++++++++++ ...associated-types-no-suitable-supertrait.rs | 14 +++++- src/test/compile-fail/enum-to-float-cast-2.rs | 28 ++++++++++++ src/test/compile-fail/enum-to-float-cast.rs | 4 -- src/test/compile-fail/issue-16048.rs | 2 +- src/test/compile-fail/issue-19244-1.rs | 4 +- src/test/compile-fail/issue-19244-2.rs | 4 +- src/test/compile-fail/issue-2063.rs | 5 ++- .../non-constant-expr-for-fixed-len-vec.rs | 2 +- .../compile-fail/struct-base-wrong-type-2.rs | 31 +++++++++++++ .../compile-fail/struct-base-wrong-type.rs | 21 ++++----- src/test/compile-fail/variadic-ffi-3.rs | 43 +++++++++++++++++++ src/test/compile-fail/variadic-ffi.rs | 29 +++++-------- .../wrong-mul-method-signature.rs | 13 ++---- ...ted-types-projection-to-unrelated-trait.rs | 43 +++++++++++++++++++ 15 files changed, 220 insertions(+), 54 deletions(-) create mode 100644 src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs create mode 100644 src/test/compile-fail/enum-to-float-cast-2.rs create mode 100644 src/test/compile-fail/struct-base-wrong-type-2.rs create mode 100644 src/test/compile-fail/variadic-ffi-3.rs create mode 100644 src/test/run-pass/associated-types-projection-to-unrelated-trait.rs diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs new file mode 100644 index 00000000000..5f1cd2444d3 --- /dev/null +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we get an error when you use `::Value` in +// the trait definition but `Self` does not, in fact, implement `Get`. +// +// See also associated-types-no-suitable-supertrait.rs, which checks +// that we see the same error when making this mistake on an impl +// rather than the default method impl. +// +// See also run-pass/associated-types-projection-to-unrelated-trait.rs, +// which checks that the trait interface itself is not considered an +// error as long as all impls satisfy the constraint. + +trait Get : ::std::marker::MarkerTrait { + type Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) {} + //~^ ERROR the trait `Get` is not implemented for the type `Self` +} + +fn main() { } diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs index 2b84c38f80b..24429a48205 100644 --- a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs @@ -10,6 +10,14 @@ // Check that we get an error when you use `::Value` in // the trait definition but `Self` does not, in fact, implement `Get`. +// +// See also associated-types-no-suitable-supertrait-2.rs, which checks +// that we see the same error if we get around to checking the default +// method body. +// +// See also run-pass/associated-types-projection-to-unrelated-trait.rs, +// which checks that the trait interface itself is not considered an +// error as long as all impls satisfy the constraint. trait Get : ::std::marker::MarkerTrait { type Value; @@ -17,13 +25,15 @@ trait Get : ::std::marker::MarkerTrait { trait Other { fn uhoh(&self, foo: U, bar: ::Value) {} - //~^ ERROR the trait `Get` is not implemented for the type `Self` + // (note that we no longer catch the error here, since the + // error below aborts compilation. + // See also associated-types-no-suitable-supertrait-2.rs + // which checks that this error would be caught eventually.) } impl Other for T { fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} //~^ ERROR the trait `Get` is not implemented for the type `(T, U)` - //~| ERROR the trait `Get` is not implemented for the type `(T, U)` } fn main() { } diff --git a/src/test/compile-fail/enum-to-float-cast-2.rs b/src/test/compile-fail/enum-to-float-cast-2.rs new file mode 100644 index 00000000000..7ee67131755 --- /dev/null +++ b/src/test/compile-fail/enum-to-float-cast-2.rs @@ -0,0 +1,28 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that enum-to-float casts are disallowed. + +enum E { + L0 = -1, + H0 = 1 +} + +enum F { + L1 = 1, + H1 = 0xFFFFFFFFFFFFFFFF +} + +pub fn main() { + let a = E::L0 as f32; //~ ERROR illegal cast + let c = F::H1 as f32; //~ ERROR illegal cast + assert_eq!(a, -1.0f32); + assert_eq!(c, -1.0f32); +} diff --git a/src/test/compile-fail/enum-to-float-cast.rs b/src/test/compile-fail/enum-to-float-cast.rs index 3ad27906552..225b8702302 100644 --- a/src/test/compile-fail/enum-to-float-cast.rs +++ b/src/test/compile-fail/enum-to-float-cast.rs @@ -24,12 +24,8 @@ static C0: f32 = E::L0 as f32; //~ ERROR illegal cast static C1: f32 = F::H1 as f32; //~ ERROR illegal cast pub fn main() { - let a = E::L0 as f32; //~ ERROR illegal cast let b = C0; - let c = F::H1 as f32; //~ ERROR illegal cast let d = C1; - assert_eq!(a, -1.0f32); assert_eq!(b, -1.0f32); - assert_eq!(c, -1.0f32); assert_eq!(d, -1.0f32); } diff --git a/src/test/compile-fail/issue-16048.rs b/src/test/compile-fail/issue-16048.rs index dbd3336962b..46b7b933d87 100644 --- a/src/test/compile-fail/issue-16048.rs +++ b/src/test/compile-fail/issue-16048.rs @@ -29,7 +29,7 @@ impl<'a> Test<'a> for Foo<'a> { impl<'a> NoLifetime for Foo<'a> { fn get<'p, T : Test<'a>>(&self) -> T { //~^ ERROR lifetime parameters or bounds on method `get` do not match the trait declaration - return *self as T; //~ ERROR non-scalar cast: `Foo<'a>` as `T` + return *self as T; } } diff --git a/src/test/compile-fail/issue-19244-1.rs b/src/test/compile-fail/issue-19244-1.rs index 5c11787d467..0fa1a154772 100644 --- a/src/test/compile-fail/issue-19244-1.rs +++ b/src/test/compile-fail/issue-19244-1.rs @@ -12,7 +12,5 @@ const TUP: (usize,) = (42,); fn main() { let a: [isize; TUP.1]; - //~^ ERROR array length constant evaluation error: tuple index out of bounds - //~| ERROR attempted out-of-bounds tuple index - //~| ERROR attempted out-of-bounds tuple index + //~^ ERROR attempted out-of-bounds tuple index } diff --git a/src/test/compile-fail/issue-19244-2.rs b/src/test/compile-fail/issue-19244-2.rs index d896f768659..7d7d7d7c8ce 100644 --- a/src/test/compile-fail/issue-19244-2.rs +++ b/src/test/compile-fail/issue-19244-2.rs @@ -13,7 +13,5 @@ const STRUCT: MyStruct = MyStruct { field: 42 }; fn main() { let a: [isize; STRUCT.nonexistent_field]; - //~^ ERROR array length constant evaluation error: nonexistent struct field - //~| ERROR attempted access of field `nonexistent_field` - //~| ERROR attempted access of field `nonexistent_field` + //~^ ERROR attempted access of field `nonexistent_field` } diff --git a/src/test/compile-fail/issue-2063.rs b/src/test/compile-fail/issue-2063.rs index aed395d17ea..9e63cc203f4 100644 --- a/src/test/compile-fail/issue-2063.rs +++ b/src/test/compile-fail/issue-2063.rs @@ -28,7 +28,10 @@ impl to_str_2 for t { } fn new_t(x: t) { - x.my_to_string(); //~ ERROR does not implement + x.my_to_string(); + // (there used to be an error emitted right here as well. It was + // spurious, at best; if `t` did exist as a type, it clearly would + // have an impl of the `to_str_2` trait.) } fn main() { diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs index 59e910ec6af..b5401f7d124 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs @@ -12,8 +12,8 @@ fn main() { fn bar(n: isize) { + // FIXME (#24414): This error message needs improvement. let _x: [isize; n]; //~^ ERROR no type for local variable - //~| ERROR array length constant evaluation error: non-constant path in constant expr } } diff --git a/src/test/compile-fail/struct-base-wrong-type-2.rs b/src/test/compile-fail/struct-base-wrong-type-2.rs new file mode 100644 index 00000000000..83e73b6bc3e --- /dev/null +++ b/src/test/compile-fail/struct-base-wrong-type-2.rs @@ -0,0 +1,31 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that `base` in `Fru { field: expr, ..base }` must have right type. +// +// See also struct-base-wrong-type.rs, which tests same condition +// within a const expression. + +struct Foo { a: isize, b: isize } +struct Bar { x: isize } + +fn main() { + let b = Bar { x: 5 }; + let f = Foo { a: 2, ..b }; //~ ERROR mismatched types + //~| expected `Foo` + //~| found `Bar` + //~| expected struct `Foo` + //~| found struct `Bar` + let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types + //~| expected `Foo` + //~| found `_` + //~| expected struct `Foo` + //~| found integral variable +} diff --git a/src/test/compile-fail/struct-base-wrong-type.rs b/src/test/compile-fail/struct-base-wrong-type.rs index a2ad2336d4b..c98131560d4 100644 --- a/src/test/compile-fail/struct-base-wrong-type.rs +++ b/src/test/compile-fail/struct-base-wrong-type.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Check that `base` in `Fru { field: expr, ..base }` must have right type. +// +// See also struct-base-wrong-type-2.rs, which tests same condition +// within a function body. + struct Foo { a: isize, b: isize } struct Bar { x: isize } @@ -25,14 +30,10 @@ static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types fn main() { let b = Bar { x: 5 }; - let f = Foo { a: 2, ..b }; //~ ERROR mismatched types - //~| expected `Foo` - //~| found `Bar` - //~| expected struct `Foo` - //~| found struct `Bar` - let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types - //~| expected `Foo` - //~| found `_` - //~| expected struct `Foo` - //~| found integral variable + // errors below are no longer caught since error above causes + // compilation to abort before we bother checking function bodies. + // See also struct-base-wrong-type-2.rs, which checks that we + // would catch these errors eventually. + let f = Foo { a: 2, ..b }; + let f__isize = Foo { a: 2, ..4 }; } diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs new file mode 100644 index 00000000000..94055450bc6 --- /dev/null +++ b/src/test/compile-fail/variadic-ffi-3.rs @@ -0,0 +1,43 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern { + fn foo(f: isize, x: u8, ...); +} + +extern "C" fn bar(f: isize, x: u8) {} + +fn main() { + unsafe { + foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied + foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied + + let x: unsafe extern "C" fn(f: isize, x: u8) = foo; + //~^ ERROR: mismatched types + //~| expected `unsafe extern "C" fn(isize, u8)` + //~| found `unsafe extern "C" fn(isize, u8, ...)` + //~| expected non-variadic fn + //~| found variadic function + + let y: extern "C" fn(f: isize, x: u8, ...) = bar; + //~^ ERROR: mismatched types + //~| expected `extern "C" fn(isize, u8, ...)` + //~| found `extern "C" fn(isize, u8) {bar}` + //~| expected variadic fn + //~| found non-variadic function + + foo(1, 2, 3f32); //~ ERROR: can't pass an f32 to variadic function, cast to c_double + foo(1, 2, true); //~ ERROR: can't pass bool to variadic function, cast to c_int + foo(1, 2, 1i8); //~ ERROR: can't pass i8 to variadic function, cast to c_int + foo(1, 2, 1u8); //~ ERROR: can't pass u8 to variadic function, cast to c_uint + foo(1, 2, 1i16); //~ ERROR: can't pass i16 to variadic function, cast to c_int + foo(1, 2, 1u16); //~ ERROR: can't pass u16 to variadic function, cast to c_uint + } +} diff --git a/src/test/compile-fail/variadic-ffi.rs b/src/test/compile-fail/variadic-ffi.rs index 2a62ac2ac30..12942178493 100644 --- a/src/test/compile-fail/variadic-ffi.rs +++ b/src/test/compile-fail/variadic-ffi.rs @@ -19,29 +19,20 @@ extern { extern "C" fn bar(f: isize, x: u8) {} fn main() { + // errors below are no longer checked because error above aborts + // compilation; see variadic-ffi-3.rs for corresponding test. unsafe { - foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied - foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied + foo(); + foo(1); let x: unsafe extern "C" fn(f: isize, x: u8) = foo; - //~^ ERROR: mismatched types - //~| expected `unsafe extern "C" fn(isize, u8)` - //~| found `unsafe extern "C" fn(isize, u8, ...)` - //~| expected non-variadic fn - //~| found variadic function - let y: extern "C" fn(f: isize, x: u8, ...) = bar; - //~^ ERROR: mismatched types - //~| expected `extern "C" fn(isize, u8, ...)` - //~| found `extern "C" fn(isize, u8) {bar}` - //~| expected variadic fn - //~| found non-variadic function - foo(1, 2, 3f32); //~ ERROR: can't pass an f32 to variadic function, cast to c_double - foo(1, 2, true); //~ ERROR: can't pass bool to variadic function, cast to c_int - foo(1, 2, 1i8); //~ ERROR: can't pass i8 to variadic function, cast to c_int - foo(1, 2, 1u8); //~ ERROR: can't pass u8 to variadic function, cast to c_uint - foo(1, 2, 1i16); //~ ERROR: can't pass i16 to variadic function, cast to c_int - foo(1, 2, 1u16); //~ ERROR: can't pass u16 to variadic function, cast to c_uint + foo(1, 2, 3f32); + foo(1, 2, true); + foo(1, 2, 1i8); + foo(1, 2, 1u8); + foo(1, 2, 1i16); + foo(1, 2, 1u16); } } diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index 21c249c0e1f..069fd2dec99 100644 --- a/src/test/compile-fail/wrong-mul-method-signature.rs +++ b/src/test/compile-fail/wrong-mul-method-signature.rs @@ -71,16 +71,9 @@ pub fn main() { let x: Vec1 = Vec1 { x: 1.0 } * 2.0; // this is OK let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order - //~^ ERROR mismatched types - //~| expected `Vec2` - //~| found `_` - //~| expected struct `Vec2` - //~| found floating-point variable - //~| ERROR mismatched types - //~| expected `Vec2` - //~| found `f64` - //~| expected struct `Vec2` - //~| found f64 + // (we no longer signal a compile error here, since the + // error in the trait signature will cause compilation to + // abort before we bother looking at function bodies.) let x: i32 = Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0; } diff --git a/src/test/run-pass/associated-types-projection-to-unrelated-trait.rs b/src/test/run-pass/associated-types-projection-to-unrelated-trait.rs new file mode 100644 index 00000000000..6070cff9a29 --- /dev/null +++ b/src/test/run-pass/associated-types-projection-to-unrelated-trait.rs @@ -0,0 +1,43 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we do not get an error when you use `::Value` in +// the trait definition if there is no default method and for every impl, +// `Self` does implement `Get`. +// +// See also compile-fail tests associated-types-no-suitable-supertrait +// and associated-types-no-suitable-supertrait-2, which show how small +// variants of the code below can fail. + +trait Get { + type Value; +} + +trait Other { + fn okay(&self, foo: U, bar: ::Value); +} + +impl Get for () { + type Value = f32; +} + +impl Get for f64 { + type Value = u32; +} + +impl Other for () { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +impl Other for f64 { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +fn main() { }