From 30f4ffff33450a51f04ea229e68527422ebd6951 Mon Sep 17 00:00:00 2001 From: Robin Kruppe Date: Wed, 14 Oct 2015 19:27:49 +0200 Subject: [PATCH 01/10] Reject "+" and "-" when parsing floats. Fixes #29042 --- src/libcore/num/dec2flt/parse.rs | 7 ++++++- src/libcoretest/num/dec2flt/mod.rs | 12 ++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs index 58e2a6e9bba46..414bcc874eac1 100644 --- a/src/libcore/num/dec2flt/parse.rs +++ b/src/libcore/num/dec2flt/parse.rs @@ -59,7 +59,12 @@ pub fn parse_decimal(s: &str) -> ParseResult { let s = s.as_bytes(); let (integral, s) = eat_digits(s); match s.first() { - None => Valid(Decimal::new(integral, b"", 0)), + None => { + if integral.is_empty() { + return Invalid; // No digits at all + } + Valid(Decimal::new(integral, b"", 0)) + } Some(&b'e') | Some(&b'E') => { if integral.is_empty() { return Invalid; // No digits before 'e' diff --git a/src/libcoretest/num/dec2flt/mod.rs b/src/libcoretest/num/dec2flt/mod.rs index 131cf62957537..fb98e7e6f9adf 100644 --- a/src/libcoretest/num/dec2flt/mod.rs +++ b/src/libcoretest/num/dec2flt/mod.rs @@ -101,6 +101,18 @@ fn lonely_dot() { assert_eq!(".".parse(), Ok(0.0)); } +#[test] +fn lonely_sign() { + assert!("+".parse::().is_err()); + assert!("-".parse::().is_err()); +} + +#[test] +fn whitespace() { + assert!(" 1.0".parse::().is_err()); + assert!("1.0 ".parse::().is_err()); +} + #[test] fn nan() { assert!("NaN".parse::().unwrap().is_nan()); From a4cbd6a7fdb0bc01a593bab57207fd631c971764 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Sep 2015 14:31:01 -0700 Subject: [PATCH 02/10] rustc: Don't lint about isize/usize in FFI This lint warning was originally intended to help against misuse of the old Rust `int` and `uint` types in FFI bindings where the Rust `int` was not equal to the C `int`. This confusion no longer exists (as Rust's types are now `isize` and `usize`), and as a result the need for this lint has become much less over time. Additionally, starting with [the RFC for libc][rfc] it's likely that `isize` and `usize` will be quite common in FFI bindings (e.g. they're the definition of `size_t` and `ssize_t` on many platforms). [rfc]: /~https://github.com/rust-lang/rfcs/pull/1291 This commit disables these lints to instead consider `isize` and `usize` valid types to have in FFI signatures. --- src/librustc_lint/builtin.rs | 8 -------- src/test/compile-fail/issue-16250.rs | 4 +++- src/test/compile-fail/lint-ctypes.rs | 9 +++++---- .../foreign-int-types.rs} | 5 ++--- 4 files changed, 10 insertions(+), 16 deletions(-) rename src/test/{compile-fail/warn-foreign-int-types.rs => run-pass/foreign-int-types.rs} (73%) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 4084f13e818f2..d90b7d6fac3e4 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -557,14 +557,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::TyInt(hir::TyIs) => { - FfiUnsafe("found Rust type `isize` in foreign module, while \ - `libc::c_int` or `libc::c_long` should be used") - } - ty::TyUint(hir::TyUs) => { - FfiUnsafe("found Rust type `usize` in foreign module, while \ - `libc::c_uint` or `libc::c_ulong` should be used") - } ty::TyChar => { FfiUnsafe("found Rust type `char` in foreign module, while \ `u32` or `libc::wchar_t` should be used") diff --git a/src/test/compile-fail/issue-16250.rs b/src/test/compile-fail/issue-16250.rs index b5aa3568122ad..288fe4a9abb82 100644 --- a/src/test/compile-fail/issue-16250.rs +++ b/src/test/compile-fail/issue-16250.rs @@ -10,8 +10,10 @@ #![deny(warnings)] +pub struct Foo; + extern { - pub fn foo(x: (isize)); //~ ERROR found Rust type `isize` in foreign module + pub fn foo(x: (Foo)); //~ ERROR found struct without } fn main() { diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs index 4daba86679d5d..5c49098d87053 100644 --- a/src/test/compile-fail/lint-ctypes.rs +++ b/src/test/compile-fail/lint-ctypes.rs @@ -27,12 +27,11 @@ pub struct ZeroSize; pub type RustFn = fn(); pub type RustBadRet = extern fn() -> Box; pub type CVoidRet = (); +pub struct Foo; extern { - pub fn bare_type1(size: isize); //~ ERROR: found Rust type - pub fn bare_type2(size: usize); //~ ERROR: found Rust type - pub fn ptr_type1(size: *const isize); //~ ERROR: found Rust type - pub fn ptr_type2(size: *const usize); //~ ERROR: found Rust type + pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without + pub fn ptr_type2(size: *const Foo); //~ ERROR: found struct without pub fn slice_type(p: &[u32]); //~ ERROR: found Rust slice type pub fn str_type(p: &str); //~ ERROR: found Rust type pub fn box_type(p: Box); //~ ERROR found Rust type @@ -55,6 +54,8 @@ extern { pub fn good8(fptr: extern fn() -> !); pub fn good9() -> (); pub fn good10() -> CVoidRet; + pub fn good11(size: isize); + pub fn good12(size: usize); } fn main() { diff --git a/src/test/compile-fail/warn-foreign-int-types.rs b/src/test/run-pass/foreign-int-types.rs similarity index 73% rename from src/test/compile-fail/warn-foreign-int-types.rs rename to src/test/run-pass/foreign-int-types.rs index b77f25a0a344f..5ea0ef6c7ba3b 100644 --- a/src/test/compile-fail/warn-foreign-int-types.rs +++ b/src/test/run-pass/foreign-int-types.rs @@ -13,9 +13,8 @@ mod xx { extern { - pub fn strlen(str: *const u8) -> usize; //~ ERROR found Rust type `usize` - pub fn foo(x: isize, y: usize); //~ ERROR found Rust type `isize` - //~^ ERROR found Rust type `usize` + pub fn strlen(str: *const u8) -> usize; + pub fn foo(x: isize, y: usize); } } From eb2aca307fc14dbcf0325f0dc06bb2f15faddc85 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2015 19:58:00 +0300 Subject: [PATCH 03/10] deduplicate trait errors before they are displayed Because of type inference, duplicate obligations exist and cause duplicate errors. To avoid this, only display the first error for each (predicate,span). The inclusion of the span is somewhat bikesheddy, but *is* the more conservative option (it does not remove some instability, as duplicate obligations are ignored by `duplicate_set` under some inference conditions). Fixes #28098 cc #21528 (is it a dupe?) --- src/librustc/middle/infer/mod.rs | 7 +++- src/librustc/middle/traits/error_reporting.rs | 27 ++++++++++++++ src/librustc/middle/traits/fulfill.rs | 6 ++++ src/librustc/middle/traits/mod.rs | 2 ++ ...ed-types-ICE-when-projecting-out-of-err.rs | 1 - .../compile-fail/associated-types-path-2.rs | 1 - .../compile-fail/coerce-unsafe-to-closure.rs | 1 - .../compile-fail/const-eval-overflow-4b.rs | 2 -- src/test/compile-fail/fn-variance-1.rs | 2 -- src/test/compile-fail/for-loop-bogosity.rs | 3 -- .../compile-fail/indexing-requires-a-uint.rs | 1 - src/test/compile-fail/integral-indexing.rs | 8 ----- src/test/compile-fail/issue-11771.rs | 2 -- src/test/compile-fail/issue-13352.rs | 1 - src/test/compile-fail/issue-14084.rs | 1 - src/test/compile-fail/issue-20605.rs | 3 -- src/test/compile-fail/issue-2149.rs | 1 - src/test/compile-fail/issue-22645.rs | 4 +-- src/test/compile-fail/issue-24352.rs | 1 - src/test/compile-fail/issue-28098.rs | 35 +++++++++++++++++++ .../compile-fail/shift-various-bad-types.rs | 3 -- src/test/compile-fail/str-idx.rs | 1 - src/test/compile-fail/str-mut-idx.rs | 1 - .../unboxed-closures-unsafe-extern-fn.rs | 1 - .../unboxed-closures-wrong-abi.rs | 1 - ...boxed-closures-wrong-arg-type-extern-fn.rs | 1 - 26 files changed, 77 insertions(+), 40 deletions(-) create mode 100644 src/test/compile-fail/issue-28098.rs diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 917727907ba88..3def56f94a181 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -43,7 +43,7 @@ use std::rc::Rc; use syntax::ast; use syntax::codemap; use syntax::codemap::{Span, DUMMY_SP}; -use util::nodemap::{FnvHashMap, NodeMap}; +use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap}; use self::combine::CombineFields; use self::region_inference::{RegionVarBindings, RegionSnapshot}; @@ -92,6 +92,10 @@ pub struct InferCtxt<'a, 'tcx: 'a> { pub fulfillment_cx: RefCell>, + // the set of predicates on which errors have been reported, to + // avoid reporting the same error twice. + pub reported_trait_errors: RefCell>>, + // This is a temporary field used for toggling on normalization in the inference context, // as we move towards the approach described here: // https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293 @@ -374,6 +378,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, region_vars: RegionVarBindings::new(tcx), parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)), + reported_trait_errors: RefCell::new(FnvHashSet()), normalize: false, err_count_on_creation: tcx.sess.err_count() } diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 2ed53f16afd28..ce71ba2ff2e74 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -33,6 +33,26 @@ use std::fmt; use syntax::codemap::Span; use rustc_front::attr::{AttributeMethods, AttrMetaMethods}; +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct TraitErrorKey<'tcx> { + is_warning: bool, + span: Span, + predicate: ty::Predicate<'tcx> +} + +impl<'tcx> TraitErrorKey<'tcx> { + fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx>, + e: &FulfillmentError<'tcx>) -> Self { + let predicate = + infcx.resolve_type_vars_if_possible(&e.obligation.predicate); + TraitErrorKey { + is_warning: is_warning(&e.obligation), + span: e.obligation.cause.span, + predicate: infcx.tcx.erase_regions(&predicate) + } + } +} + pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, errors: &Vec>) { for error in errors { @@ -42,6 +62,13 @@ pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, error: &FulfillmentError<'tcx>) { + let error_key = TraitErrorKey::from_error(infcx, error); + debug!("report_fulfillment_errors({:?}) - key={:?}", + error, error_key); + if !infcx.reported_trait_errors.borrow_mut().insert(error_key) { + debug!("report_fulfillment_errors: skipping duplicate"); + return; + } match error.code { FulfillmentErrorCode::CodeSelectionError(ref e) => { report_selection_error(infcx, &error.obligation, e); diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 29032f0c4719a..d4e6f693d965d 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -49,6 +49,12 @@ pub struct FulfillmentContext<'tcx> { // than the `SelectionCache`: it avoids duplicate errors and // permits recursive obligations, which are often generated from // traits like `Send` et al. + // + // Note that because of type inference, a predicate can still + // occur twice in the predicates list, for example when 2 + // initially-distinct type variables are unified after being + // inserted. Deduplicating the predicate set on selection had a + // significant performance cost the last time I checked. duplicate_set: FulfilledPredicates<'tcx>, // A list of all obligations that have been registered with this diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index b0d4d92e8e1b2..7f76cfaee5866 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -21,10 +21,12 @@ use middle::subst; use middle::ty::{self, HasTypeFlags, Ty}; use middle::ty::fold::TypeFoldable; use middle::infer::{self, fixup_err_to_string, InferCtxt}; + use std::rc::Rc; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; +pub use self::error_reporting::TraitErrorKey; pub use self::error_reporting::report_fulfillment_errors; pub use self::error_reporting::report_overflow_error; pub use self::error_reporting::report_selection_error; diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 4aad828590a30..c5a47f3e5358f 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -32,5 +32,4 @@ fn ice(a: A) { let r = loop {}; r = r + a; //~^ ERROR not implemented - //~| ERROR not implemented } diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index e603cca7f384b..c9374d4293800 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -39,7 +39,6 @@ pub fn f1_int_uint() { pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR the trait `Foo` is not implemented - //~| ERROR the trait `Foo` is not implemented } pub fn f1_uint_int() { diff --git a/src/test/compile-fail/coerce-unsafe-to-closure.rs b/src/test/compile-fail/coerce-unsafe-to-closure.rs index 27b4a04054f07..90cbbf242aad4 100644 --- a/src/test/compile-fail/coerce-unsafe-to-closure.rs +++ b/src/test/compile-fail/coerce-unsafe-to-closure.rs @@ -11,5 +11,4 @@ fn main() { let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs index 6322b56a82f00..a8f47ab92e529 100644 --- a/src/test/compile-fail/const-eval-overflow-4b.rs +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -23,7 +23,6 @@ const A_I8_T : [u32; (i8::MAX as i8 + 1u8) as usize] //~^ ERROR mismatched types //~| the trait `core::ops::Add` is not implemented for the type `i8` - //~| the trait `core::ops::Add` is not implemented for the type `i8` = [0; (i8::MAX as usize) + 1]; fn main() { @@ -33,4 +32,3 @@ fn main() { fn foo(x: T) { println!("{:?}", x); } - diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/compile-fail/fn-variance-1.rs index 8e1e88a92e452..e9dd1cb719dbc 100644 --- a/src/test/compile-fail/fn-variance-1.rs +++ b/src/test/compile-fail/fn-variance-1.rs @@ -20,10 +20,8 @@ fn main() { apply(&3, takes_imm); apply(&3, takes_mut); //~^ ERROR (values differ in mutability) - //~| ERROR (values differ in mutability) apply(&mut 3, takes_mut); apply(&mut 3, takes_imm); //~^ ERROR (values differ in mutability) - //~| ERROR (values differ in mutability) } diff --git a/src/test/compile-fail/for-loop-bogosity.rs b/src/test/compile-fail/for-loop-bogosity.rs index 6bc0e74a2eb58..c77683045170e 100644 --- a/src/test/compile-fail/for-loop-bogosity.rs +++ b/src/test/compile-fail/for-loop-bogosity.rs @@ -25,9 +25,6 @@ pub fn main() { y: 2, }; for x in bogus { //~ ERROR `core::iter::Iterator` is not implemented for the type `MyStruct` - //~^ ERROR - //~^^ ERROR - // FIXME(#21528) not fulfilled obligation error should be reported once, not thrice drop(x); } } diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs index 3ca00fcb66ac1..3d3b7bc1bcb43 100644 --- a/src/test/compile-fail/indexing-requires-a-uint.rs +++ b/src/test/compile-fail/indexing-requires-a-uint.rs @@ -14,7 +14,6 @@ fn main() { fn bar(_: T) {} [0][0u8]; //~ ERROR: the trait `core::ops::Index` is not implemented - //~^ ERROR: the trait `core::ops::Index` is not implemented [0][0]; // should infer to be a usize diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs index e2fb0fa4f2fa5..f78d677679bc8 100644 --- a/src/test/compile-fail/integral-indexing.rs +++ b/src/test/compile-fail/integral-indexing.rs @@ -14,21 +14,13 @@ pub fn main() { v[3_usize]; v[3]; v[3u8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented v[3i8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented v[3u32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented v[3i32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3_usize]; s.as_bytes()[3]; s.as_bytes()[3u8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3i8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3u32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3i32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented } diff --git a/src/test/compile-fail/issue-11771.rs b/src/test/compile-fail/issue-11771.rs index 40fc6b1ed6aaa..69899105bc317 100644 --- a/src/test/compile-fail/issue-11771.rs +++ b/src/test/compile-fail/issue-11771.rs @@ -12,12 +12,10 @@ fn main() { let x = (); 1 + x //~^ ERROR E0277 - //~| ERROR E0277 ; let x: () = (); 1 + x //~^ ERROR E0277 - //~| ERROR E0277 ; } diff --git a/src/test/compile-fail/issue-13352.rs b/src/test/compile-fail/issue-13352.rs index 14128a0e6f7ec..13e677d72bc1e 100644 --- a/src/test/compile-fail/issue-13352.rs +++ b/src/test/compile-fail/issue-13352.rs @@ -18,5 +18,4 @@ fn main() { }); 2_usize + (loop {}); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/compile-fail/issue-14084.rs b/src/test/compile-fail/issue-14084.rs index b33a6767274ea..26ed9d8c26ada 100644 --- a/src/test/compile-fail/issue-14084.rs +++ b/src/test/compile-fail/issue-14084.rs @@ -14,6 +14,5 @@ fn main() { box ( () ) 0; //~^ ERROR: the trait `core::ops::Placer<_>` is not implemented - //~| ERROR: the trait `core::ops::Placer<_>` is not implemented //~| WARN deprecated syntax } diff --git a/src/test/compile-fail/issue-20605.rs b/src/test/compile-fail/issue-20605.rs index 87b7616db8ed2..f2d65af9cdfc8 100644 --- a/src/test/compile-fail/issue-20605.rs +++ b/src/test/compile-fail/issue-20605.rs @@ -11,9 +11,6 @@ fn changer<'a>(mut things: Box>) { for item in *things { *item = 0 } //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `core::iter::Iterator -//~^^ ERROR -//~^^^ ERROR -// FIXME(#21528) error should be reported once, not thrice } fn main() {} diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index bb170ef7d0036..256c5d8e6f72c 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -17,7 +17,6 @@ impl vec_monad for Vec { let mut r = panic!(); for elt in self { r = r + f(*elt); } //~^ ERROR E0277 - //~| ERROR E0277 } } fn main() { diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/compile-fail/issue-22645.rs index 8677934fd646c..aa7fa82fa29ba 100644 --- a/src/test/compile-fail/issue-22645.rs +++ b/src/test/compile-fail/issue-22645.rs @@ -23,7 +23,5 @@ impl Add for Bob { fn main() { let b = Bob + 3.5; b + 3 //~ ERROR: is not implemented - //~^ ERROR: is not implemented - //~^^ ERROR: is not implemented - //~^^^ ERROR: mismatched types + //~^ ERROR: mismatched types } diff --git a/src/test/compile-fail/issue-24352.rs b/src/test/compile-fail/issue-24352.rs index 0fbc634826bc5..9936f67b3af3c 100644 --- a/src/test/compile-fail/issue-24352.rs +++ b/src/test/compile-fail/issue-24352.rs @@ -11,5 +11,4 @@ fn main() { 1.0f64 - 1.0; 1.0f64 - 1 //~ ERROR: is not implemented - //~^ ERROR: is not implemented } diff --git a/src/test/compile-fail/issue-28098.rs b/src/test/compile-fail/issue-28098.rs new file mode 100644 index 0000000000000..f565d24e1fd08 --- /dev/null +++ b/src/test/compile-fail/issue-28098.rs @@ -0,0 +1,35 @@ +// 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. + +fn main() { + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + for _ in false {} + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + other() +} + +pub fn other() { + // check errors are still reported globally + + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + for _ in false {} + //~^ ERROR the trait `core::iter::Iterator` is not implemented +} diff --git a/src/test/compile-fail/shift-various-bad-types.rs b/src/test/compile-fail/shift-various-bad-types.rs index 24b66213b39bd..c980572fa152f 100644 --- a/src/test/compile-fail/shift-various-bad-types.rs +++ b/src/test/compile-fail/shift-various-bad-types.rs @@ -18,15 +18,12 @@ struct Panolpy { fn foo(p: &Panolpy) { 22 >> p.char; //~^ ERROR E0277 - //~| ERROR E0277 22 >> p.str; //~^ ERROR E0277 - //~| ERROR E0277 22 >> p; //~^ ERROR E0277 - //~| ERROR E0277 let x; 22 >> x; // ambiguity error winds up being suppressed diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs index ddd2a4eeedf76..6e48ae20d09f3 100644 --- a/src/test/compile-fail/str-idx.rs +++ b/src/test/compile-fail/str-idx.rs @@ -11,5 +11,4 @@ pub fn main() { let s: &str = "hello"; let c: u8 = s[4]; //~ ERROR the trait `core::ops::Index<_>` is not implemented - //~^ ERROR the trait `core::ops::Index<_>` is not implemented } diff --git a/src/test/compile-fail/str-mut-idx.rs b/src/test/compile-fail/str-mut-idx.rs index 73abe6cb59db2..ec6a14778a463 100644 --- a/src/test/compile-fail/str-mut-idx.rs +++ b/src/test/compile-fail/str-mut-idx.rs @@ -17,7 +17,6 @@ fn mutate(s: &mut str) { s[1usize] = bot(); //~^ ERROR `core::ops::Index` is not implemented for the type `str` //~| ERROR `core::ops::IndexMut` is not implemented for the type `str` - //~| ERROR `core::ops::Index` is not implemented for the type `str` } pub fn main() {} diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index dc7c70ba649d8..361df93a71669 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -35,7 +35,6 @@ fn b() { fn c() { let z = call_it_once(square, 22); //~^ ERROR not implemented - //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index cdcb435b65a6a..ca15d1bb5eefc 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -35,7 +35,6 @@ fn b() { fn c() { let z = call_it_once(square, 22); //~^ ERROR not implemented - //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index 150bf36dcc286..b960362aad7cd 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -36,7 +36,6 @@ fn b() { fn c() { let z = call_it_once(square, 22); //~^ ERROR not implemented - //~| ERROR not implemented } fn main() { } From fc166d44f02c1d7baa20e2ae2ef20b599cd99ecf Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 25 Sep 2015 02:40:57 +0300 Subject: [PATCH 04/10] show each object-safety violation once different supertraits can suffer from the same object-safety violation, leading to duplication in the error message. Avoid it. Fixes #20692 --- src/librustc/middle/traits/error_reporting.rs | 9 ++++++-- src/librustc/middle/traits/object_safety.rs | 2 +- src/librustc/middle/ty/mod.rs | 14 +++++++++++ src/test/compile-fail/issue-20692.rs | 23 +++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/issue-20692.rs diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index ce71ba2ff2e74..4580e642d17df 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -28,7 +28,8 @@ use middle::def_id::DefId; use middle::infer::InferCtxt; use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef, Ty}; use middle::ty::fold::TypeFoldable; -use std::collections::HashMap; +use util::nodemap::{FnvHashMap, FnvHashSet}; + use std::fmt; use syntax::codemap::Span; use rustc_front::attr::{AttributeMethods, AttrMetaMethods}; @@ -124,7 +125,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, (gen.name.as_str().to_string(), trait_ref.substs.types.get(param, i) .to_string()) - }).collect::>(); + }).collect::>(); generic_map.insert("Self".to_string(), trait_ref.self_ty().to_string()); let parser = Parser::new(&istring); @@ -329,7 +330,11 @@ pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>, "the trait `{}` cannot be made into an object", tcx.item_path_str(trait_def_id)); + let mut reported_violations = FnvHashSet(); for violation in object_safety_violations(tcx, trait_def_id) { + if !reported_violations.insert(violation.clone()) { + continue; + } match violation { ObjectSafetyViolation::SizedSelf => { tcx.sess.fileline_note( diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index 3a2602cd5b448..333d23e6eca8b 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -27,7 +27,7 @@ use middle::ty::{self, ToPolyTraitRef, Ty}; use std::rc::Rc; use syntax::ast; -#[derive(Debug)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum ObjectSafetyViolation<'tcx> { /// Self : Sized declared on the trait SizedSelf, diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index a8adb38864424..4a96260ec1e7c 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -272,6 +272,20 @@ impl<'tcx> Method<'tcx> { } } +impl<'tcx> PartialEq for Method<'tcx> { + #[inline] + fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id } +} + +impl<'tcx> Eq for Method<'tcx> {} + +impl<'tcx> Hash for Method<'tcx> { + #[inline] + fn hash(&self, s: &mut H) { + self.def_id.hash(s) + } +} + #[derive(Clone, Copy, Debug)] pub struct AssociatedConst<'tcx> { pub name: Name, diff --git a/src/test/compile-fail/issue-20692.rs b/src/test/compile-fail/issue-20692.rs new file mode 100644 index 0000000000000..62d775adac3c7 --- /dev/null +++ b/src/test/compile-fail/issue-20692.rs @@ -0,0 +1,23 @@ +// 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. + +trait Array: Sized {} + +fn f(x: &T) { + let _ = x + //~^ ERROR `Array` cannot be made into an object + //~| NOTE the trait cannot require that `Self : Sized` + as + &Array; + //~^ ERROR `Array` cannot be made into an object + //~| NOTE the trait cannot require that `Self : Sized` +} + +fn main() {} From 7eb6ca228ee613205d4105ab74d0bdbbb8e6cafe Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 26 Sep 2015 22:25:49 +0300 Subject: [PATCH 05/10] remove the destructors table Conflicts: src/librustc_lint/builtin.rs --- src/librustc/middle/reachable.rs | 14 +++++++++----- src/librustc/middle/ty/context.rs | 4 ---- src/librustc/middle/ty/mod.rs | 5 ----- src/librustc_lint/builtin.rs | 20 ++++++++++---------- src/librustc_typeck/check/method/confirm.rs | 8 +------- src/librustc_typeck/check/mod.rs | 10 ++++++---- src/librustc_typeck/coherence/mod.rs | 7 ++----- 7 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 215368754c999..03374fa492e18 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -348,13 +348,17 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // this properly would result in the necessity of computing *type* // reachability, which might result in a compile time loss. fn mark_destructors_reachable(&mut self) { - for adt in self.tcx.adt_defs() { - if let Some(destructor_def_id) = adt.destructor() { - if destructor_def_id.is_local() { - self.reachable_symbols.insert(destructor_def_id.node); + let drop_trait = match self.tcx.lang_items.drop_trait() { + Some(id) => self.tcx.lookup_trait_def(id), None => { return } + }; + drop_trait.for_each_impl(self.tcx, |drop_impl| { + for destructor in &self.tcx.impl_items.borrow()[&drop_impl] { + let destructor_did = destructor.def_id(); + if destructor_did.is_local() { + self.reachable_symbols.insert(destructor_did.node); } } - } + }) } } diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs index e3b6da56680da..ef9707967f39d 100644 --- a/src/librustc/middle/ty/context.rs +++ b/src/librustc/middle/ty/context.rs @@ -245,9 +245,6 @@ pub struct ctxt<'tcx> { /// True if the variance has been computed yet; false otherwise. pub variance_computed: Cell, - /// A method will be in this list if and only if it is a destructor. - pub destructors: RefCell, - /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. @@ -475,7 +472,6 @@ impl<'tcx> ctxt<'tcx> { normalized_cache: RefCell::new(FnvHashMap()), lang_items: lang_items, provided_method_sources: RefCell::new(DefIdMap()), - destructors: RefCell::new(DefIdSet()), inherent_impls: RefCell::new(DefIdMap()), impl_items: RefCell::new(DefIdMap()), used_unsafe: RefCell::new(NodeSet()), diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index 4a96260ec1e7c..59eb5e7a72f9b 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -2331,11 +2331,6 @@ impl<'tcx> ctxt<'tcx> { self.lookup_adt_def_master(did) } - /// Return the list of all interned ADT definitions - pub fn adt_defs(&self) -> Vec> { - self.adt_defs.borrow().values().cloned().collect() - } - /// Given the did of an item, returns its full set of predicates. pub fn lookup_predicates(&self, did: DefId) -> GenericPredicates<'tcx> { lookup_locally_or_in_crate_store( diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d90b7d6fac3e4..717690adddedd 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -2591,16 +2591,16 @@ impl LintPass for DropWithReprExtern { fn get_lints(&self) -> LintArray { lint_array!(DROP_WITH_REPR_EXTERN) } + fn check_crate(&mut self, ctx: &Context, _: &hir::Crate) { - for dtor_did in ctx.tcx.destructors.borrow().iter() { - let (drop_impl_did, dtor_self_type) = - if dtor_did.is_local() { - let impl_did = ctx.tcx.map.get_parent_did(dtor_did.node); - let ty = ctx.tcx.lookup_item_type(impl_did).ty; - (impl_did, ty) - } else { - continue; - }; + let drop_trait = match ctx.tcx.lang_items.drop_trait() { + Some(id) => ctx.tcx.lookup_trait_def(id), None => { return } + }; + drop_trait.for_each_impl(ctx.tcx, |drop_impl_did| { + if !drop_impl_did.is_local() { + return; + } + let dtor_self_type = ctx.tcx.lookup_item_type(drop_impl_did).ty; match dtor_self_type.sty { ty::TyEnum(self_type_def, _) | @@ -2626,6 +2626,6 @@ impl LintPass for DropWithReprExtern { } _ => {} } - } + }) } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 572ba7a848713..454c11db263e1 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -621,13 +621,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { ty::TraitContainer(trait_def_id) => { callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id) } - ty::ImplContainer(..) => { - // Since `drop` is a trait method, we expect that any - // potential calls to it will wind up in the other - // arm. But just to be sure, check that the method id - // does not appear in the list of destructors. - assert!(!self.tcx().destructors.borrow().contains(&pick.item.def_id())); - } + ty::ImplContainer(..) => {} } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9dd7cfea43f69..9a8f70454ac4b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -431,9 +431,11 @@ pub fn check_item_bodies(ccx: &CrateCtxt) { } pub fn check_drop_impls(ccx: &CrateCtxt) { - for drop_method_did in ccx.tcx.destructors.borrow().iter() { - if drop_method_did.is_local() { - let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node); + let drop_trait = match ccx.tcx.lang_items.drop_trait() { + Some(id) => ccx.tcx.lookup_trait_def(id), None => { return } + }; + drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| { + if drop_impl_did.is_local() { match dropck::check_drop_impl(ccx.tcx, drop_impl_did) { Ok(()) => {} Err(()) => { @@ -441,7 +443,7 @@ pub fn check_drop_impls(ccx: &CrateCtxt) { } } } - } + }); ccx.tcx.sess.abort_if_errors(); } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9ba6f1398e471..8cffac67321f5 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // Populate the table of destructors. It might seem a bit strange to // do this here, but it's actually the most convenient place, since // the coherence tables contain the trait -> type mappings. - self.populate_destructor_table(); + self.populate_destructors(); // Check to make sure implementations of `Copy` are legal. self.check_implementations_of_copy(); @@ -286,7 +286,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // Destructors // - fn populate_destructor_table(&self) { + fn populate_destructors(&self) { let tcx = self.crate_context.tcx; let drop_trait = match tcx.lang_items.drop_trait() { Some(id) => id, None => { return } @@ -309,9 +309,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { ty::TyEnum(type_def, _) | ty::TyStruct(type_def, _) => { type_def.set_destructor(method_def_id.def_id()); - tcx.destructors - .borrow_mut() - .insert(method_def_id.def_id()); } _ => { // Destructors only work on nominal types. From 9cc4beb5c348a26c0e814c55dd772ab587e24219 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 26 Sep 2015 23:12:11 +0300 Subject: [PATCH 06/10] don't crash when there are multiple conflicting implementations of Drop Fixes #28568 --- src/librustc/middle/ty/mod.rs | 1 - src/test/compile-fail/issue-28568.rs | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/issue-28568.rs diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index 59eb5e7a72f9b..3025d7b58979f 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -1695,7 +1695,6 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> { } pub fn set_destructor(&self, dtor: DefId) { - assert!(self.destructor.get().is_none()); self.destructor.set(Some(dtor)); } diff --git a/src/test/compile-fail/issue-28568.rs b/src/test/compile-fail/issue-28568.rs new file mode 100644 index 0000000000000..36b4a57eb117f --- /dev/null +++ b/src/test/compile-fail/issue-28568.rs @@ -0,0 +1,23 @@ +// 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. + +struct MyStruct; + +impl Drop for MyStruct { +//~^ ERROR conflicting implementations for trait + fn drop(&mut self) { } +} + +impl Drop for MyStruct { +//~^ NOTE conflicting implementation here + fn drop(&mut self) { } +} + +fn main() {} From 98aabbc899972cb239db5058da66b405c10c05f2 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2015 17:02:07 +0300 Subject: [PATCH 07/10] use the infcx tables to check if a closure is Copy Fixes #28550 --- src/librustc/middle/infer/mod.rs | 9 ++++++++- src/test/run-pass/issue-28550.rs | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue-28550.rs diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 3def56f94a181..0c1c905c8dadb 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -1394,9 +1394,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.resolve_type_vars_or_error(&ty) } + pub fn tables_are_tcx_tables(&self) -> bool { + let tables: &RefCell = &self.tables; + let tcx_tables: &RefCell = &self.tcx.tables; + tables as *const _ == tcx_tables as *const _ + } + pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); - if ty.needs_infer() { + if ty.needs_infer() || + (ty.has_closure_types() && !self.tables_are_tcx_tables()) { // this can get called from typeck (by euv), and moves_by_default // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other diff --git a/src/test/run-pass/issue-28550.rs b/src/test/run-pass/issue-28550.rs new file mode 100644 index 0000000000000..f44a535e8176e --- /dev/null +++ b/src/test/run-pass/issue-28550.rs @@ -0,0 +1,25 @@ +// 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. + +struct AT,T>(F::Output); +struct BT,T>(A); + +// Removing Option causes it to compile. +fn fooT>(f: F) -> Option> { + Some(B(A(f()))) +} + +fn main() { + let v = (|| foo(||4))(); + match v { + Some(B(A(4))) => {}, + _ => unreachable!() + } +} From b672349a23e6e0587589cbfd9f2b7ff176218ec2 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 21 Sep 2015 14:21:30 +0530 Subject: [PATCH 08/10] Make function pointers implement traits for up to 12 parameters (12 was chosen to be consistent with what we do for tuples) Fixes #28559 --- src/libcore/ptr.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 406a5dffdb084..831616293cd8f 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -385,6 +385,13 @@ fnptr_impls_args! { A, B } fnptr_impls_args! { A, B, C } fnptr_impls_args! { A, B, C, D } fnptr_impls_args! { A, B, C, D, E } +fnptr_impls_args! { A, B, C, D, E, F } +fnptr_impls_args! { A, B, C, D, E, F, G } +fnptr_impls_args! { A, B, C, D, E, F, G, H } +fnptr_impls_args! { A, B, C, D, E, F, G, H, I } +fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J } +fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K } +fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } // Comparison for pointers #[stable(feature = "rust1", since = "1.0.0")] From 667584d6344bd36925630ce41bc0bd604d712e16 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 Sep 2015 18:07:05 +1200 Subject: [PATCH 09/10] Warn on `pub extern crate`. Temporary 'fix' for #26775 --- src/libsyntax/parse/parser.rs | 17 ++++++++++++----- src/test/compile-fail/warn-pub-extern-crate.rs | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/warn-pub-extern-crate.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ff622859cf0b1..8d50cc099bd60 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5116,12 +5116,19 @@ impl<'a> Parser<'a> { try!(self.expect(&token::Semi)); let last_span = self.last_span; + + if visibility == ast::Public { + self.span_warn(mk_sp(lo, last_span.hi), + "`pub extern crate` does not work as expected and should not be used. \ + Likely to become an error. Prefer `extern crate` and `pub use`."); + } + Ok(self.mk_item(lo, - last_span.hi, - ident, - ItemExternCrate(maybe_path), - visibility, - attrs)) + last_span.hi, + ident, + ItemExternCrate(maybe_path), + visibility, + attrs)) } /// Parse `extern` for foreign ABIs diff --git a/src/test/compile-fail/warn-pub-extern-crate.rs b/src/test/compile-fail/warn-pub-extern-crate.rs new file mode 100644 index 0000000000000..fec0b8e1a4cc1 --- /dev/null +++ b/src/test/compile-fail/warn-pub-extern-crate.rs @@ -0,0 +1,18 @@ +// 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 `pub extern crate` gives a warning. + + +pub extern crate core; //~WARN `pub extern crate` does not work +//~^ ERROR core + +fn main() { +} From f492cf79a25df703f8bfb431495d39ac0a8012cf Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 31 Aug 2015 22:37:05 +0300 Subject: [PATCH 10/10] check upvars in closures that are in statics Fixes #27890 Fixes #28099 Fixes #28113 --- src/librustc_typeck/check/mod.rs | 7 ++++++- src/librustc_typeck/check/upvar.rs | 14 +++++++++++++ src/test/compile-fail/borrowck-in-static.rs | 22 +++++++++++++++++++++ src/test/compile-fail/issue-28113.rs | 15 ++++++++++++++ src/test/run-pass/issue-27890.rs | 16 +++++++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/borrowck-in-static.rs create mode 100644 src/test/compile-fail/issue-28113.rs create mode 100644 src/test/run-pass/issue-27890.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9a8f70454ac4b..b07168966c191 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4153,8 +4153,13 @@ fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, check_expr_with_hint(fcx, e, declty); demand::coerce(fcx, e.span, declty, e); - fcx.select_all_obligations_or_error(); + + fcx.select_all_obligations_and_apply_defaults(); + upvar::closure_analyze_const(&fcx, e); + fcx.select_obligations_where_possible(); fcx.check_casts(); + fcx.select_all_obligations_or_error(); + regionck::regionck_expr(fcx, e); writeback::resolve_type_vars_in_expr(fcx, e); } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index f9f711a1a6316..10d7c4620e7d3 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -73,6 +73,20 @@ pub fn closure_analyze_fn(fcx: &FnCtxt, assert!(fcx.inh.deferred_call_resolutions.borrow().is_empty()); } +pub fn closure_analyze_const(fcx: &FnCtxt, + body: &hir::Expr) +{ + let mut seed = SeedBorrowKind::new(fcx); + seed.visit_expr(body); + let closures_with_inferred_kinds = seed.closures_with_inferred_kinds; + + let mut adjust = AdjustBorrowKind::new(fcx, &closures_with_inferred_kinds); + adjust.visit_expr(body); + + // it's our job to process these. + assert!(fcx.inh.deferred_call_resolutions.borrow().is_empty()); +} + /////////////////////////////////////////////////////////////////////////// // SEED BORROW KIND diff --git a/src/test/compile-fail/borrowck-in-static.rs b/src/test/compile-fail/borrowck-in-static.rs new file mode 100644 index 0000000000000..16b0e8638de39 --- /dev/null +++ b/src/test/compile-fail/borrowck-in-static.rs @@ -0,0 +1,22 @@ +// 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 borrowck looks inside consts/statics + +static FN : &'static (Fn() -> (BoxBox>) + Sync) = &|| { + let x = Box::new(0); + Box::new(|| x) //~ ERROR cannot move out of captured outer variable +}; + +fn main() { + let f = (FN)(); + f(); + f(); +} diff --git a/src/test/compile-fail/issue-28113.rs b/src/test/compile-fail/issue-28113.rs new file mode 100644 index 0000000000000..c5c4fb070178a --- /dev/null +++ b/src/test/compile-fail/issue-28113.rs @@ -0,0 +1,15 @@ +// 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. + +const X: u8 = + || -> u8 { 5 }() //~ ERROR function calls in constants are limited +; + +fn main() {} diff --git a/src/test/run-pass/issue-27890.rs b/src/test/run-pass/issue-27890.rs new file mode 100644 index 0000000000000..a33882a833185 --- /dev/null +++ b/src/test/run-pass/issue-27890.rs @@ -0,0 +1,16 @@ +// 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. + +static PLUS_ONE: &'static (Fn(i32) -> i32 + Sync) = (&|x: i32| { x + 1 }) + as &'static (Fn(i32) -> i32 + Sync); + +fn main() { + assert_eq!(PLUS_ONE(2), 3); +}