Auto merge of #24422 - pnkfelix:typeck-highlevel-before-bodies, r=nikomatsakis
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. However, it also means that some early error feedback is now not provided. This may be for the best, because the error feedback were were providing in some of those cases were false positives -- it was spurious feedback and a distraction from the real problem. So it is not 100% clear whether we actually want to put this change in or not. I think its a net win, but others might disagree. (Kudos to @arielb1 for suggesting this modification.)
This commit is contained in:
commit
7fbedc58e3
@ -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) {
|
||||
|
@ -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 <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.
|
||||
|
||||
// Check that we get an error when you use `<Self as Get>::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<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
||||
//~^ ERROR the trait `Get` is not implemented for the type `Self`
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -10,6 +10,14 @@
|
||||
|
||||
// Check that we get an error when you use `<Self as Get>::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<U:Get>(&self, foo: U, bar: <Self as Get>::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<T:Get> Other for T {
|
||||
fn uhoh<U:Get>(&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() { }
|
||||
|
28
src/test/compile-fail/enum-to-float-cast-2.rs
Normal file
28
src/test/compile-fail/enum-to-float-cast-2.rs
Normal file
@ -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 <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.
|
||||
|
||||
// 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`
|
||||
}
|
||||
|
@ -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() {
|
||||
|
43
src/test/compile-fail/issue-23729.rs
Normal file
43
src/test/compile-fail/issue-23729.rs
Normal file
@ -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 <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.
|
||||
|
||||
// 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<u64> {
|
||||
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)
|
||||
}
|
||||
}
|
43
src/test/compile-fail/issue-23827.rs
Normal file
43
src/test/compile-fail/issue-23827.rs
Normal file
@ -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 <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.
|
||||
|
||||
// Regression test for #23827
|
||||
|
||||
#![feature(core, unboxed_closures)]
|
||||
|
||||
pub struct Prototype {
|
||||
pub target: u32
|
||||
}
|
||||
|
||||
trait Component {
|
||||
fn apply(self, e: u32);
|
||||
}
|
||||
|
||||
impl<C: Component> Fn<(C,)> for Prototype {
|
||||
extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype {
|
||||
comp.apply(self.target);
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Component> FnMut<(C,)> for Prototype {
|
||||
extern "rust-call" fn call_mut(&mut self, (comp,): (C,)) -> Prototype {
|
||||
Fn::call(*&self, (comp,))
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Component> 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() {}
|
40
src/test/compile-fail/issue-24356.rs
Normal file
40
src/test/compile-fail/issue-24356.rs
Normal file
@ -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 <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.
|
||||
|
||||
// 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
|
||||
};
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
31
src/test/compile-fail/struct-base-wrong-type-2.rs
Normal file
31
src/test/compile-fail/struct-base-wrong-type-2.rs
Normal file
@ -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 <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.
|
||||
|
||||
// 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
|
||||
}
|
@ -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 };
|
||||
}
|
||||
|
43
src/test/compile-fail/variadic-ffi-3.rs
Normal file
43
src/test/compile-fail/variadic-ffi-3.rs
Normal file
@ -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 <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.
|
||||
|
||||
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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 <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.
|
||||
|
||||
// Check that we do not get an error when you use `<Self as Get>::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<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
|
||||
}
|
||||
|
||||
impl Get for () {
|
||||
type Value = f32;
|
||||
}
|
||||
|
||||
impl Get for f64 {
|
||||
type Value = u32;
|
||||
}
|
||||
|
||||
impl Other for () {
|
||||
fn okay<U:Get>(&self, _foo: U, _bar: <Self as Get>::Value) { }
|
||||
}
|
||||
|
||||
impl Other for f64 {
|
||||
fn okay<U:Get>(&self, _foo: U, _bar: <Self as Get>::Value) { }
|
||||
}
|
||||
|
||||
fn main() { }
|
Loading…
Reference in New Issue
Block a user