From 4ef7551ccacd4d2042493f2ed905813b297634d0 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Sun, 18 Jan 2015 19:43:35 +0900 Subject: Fix type inference related to upvars in closures --- src/test/run-pass/unboxed-closures-infer-upvar.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/run-pass/unboxed-closures-infer-upvar.rs (limited to 'src/test/run-pass') diff --git a/src/test/run-pass/unboxed-closures-infer-upvar.rs b/src/test/run-pass/unboxed-closures-infer-upvar.rs new file mode 100644 index 00000000000..087ef5dcf05 --- /dev/null +++ b/src/test/run-pass/unboxed-closures-infer-upvar.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. + +// Test that the type variable in the type(`Vec<_>`) of a closed over +// variable does not interfere with type inference. + +fn f(mut f: F) { + f(); +} + +fn main() { + let mut v: Vec<_> = vec![]; + f(|| v.push(0)); + assert_eq!(v, vec![0]); +} -- cgit 1.4.1-3-g733a5 From 5354317037368124d180acc3f8754bdb2b0387b8 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Mon, 9 Feb 2015 09:29:21 -0800 Subject: Process cfg_attr right before stripping cfg Fixes #22070. Fixes #19372. --- src/libsyntax/config.rs | 49 ++++++++++++++++++++++++++++++- src/libsyntax/ext/base.rs | 2 -- src/libsyntax/ext/cfg_attr.rs | 34 --------------------- src/libsyntax/lib.rs | 1 - src/test/compile-fail/cfg-attr-cfg-2.rs | 18 ++++++++++++ src/test/compile-fail/cfg-attr-crate-2.rs | 17 +++++++++++ src/test/run-pass/cfg-attr-cfg.rs | 15 ++++++++++ src/test/run-pass/cfg-attr-crate.rs | 15 ++++++++++ 8 files changed, 113 insertions(+), 38 deletions(-) delete mode 100644 src/libsyntax/ext/cfg_attr.rs create mode 100644 src/test/compile-fail/cfg-attr-cfg-2.rs create mode 100644 src/test/compile-fail/cfg-attr-crate-2.rs create mode 100644 src/test/run-pass/cfg-attr-cfg.rs create mode 100644 src/test/run-pass/cfg-attr-crate.rs (limited to 'src/test/run-pass') diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index eb845e463a0..7ca0591be50 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -12,7 +12,7 @@ use attr::AttrMetaMethods; use diagnostic::SpanHandler; use fold::Folder; use {ast, fold, attr}; -use codemap::Spanned; +use codemap::{Spanned, respan}; use ptr::P; use util::small_vector::SmallVector; @@ -26,6 +26,7 @@ struct Context where F: FnMut(&[ast::Attribute]) -> bool { // Support conditional compilation by transforming the AST, stripping out // any items that do not belong in the current configuration pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { + let krate = process_cfg_attr(diagnostic, krate); let config = krate.config.clone(); strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs)) } @@ -281,3 +282,49 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attr attr::cfg_matches(diagnostic, cfg, &*mis[0]) }) } + +struct CfgAttrFolder<'a> { + diag: &'a SpanHandler, + config: ast::CrateConfig, +} + +// Process `#[cfg_attr]`. +fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { + let mut fld = CfgAttrFolder { + diag: diagnostic, + config: krate.config.clone(), + }; + fld.fold_crate(krate) +} + +impl<'a> fold::Folder for CfgAttrFolder<'a> { + fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { + if !attr.check_name("cfg_attr") { + return fold::noop_fold_attribute(attr, self); + } + + let (cfg, mi) = match attr.meta_item_list() { + Some([ref cfg, ref mi]) => (cfg, mi), + _ => { + self.diag.span_err(attr.span, "expected `#[cfg_attr(, )]`"); + return None; + } + }; + + if attr::cfg_matches(self.diag, &self.config[], &cfg) { + Some(respan(mi.span, ast::Attribute_ { + id: attr::mk_attr_id(), + style: attr.node.style, + value: mi.clone(), + is_sugared_doc: false, + })) + } else { + None + } + } + + // Need the ability to run pre-expansion. + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) + } +} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 778b2cabea6..64ae6162ef4 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -528,8 +528,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv { syntax_expanders.insert(intern("cfg"), builtin_normal_expander( ext::cfg::expand_cfg)); - syntax_expanders.insert(intern("cfg_attr"), - Modifier(box ext::cfg_attr::expand)); syntax_expanders.insert(intern("trace_macros"), builtin_normal_expander( ext::trace_macros::expand_trace_macros)); diff --git a/src/libsyntax/ext/cfg_attr.rs b/src/libsyntax/ext/cfg_attr.rs deleted file mode 100644 index 72eaa3e47be..00000000000 --- a/src/libsyntax/ext/cfg_attr.rs +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -use ast; -use attr; -use codemap::Span; -use ext::base::ExtCtxt; -use ext::build::AstBuilder; -use ptr::P; - -pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P) -> P { - let (cfg, attr) = match mi.node { - ast::MetaList(_, ref mis) if mis.len() == 2 => (&mis[0], &mis[1]), - _ => { - cx.span_err(sp, "expected `#[cfg_attr(, )]`"); - return it; - } - }; - - let mut out = (*it).clone(); - if attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &**cfg) { - out.attrs.push(cx.attribute(attr.span, attr.clone())); - } - - P(out) -} - diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 08e795ef80d..41850ada3e6 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -96,7 +96,6 @@ pub mod ext { pub mod base; pub mod build; pub mod cfg; - pub mod cfg_attr; pub mod concat; pub mod concat_idents; pub mod deriving; diff --git a/src/test/compile-fail/cfg-attr-cfg-2.rs b/src/test/compile-fail/cfg-attr-cfg-2.rs new file mode 100644 index 00000000000..b71a3be5dce --- /dev/null +++ b/src/test/compile-fail/cfg-attr-cfg-2.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. +// +// error-pattern: main function not found +// compile-flags: --cfg foo + +// main is conditionally compiled, but the conditional compilation +// is conditional too! + +#[cfg_attr(foo, cfg(bar))] +fn main() { } diff --git a/src/test/compile-fail/cfg-attr-crate-2.rs b/src/test/compile-fail/cfg-attr-crate-2.rs new file mode 100644 index 00000000000..4867dd8d0b4 --- /dev/null +++ b/src/test/compile-fail/cfg-attr-crate-2.rs @@ -0,0 +1,17 @@ +// 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. +// +// compile-flags: --cfg broken + +// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 + +#![cfg_attr(broken, no_std)] //~ ERROR no_std is experimental + +fn main() { } diff --git a/src/test/run-pass/cfg-attr-cfg.rs b/src/test/run-pass/cfg-attr-cfg.rs new file mode 100644 index 00000000000..09ab7019486 --- /dev/null +++ b/src/test/run-pass/cfg-attr-cfg.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. + +// main is conditionally compiled, but the conditional compilation +// is conditional too! + +#[cfg_attr(foo, cfg(bar))] +fn main() { } diff --git a/src/test/run-pass/cfg-attr-crate.rs b/src/test/run-pass/cfg-attr-crate.rs new file mode 100644 index 00000000000..e6bd8afad28 --- /dev/null +++ b/src/test/run-pass/cfg-attr-crate.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. + +// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 + +#![cfg_attr(not_used, no_std)] + +fn main() { } -- cgit 1.4.1-3-g733a5 From a1b3189f4864f1ada755e9ebc2e0ce1ac5bf2e06 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 6 Feb 2015 18:05:32 +0100 Subject: add test illustrating the feature. (with multiple impls to further exercise correct trait-matching.) --- .../run-pass/infer-container-across-object-cast.rs | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/test/run-pass/infer-container-across-object-cast.rs (limited to 'src/test/run-pass') diff --git a/src/test/run-pass/infer-container-across-object-cast.rs b/src/test/run-pass/infer-container-across-object-cast.rs new file mode 100644 index 00000000000..979e76b1ff9 --- /dev/null +++ b/src/test/run-pass/infer-container-across-object-cast.rs @@ -0,0 +1,59 @@ +// 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. + +// Given ` as Box`, we should be able to infer that a +// `Box<_>` is the expected type. + +trait Foo { fn foo(&self) -> u32; } +impl Foo for u32 { fn foo(&self) -> u32 { *self } } + +// (another impl to ensure trait-matching cannot just choose from a singleton set) +impl Foo for () { fn foo(&self) -> u32 { -176 } } + +trait Boxed { fn make() -> Self; } +impl Boxed for Box { fn make() -> Self { Box::new(7) } } + +// (another impl to ensure trait-matching cannot just choose from a singleton set) +impl Boxed for () { fn make() -> Self { () } } + +fn boxed_foo() { + let b7 = Boxed::make() as Box; + assert_eq!(b7.foo(), 7); +} + +trait Refed<'a,T> { fn make(&'a T) -> Self; } +impl<'a> Refed<'a, u32> for &'a u32 { fn make(x: &'a u32) -> Self { x } } + +// (another impl to ensure trait-matching cannot just choose from a singleton set) +impl<'a,'b> Refed<'a, ()> for &'b () { fn make(_: &'a ()) -> Self { static U: () = (); &U } } + +fn refed_foo() { + let a = 8; + let b7 = Refed::make(&a) as &Foo; + assert_eq!(b7.foo(), 8); +} + +fn check_subtyping_works() { + fn inner<'short, 'long:'short>(_s: &'short u32, + l: &'long u32) -> &'short (Foo+'short) { + Refed::make(l) as &Foo + } + + let a = 9; + let b = 10; + let r = inner(&b, &a); + assert_eq!(r.foo(), 9); +} + +pub fn main() { + boxed_foo(); + refed_foo(); + check_subtyping_works(); +} -- cgit 1.4.1-3-g733a5