2013-10-02 20:10:16 -05:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
//! Feature gating
|
|
|
|
//!
|
|
|
|
//! This modules implements the gating necessary for preventing certain compiler
|
|
|
|
//! features from being used by default. This module will crawl a pre-expanded
|
|
|
|
//! AST to ensure that there are no features which are used that are not
|
|
|
|
//! enabled.
|
|
|
|
//!
|
|
|
|
//! Features are enabled in programs via the crate-level attributes of
|
2014-06-22 12:29:42 -05:00
|
|
|
//! `#![feature(...)]` with a comma-separated list of features.
|
2014-11-06 02:05:53 -06:00
|
|
|
use self::Status::*;
|
2013-10-02 20:10:16 -05:00
|
|
|
|
2014-09-10 19:55:42 -05:00
|
|
|
use abi::RustIntrinsic;
|
|
|
|
use ast::NodeId;
|
|
|
|
use ast;
|
|
|
|
use attr;
|
|
|
|
use attr::AttrMetaMethods;
|
2014-12-23 23:44:13 -06:00
|
|
|
use codemap::{CodeMap, Span};
|
2014-09-10 19:55:42 -05:00
|
|
|
use diagnostic::SpanHandler;
|
|
|
|
use visit;
|
|
|
|
use visit::Visitor;
|
|
|
|
use parse::token;
|
2013-11-26 16:55:06 -06:00
|
|
|
|
2014-09-07 12:09:06 -05:00
|
|
|
use std::slice;
|
2014-12-06 19:55:34 -06:00
|
|
|
use std::ascii::AsciiExt;
|
|
|
|
|
2014-02-24 14:45:31 -06:00
|
|
|
|
2014-12-03 02:29:57 -06:00
|
|
|
// if you change this list without updating src/doc/reference.md, @cmr will be sad
|
2013-10-02 20:10:16 -05:00
|
|
|
static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
|
2015-01-05 00:04:55 -06:00
|
|
|
("globs", Accepted),
|
2015-01-02 21:41:40 -06:00
|
|
|
("macro_rules", Accepted),
|
2014-11-15 19:57:54 -06:00
|
|
|
("struct_variant", Accepted),
|
2013-10-21 04:16:58 -05:00
|
|
|
("asm", Active),
|
2014-10-01 16:19:55 -05:00
|
|
|
("managed_boxes", Removed),
|
2013-11-22 06:25:14 -06:00
|
|
|
("non_ascii_idents", Active),
|
2013-11-26 13:21:22 -06:00
|
|
|
("thread_local", Active),
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
("link_args", Active),
|
2015-01-06 11:24:46 -06:00
|
|
|
("phase", Removed),
|
2014-05-24 18:16:10 -05:00
|
|
|
("plugin_registrar", Active),
|
2014-01-17 18:22:48 -06:00
|
|
|
("log_syntax", Active),
|
2014-01-27 07:30:52 -06:00
|
|
|
("trace_macros", Active),
|
2014-04-03 18:24:21 -05:00
|
|
|
("concat_idents", Active),
|
2014-06-17 18:00:04 -05:00
|
|
|
("unsafe_destructor", Active),
|
2014-06-20 18:39:23 -05:00
|
|
|
("intrinsics", Active),
|
|
|
|
("lang_items", Active),
|
2014-04-03 18:24:21 -05:00
|
|
|
|
2014-01-22 19:25:22 -06:00
|
|
|
("simd", Active),
|
2015-01-05 00:07:16 -06:00
|
|
|
("default_type_params", Accepted),
|
2014-02-04 05:03:00 -06:00
|
|
|
("quote", Active),
|
2014-12-30 09:44:31 -06:00
|
|
|
("link_llvm_intrinsics", Active),
|
2014-02-25 18:15:10 -06:00
|
|
|
("linkage", Active),
|
2014-11-02 11:40:30 -06:00
|
|
|
("struct_inherit", Removed),
|
2013-10-02 20:10:16 -05:00
|
|
|
|
2014-06-24 18:34:46 -05:00
|
|
|
("quad_precision_float", Removed),
|
2014-04-08 17:08:08 -05:00
|
|
|
|
2014-07-01 11:39:41 -05:00
|
|
|
("rustc_diagnostic_macros", Active),
|
2014-05-29 00:26:56 -05:00
|
|
|
("unboxed_closures", Active),
|
2014-08-12 22:31:30 -05:00
|
|
|
("import_shadowing", Active),
|
2014-09-06 15:52:07 -05:00
|
|
|
("advanced_slice_patterns", Active),
|
2014-12-02 16:13:12 -06:00
|
|
|
("tuple_indexing", Accepted),
|
2015-01-05 00:04:32 -06:00
|
|
|
("associated_types", Accepted),
|
2014-09-19 14:30:07 -05:00
|
|
|
("visible_private_types", Active),
|
2014-09-26 00:48:16 -05:00
|
|
|
("slicing_syntax", Active),
|
2014-07-01 11:39:41 -05:00
|
|
|
|
2014-12-02 16:13:12 -06:00
|
|
|
("if_let", Accepted),
|
|
|
|
("while_let", Accepted),
|
2014-08-26 22:00:41 -05:00
|
|
|
|
2014-12-31 22:43:46 -06:00
|
|
|
("plugin", Active),
|
|
|
|
|
2014-05-02 13:04:26 -05:00
|
|
|
// A temporary feature gate used to enable parser extensions needed
|
|
|
|
// to bootstrap fix for #5723.
|
2014-08-27 20:46:52 -05:00
|
|
|
("issue_5723_bootstrap", Accepted),
|
2014-05-02 13:04:26 -05:00
|
|
|
|
Fix orphan checking (cc #19470). (This is not a complete fix of #19470 because of the backwards compatibility feature gate.)
This is a [breaking-change]. The new rules require that, for an impl of a trait defined
in some other crate, two conditions must hold:
1. Some type must be local.
2. Every type parameter must appear "under" some local type.
Here are some examples that are legal:
```rust
struct MyStruct<T> { ... }
// Here `T` appears "under' `MyStruct`.
impl<T> Clone for MyStruct<T> { }
// Here `T` appears "under' `MyStruct` as well. Note that it also appears
// elsewhere.
impl<T> Iterator<T> for MyStruct<T> { }
```
Here is an illegal example:
```rust
// Here `U` does not appear "under" `MyStruct` or any other local type.
// We call `U` "uncovered".
impl<T,U> Iterator<U> for MyStruct<T> { }
```
There are a couple of ways to rewrite this last example so that it is
legal:
1. In some cases, the uncovered type parameter (here, `U`) should be converted
into an associated type. This is however a non-local change that requires access
to the original trait. Also, associated types are not fully baked.
2. Add `U` as a type parameter of `MyStruct`:
```rust
struct MyStruct<T,U> { ... }
impl<T,U> Iterator<U> for MyStruct<T,U> { }
```
3. Create a newtype wrapper for `U`
```rust
impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { }
```
Because associated types are not fully baked, which in the case of the
`Hash` trait makes adhering to this rule impossible, you can
temporarily disable this rule in your crate by using
`#![feature(old_orphan_check)]`. Note that the `old_orphan_check`
feature will be removed before 1.0 is released.
2014-12-26 02:30:51 -06:00
|
|
|
// A way to temporarily opt out of opt in copy. This will *never* be accepted.
|
|
|
|
("opt_out_copy", Deprecated),
|
|
|
|
|
|
|
|
// A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
|
|
|
|
("old_orphan_check", Deprecated),
|
2014-12-08 12:21:35 -06:00
|
|
|
|
2014-12-29 06:52:43 -06:00
|
|
|
// OIBIT specific features
|
|
|
|
("optin_builtin_traits", Active),
|
|
|
|
|
2013-10-02 20:10:16 -05:00
|
|
|
// These are used to test this portion of the compiler, they don't actually
|
|
|
|
// mean anything
|
|
|
|
("test_accepted_feature", Accepted),
|
|
|
|
("test_removed_feature", Removed),
|
|
|
|
];
|
|
|
|
|
|
|
|
enum Status {
|
|
|
|
/// Represents an active feature that is currently being implemented or
|
|
|
|
/// currently being considered for addition/removal.
|
|
|
|
Active,
|
|
|
|
|
Fix orphan checking (cc #19470). (This is not a complete fix of #19470 because of the backwards compatibility feature gate.)
This is a [breaking-change]. The new rules require that, for an impl of a trait defined
in some other crate, two conditions must hold:
1. Some type must be local.
2. Every type parameter must appear "under" some local type.
Here are some examples that are legal:
```rust
struct MyStruct<T> { ... }
// Here `T` appears "under' `MyStruct`.
impl<T> Clone for MyStruct<T> { }
// Here `T` appears "under' `MyStruct` as well. Note that it also appears
// elsewhere.
impl<T> Iterator<T> for MyStruct<T> { }
```
Here is an illegal example:
```rust
// Here `U` does not appear "under" `MyStruct` or any other local type.
// We call `U` "uncovered".
impl<T,U> Iterator<U> for MyStruct<T> { }
```
There are a couple of ways to rewrite this last example so that it is
legal:
1. In some cases, the uncovered type parameter (here, `U`) should be converted
into an associated type. This is however a non-local change that requires access
to the original trait. Also, associated types are not fully baked.
2. Add `U` as a type parameter of `MyStruct`:
```rust
struct MyStruct<T,U> { ... }
impl<T,U> Iterator<U> for MyStruct<T,U> { }
```
3. Create a newtype wrapper for `U`
```rust
impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { }
```
Because associated types are not fully baked, which in the case of the
`Hash` trait makes adhering to this rule impossible, you can
temporarily disable this rule in your crate by using
`#![feature(old_orphan_check)]`. Note that the `old_orphan_check`
feature will be removed before 1.0 is released.
2014-12-26 02:30:51 -06:00
|
|
|
/// Represents a feature gate that is temporarily enabling deprecated behavior.
|
|
|
|
/// This gate will never be accepted.
|
|
|
|
Deprecated,
|
|
|
|
|
2013-10-02 20:10:16 -05:00
|
|
|
/// Represents a feature which has since been removed (it was once Active)
|
|
|
|
Removed,
|
|
|
|
|
|
|
|
/// This language feature has since been Accepted (it was once Active)
|
|
|
|
Accepted,
|
|
|
|
}
|
|
|
|
|
2014-02-24 14:45:31 -06:00
|
|
|
/// A set of features to be used by later passes.
|
2015-01-03 21:54:18 -06:00
|
|
|
#[derive(Copy)]
|
2014-02-24 14:45:31 -06:00
|
|
|
pub struct Features {
|
2014-11-15 18:10:22 -06:00
|
|
|
pub unboxed_closures: bool,
|
2014-09-10 19:55:42 -05:00
|
|
|
pub rustc_diagnostic_macros: bool,
|
|
|
|
pub import_shadowing: bool,
|
2014-09-19 14:30:07 -05:00
|
|
|
pub visible_private_types: bool,
|
2014-09-26 19:14:23 -05:00
|
|
|
pub quote: bool,
|
2014-12-08 12:21:35 -06:00
|
|
|
pub opt_out_copy: bool,
|
Fix orphan checking (cc #19470). (This is not a complete fix of #19470 because of the backwards compatibility feature gate.)
This is a [breaking-change]. The new rules require that, for an impl of a trait defined
in some other crate, two conditions must hold:
1. Some type must be local.
2. Every type parameter must appear "under" some local type.
Here are some examples that are legal:
```rust
struct MyStruct<T> { ... }
// Here `T` appears "under' `MyStruct`.
impl<T> Clone for MyStruct<T> { }
// Here `T` appears "under' `MyStruct` as well. Note that it also appears
// elsewhere.
impl<T> Iterator<T> for MyStruct<T> { }
```
Here is an illegal example:
```rust
// Here `U` does not appear "under" `MyStruct` or any other local type.
// We call `U` "uncovered".
impl<T,U> Iterator<U> for MyStruct<T> { }
```
There are a couple of ways to rewrite this last example so that it is
legal:
1. In some cases, the uncovered type parameter (here, `U`) should be converted
into an associated type. This is however a non-local change that requires access
to the original trait. Also, associated types are not fully baked.
2. Add `U` as a type parameter of `MyStruct`:
```rust
struct MyStruct<T,U> { ... }
impl<T,U> Iterator<U> for MyStruct<T,U> { }
```
3. Create a newtype wrapper for `U`
```rust
impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { }
```
Because associated types are not fully baked, which in the case of the
`Hash` trait makes adhering to this rule impossible, you can
temporarily disable this rule in your crate by using
`#![feature(old_orphan_check)]`. Note that the `old_orphan_check`
feature will be removed before 1.0 is released.
2014-12-26 02:30:51 -06:00
|
|
|
pub old_orphan_check: bool,
|
2014-02-24 14:45:31 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Features {
|
|
|
|
pub fn new() -> Features {
|
|
|
|
Features {
|
2014-11-15 18:10:22 -06:00
|
|
|
unboxed_closures: false,
|
2014-09-10 19:55:42 -05:00
|
|
|
rustc_diagnostic_macros: false,
|
|
|
|
import_shadowing: false,
|
2014-09-19 14:30:07 -05:00
|
|
|
visible_private_types: false,
|
2014-09-26 19:14:23 -05:00
|
|
|
quote: false,
|
2014-12-08 12:21:35 -06:00
|
|
|
opt_out_copy: false,
|
Fix orphan checking (cc #19470). (This is not a complete fix of #19470 because of the backwards compatibility feature gate.)
This is a [breaking-change]. The new rules require that, for an impl of a trait defined
in some other crate, two conditions must hold:
1. Some type must be local.
2. Every type parameter must appear "under" some local type.
Here are some examples that are legal:
```rust
struct MyStruct<T> { ... }
// Here `T` appears "under' `MyStruct`.
impl<T> Clone for MyStruct<T> { }
// Here `T` appears "under' `MyStruct` as well. Note that it also appears
// elsewhere.
impl<T> Iterator<T> for MyStruct<T> { }
```
Here is an illegal example:
```rust
// Here `U` does not appear "under" `MyStruct` or any other local type.
// We call `U` "uncovered".
impl<T,U> Iterator<U> for MyStruct<T> { }
```
There are a couple of ways to rewrite this last example so that it is
legal:
1. In some cases, the uncovered type parameter (here, `U`) should be converted
into an associated type. This is however a non-local change that requires access
to the original trait. Also, associated types are not fully baked.
2. Add `U` as a type parameter of `MyStruct`:
```rust
struct MyStruct<T,U> { ... }
impl<T,U> Iterator<U> for MyStruct<T,U> { }
```
3. Create a newtype wrapper for `U`
```rust
impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { }
```
Because associated types are not fully baked, which in the case of the
`Hash` trait makes adhering to this rule impossible, you can
temporarily disable this rule in your crate by using
`#![feature(old_orphan_check)]`. Note that the `old_orphan_check`
feature will be removed before 1.0 is released.
2014-12-26 02:30:51 -06:00
|
|
|
old_orphan_check: false,
|
2014-02-24 14:45:31 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
struct Context<'a> {
|
|
|
|
features: Vec<&'static str>,
|
2014-09-10 19:55:42 -05:00
|
|
|
span_handler: &'a SpanHandler,
|
2014-12-23 23:44:13 -06:00
|
|
|
cm: &'a CodeMap,
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
impl<'a> Context<'a> {
|
2014-05-28 11:24:28 -05:00
|
|
|
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
|
|
|
|
if !self.has_feature(feature) {
|
2014-09-10 19:55:42 -05:00
|
|
|
self.span_handler.span_err(span, explain);
|
2014-10-17 21:39:44 -05:00
|
|
|
self.span_handler.span_help(span, format!("add #![feature({})] to the \
|
2014-09-10 19:55:42 -05:00
|
|
|
crate attributes to enable",
|
2015-01-01 18:56:28 -06:00
|
|
|
feature).index(&FullRange));
|
2014-05-28 11:24:28 -05:00
|
|
|
}
|
|
|
|
}
|
2013-10-02 20:10:16 -05:00
|
|
|
|
|
|
|
fn has_feature(&self, feature: &str) -> bool {
|
2014-11-27 14:00:50 -06:00
|
|
|
self.features.iter().any(|&n| n == feature)
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 23:44:13 -06:00
|
|
|
struct MacroVisitor<'a> {
|
|
|
|
context: &'a Context<'a>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
|
2015-01-02 15:39:05 -06:00
|
|
|
fn visit_mac(&mut self, mac: &ast::Mac) {
|
|
|
|
let ast::MacInvocTT(ref path, _, _) = mac.node;
|
2014-12-23 23:44:13 -06:00
|
|
|
let id = path.segments.last().unwrap().identifier;
|
|
|
|
|
2015-01-02 21:41:40 -06:00
|
|
|
if id == token::str_to_ident("asm") {
|
2014-12-23 23:44:13 -06:00
|
|
|
self.context.gate_feature("asm", path.span, "inline assembly is not \
|
|
|
|
stable enough for use and is subject to change");
|
|
|
|
}
|
|
|
|
|
|
|
|
else if id == token::str_to_ident("log_syntax") {
|
|
|
|
self.context.gate_feature("log_syntax", path.span, "`log_syntax!` is not \
|
|
|
|
stable enough for use and is subject to change");
|
|
|
|
}
|
|
|
|
|
|
|
|
else if id == token::str_to_ident("trace_macros") {
|
|
|
|
self.context.gate_feature("trace_macros", path.span, "`trace_macros` is not \
|
|
|
|
stable enough for use and is subject to change");
|
|
|
|
}
|
|
|
|
|
|
|
|
else if id == token::str_to_ident("concat_idents") {
|
|
|
|
self.context.gate_feature("concat_idents", path.span, "`concat_idents` is not \
|
|
|
|
stable enough for use and is subject to change");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct PostExpansionVisitor<'a> {
|
|
|
|
context: &'a Context<'a>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> PostExpansionVisitor<'a> {
|
|
|
|
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
|
|
|
|
if !self.context.cm.span_is_internal(span) {
|
|
|
|
self.context.gate_feature(feature, span, explain)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
|
2014-11-18 10:39:16 -06:00
|
|
|
fn visit_name(&mut self, sp: Span, name: ast::Name) {
|
|
|
|
if !token::get_name(name).get().is_ascii() {
|
2013-11-22 06:25:14 -06:00
|
|
|
self.gate_feature("non_ascii_idents", sp,
|
|
|
|
"non-ascii idents are not fully supported.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_view_item(&mut self, i: &ast::ViewItem) {
|
2013-10-02 20:10:16 -05:00
|
|
|
match i.node {
|
2015-01-05 00:04:55 -06:00
|
|
|
ast::ViewItemUse(..) => {}
|
2014-03-07 01:57:45 -06:00
|
|
|
ast::ViewItemExternCrate(..) => {
|
2013-12-25 12:10:33 -06:00
|
|
|
for attr in i.attrs.iter() {
|
2014-12-31 22:43:46 -06:00
|
|
|
if attr.check_name("plugin") {
|
|
|
|
self.gate_feature("plugin", attr.span,
|
|
|
|
"compiler plugins are experimental \
|
|
|
|
and possibly buggy");
|
2013-12-25 12:10:33 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_view_item(self, i)
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_item(&mut self, i: &ast::Item) {
|
2013-11-26 13:21:22 -06:00
|
|
|
for attr in i.attrs.iter() {
|
2014-11-20 19:25:27 -06:00
|
|
|
if attr.name() == "thread_local" {
|
2013-11-26 13:21:22 -06:00
|
|
|
self.gate_feature("thread_local", i.span,
|
|
|
|
"`#[thread_local]` is an experimental feature, and does not \
|
|
|
|
currently handle destructors. There is no corresponding \
|
|
|
|
`#[task_local]` mapping to the task model");
|
2014-11-20 19:25:27 -06:00
|
|
|
} else if attr.name() == "linkage" {
|
2014-11-11 19:22:41 -06:00
|
|
|
self.gate_feature("linkage", i.span,
|
|
|
|
"the `linkage` attribute is experimental \
|
|
|
|
and not portable across platforms")
|
2013-11-26 13:21:22 -06:00
|
|
|
}
|
|
|
|
}
|
2013-10-02 20:10:16 -05:00
|
|
|
match i.node {
|
2014-06-20 18:39:23 -05:00
|
|
|
ast::ItemForeignMod(ref foreign_module) => {
|
2015-01-01 18:56:28 -06:00
|
|
|
if attr::contains_name(i.attrs.index(&FullRange), "link_args") {
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
self.gate_feature("link_args", i.span,
|
|
|
|
"the `link_args` attribute is not portable \
|
|
|
|
across platforms, it is recommended to \
|
|
|
|
use `#[link(name = \"foo\")]` instead")
|
|
|
|
}
|
2014-06-20 18:39:23 -05:00
|
|
|
if foreign_module.abi == RustIntrinsic {
|
|
|
|
self.gate_feature("intrinsics",
|
|
|
|
i.span,
|
|
|
|
"intrinsics are subject to change")
|
|
|
|
}
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-25 12:10:33 -06:00
|
|
|
ast::ItemFn(..) => {
|
2015-01-01 18:56:28 -06:00
|
|
|
if attr::contains_name(i.attrs.index(&FullRange), "plugin_registrar") {
|
2014-05-24 18:16:10 -05:00
|
|
|
self.gate_feature("plugin_registrar", i.span,
|
|
|
|
"compiler plugins are experimental and possibly buggy");
|
2013-12-25 12:10:33 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-11 12:24:58 -05:00
|
|
|
ast::ItemStruct(..) => {
|
2015-01-01 18:56:28 -06:00
|
|
|
if attr::contains_name(i.attrs.index(&FullRange), "simd") {
|
2014-01-22 19:25:22 -06:00
|
|
|
self.gate_feature("simd", i.span,
|
|
|
|
"SIMD types are experimental and possibly buggy");
|
2014-02-24 01:17:02 -06:00
|
|
|
}
|
2014-01-22 19:25:22 -06:00
|
|
|
}
|
|
|
|
|
2015-01-05 21:13:38 -06:00
|
|
|
ast::ItemImpl(_, polarity, _, _, _, _) => {
|
2014-12-29 06:52:43 -06:00
|
|
|
match polarity {
|
|
|
|
ast::ImplPolarity::Negative => {
|
|
|
|
self.gate_feature("optin_builtin_traits",
|
|
|
|
i.span,
|
|
|
|
"negative trait bounds are not yet fully implemented; \
|
|
|
|
use marker types for now");
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2015-01-03 22:43:24 -06:00
|
|
|
if attr::contains_name(i.attrs.as_slice(),
|
2014-06-17 18:00:04 -05:00
|
|
|
"unsafe_destructor") {
|
|
|
|
self.gate_feature("unsafe_destructor",
|
|
|
|
i.span,
|
|
|
|
"`#[unsafe_destructor]` allows too \
|
|
|
|
many unsafe patterns and may be \
|
|
|
|
removed in the future");
|
|
|
|
}
|
2014-08-05 21:44:21 -05:00
|
|
|
|
2015-01-03 22:43:24 -06:00
|
|
|
if attr::contains_name(i.attrs.index(&FullRange),
|
Implement new orphan rule that requires that impls of remote traits meet the following two criteria:
- the self type includes some local type; and,
- type parameters in the self type must be constrained by a local type.
A type parameter is called *constrained* if it appears in some type-parameter of a local type.
Here are some examples that are accepted. In all of these examples, I
assume that `Foo` is a trait defined in another crate. If `Foo` were
defined in the local crate, then all the examples would be legal.
- `impl Foo for LocalType`
- `impl<T> Foo<T> for LocalType` -- T does not appear in Self, so it is OK
- `impl<T> Foo<T> for LocalType<T>` -- T here is constrained by LocalType
- `impl<T> Foo<T> for (LocalType<T>, T)` -- T here is constrained by LocalType
Here are some illegal examples (again, these examples assume that
`Foo` is not local to the current crate):
- `impl Foo for int` -- the Self type is not local
- `impl<T> Foo for T` -- T appears in Self unconstrained by a local type
- `impl<T> Foo for (LocalType, T)` -- T appears in Self unconstrained by a local type
This is a [breaking-change]. For the time being, you can opt out of
the new rules by placing `#[old_orphan_check]` on the trait (and
enabling the feature gate where the trait is defined). Longer term,
you should restructure your traits to avoid the problem. Usually this
means changing the order of parameters so that the "central" type
parameter is in the `Self` position.
As an example of that refactoring, consider the `BorrowFrom` trait:
```rust
pub trait BorrowFrom<Sized? Owned> for Sized? {
fn borrow_from(owned: &Owned) -> &Self;
}
```
As defined, this trait is commonly implemented for custom pointer
types, such as `Arc`. Those impls follow the pattern:
```rust
impl<T> BorrowFrom<Arc<T>> for T {...}
```
Unfortunately, this impl is illegal because the self type `T` is not
local to the current crate. Therefore, we are going to change the order of the parameters,
so that `BorrowFrom` becomes `Borrow`:
```rust
pub trait Borrow<Sized? Borrowed> for Sized? {
fn borrow_from(owned: &Self) -> &Borrowed;
}
```
Now the `Arc` impl is written:
```rust
impl<T> Borrow<T> for Arc<T> { ... }
```
This impl is legal because the self type (`Arc<T>`) is local.
2015-01-04 19:35:06 -06:00
|
|
|
"old_orphan_check") {
|
|
|
|
self.gate_feature(
|
|
|
|
"old_orphan_check",
|
|
|
|
i.span,
|
|
|
|
"the new orphan check rules will eventually be strictly enforced");
|
|
|
|
}
|
2014-06-17 18:00:04 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 20:10:16 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_item(self, i);
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
2013-10-15 00:21:54 -05:00
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
|
2015-01-01 18:56:28 -06:00
|
|
|
if attr::contains_name(i.attrs.index(&FullRange), "linkage") {
|
2014-06-20 18:39:23 -05:00
|
|
|
self.gate_feature("linkage", i.span,
|
|
|
|
"the `linkage` attribute is experimental \
|
|
|
|
and not portable across platforms")
|
2014-02-25 18:15:10 -06:00
|
|
|
}
|
2014-12-30 09:44:31 -06:00
|
|
|
|
2015-01-03 22:43:24 -06:00
|
|
|
let links_to_llvm = match attr::first_attr_value_str_by_name(i.attrs.as_slice(),
|
|
|
|
"link_name") {
|
2014-12-30 09:44:31 -06:00
|
|
|
Some(val) => val.get().starts_with("llvm."),
|
|
|
|
_ => false
|
|
|
|
};
|
|
|
|
if links_to_llvm {
|
|
|
|
self.gate_feature("link_llvm_intrinsics", i.span,
|
|
|
|
"linking to LLVM intrinsics is experimental");
|
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_foreign_item(self, i)
|
2014-02-25 18:15:10 -06:00
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_ty(&mut self, t: &ast::Ty) {
|
|
|
|
visit::walk_ty(self, t);
|
2013-10-15 00:21:54 -05:00
|
|
|
}
|
2013-12-12 01:17:54 -06:00
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_expr(&mut self, e: &ast::Expr) {
|
2013-12-12 01:17:54 -06:00
|
|
|
match e.node {
|
2014-12-18 16:47:48 -06:00
|
|
|
ast::ExprRange(..) => {
|
2014-09-26 00:48:16 -05:00
|
|
|
self.gate_feature("slicing_syntax",
|
|
|
|
e.span,
|
2014-12-18 16:47:48 -06:00
|
|
|
"range syntax is experimental");
|
2014-09-26 00:48:16 -05:00
|
|
|
}
|
2013-12-12 01:17:54 -06:00
|
|
|
_ => {}
|
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_expr(self, e);
|
2013-12-12 01:17:54 -06:00
|
|
|
}
|
2014-01-30 11:28:02 -06:00
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_attribute(&mut self, attr: &ast::Attribute) {
|
2014-09-07 12:09:06 -05:00
|
|
|
if attr::contains_name(slice::ref_slice(attr), "lang") {
|
2014-06-20 18:39:23 -05:00
|
|
|
self.gate_feature("lang_items",
|
|
|
|
attr.span,
|
|
|
|
"language items are subject to change");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_pat(&mut self, pattern: &ast::Pat) {
|
2014-09-06 15:52:07 -05:00
|
|
|
match pattern.node {
|
|
|
|
ast::PatVec(_, Some(_), ref last) if !last.is_empty() => {
|
|
|
|
self.gate_feature("advanced_slice_patterns",
|
|
|
|
pattern.span,
|
|
|
|
"multiple-element slice matches anywhere \
|
|
|
|
but at the end of a slice (e.g. \
|
|
|
|
`[0, ..xs, 0]` are experimental")
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_pat(self, pattern)
|
2014-09-06 15:52:07 -05:00
|
|
|
}
|
|
|
|
|
2014-06-20 18:39:23 -05:00
|
|
|
fn visit_fn(&mut self,
|
2014-09-09 17:54:36 -05:00
|
|
|
fn_kind: visit::FnKind<'v>,
|
|
|
|
fn_decl: &'v ast::FnDecl,
|
|
|
|
block: &'v ast::Block,
|
2014-06-20 18:39:23 -05:00
|
|
|
span: Span,
|
2014-11-15 15:04:04 -06:00
|
|
|
_node_id: NodeId) {
|
2014-09-09 17:54:36 -05:00
|
|
|
match fn_kind {
|
|
|
|
visit::FkItemFn(_, _, _, abi) if abi == RustIntrinsic => {
|
2014-06-20 18:39:23 -05:00
|
|
|
self.gate_feature("intrinsics",
|
|
|
|
span,
|
|
|
|
"intrinsics are subject to change")
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_fn(self, fn_kind, fn_decl, block, span);
|
2014-06-20 18:39:23 -05:00
|
|
|
}
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
|
2014-12-23 23:44:13 -06:00
|
|
|
fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate,
|
|
|
|
check: F)
|
|
|
|
-> (Features, Vec<Span>)
|
|
|
|
where F: FnOnce(&mut Context, &ast::Crate)
|
|
|
|
{
|
2013-10-02 20:10:16 -05:00
|
|
|
let mut cx = Context {
|
2014-03-04 12:02:49 -06:00
|
|
|
features: Vec::new(),
|
2014-09-10 19:55:42 -05:00
|
|
|
span_handler: span_handler,
|
2014-12-23 23:44:13 -06:00
|
|
|
cm: cm,
|
2013-10-02 20:10:16 -05:00
|
|
|
};
|
|
|
|
|
2014-09-10 19:55:42 -05:00
|
|
|
let mut unknown_features = Vec::new();
|
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
for attr in krate.attrs.iter() {
|
2014-05-21 00:07:42 -05:00
|
|
|
if !attr.check_name("feature") {
|
2014-01-08 12:35:15 -06:00
|
|
|
continue
|
|
|
|
}
|
2013-10-02 20:10:16 -05:00
|
|
|
|
|
|
|
match attr.meta_item_list() {
|
|
|
|
None => {
|
2014-09-10 19:55:42 -05:00
|
|
|
span_handler.span_err(attr.span, "malformed feature attribute, \
|
|
|
|
expected #![feature(...)]");
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
Some(list) => {
|
2014-09-07 12:09:06 -05:00
|
|
|
for mi in list.iter() {
|
2013-10-02 20:10:16 -05:00
|
|
|
let name = match mi.node {
|
2014-01-08 12:35:15 -06:00
|
|
|
ast::MetaWord(ref word) => (*word).clone(),
|
2013-10-02 20:10:16 -05:00
|
|
|
_ => {
|
2014-09-10 19:55:42 -05:00
|
|
|
span_handler.span_err(mi.span,
|
|
|
|
"malformed feature, expected just \
|
|
|
|
one word");
|
2013-10-02 20:10:16 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
};
|
2014-01-08 12:35:15 -06:00
|
|
|
match KNOWN_FEATURES.iter()
|
2014-11-20 19:25:27 -06:00
|
|
|
.find(|& &(n, _)| name == n) {
|
Fix orphan checking (cc #19470). (This is not a complete fix of #19470 because of the backwards compatibility feature gate.)
This is a [breaking-change]. The new rules require that, for an impl of a trait defined
in some other crate, two conditions must hold:
1. Some type must be local.
2. Every type parameter must appear "under" some local type.
Here are some examples that are legal:
```rust
struct MyStruct<T> { ... }
// Here `T` appears "under' `MyStruct`.
impl<T> Clone for MyStruct<T> { }
// Here `T` appears "under' `MyStruct` as well. Note that it also appears
// elsewhere.
impl<T> Iterator<T> for MyStruct<T> { }
```
Here is an illegal example:
```rust
// Here `U` does not appear "under" `MyStruct` or any other local type.
// We call `U` "uncovered".
impl<T,U> Iterator<U> for MyStruct<T> { }
```
There are a couple of ways to rewrite this last example so that it is
legal:
1. In some cases, the uncovered type parameter (here, `U`) should be converted
into an associated type. This is however a non-local change that requires access
to the original trait. Also, associated types are not fully baked.
2. Add `U` as a type parameter of `MyStruct`:
```rust
struct MyStruct<T,U> { ... }
impl<T,U> Iterator<U> for MyStruct<T,U> { }
```
3. Create a newtype wrapper for `U`
```rust
impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { }
```
Because associated types are not fully baked, which in the case of the
`Hash` trait makes adhering to this rule impossible, you can
temporarily disable this rule in your crate by using
`#![feature(old_orphan_check)]`. Note that the `old_orphan_check`
feature will be removed before 1.0 is released.
2014-12-26 02:30:51 -06:00
|
|
|
Some(&(name, Active)) => {
|
|
|
|
cx.features.push(name);
|
|
|
|
}
|
|
|
|
Some(&(name, Deprecated)) => {
|
|
|
|
cx.features.push(name);
|
|
|
|
span_handler.span_warn(
|
|
|
|
mi.span,
|
|
|
|
"feature is deprecated and will only be available \
|
|
|
|
for a limited time, please rewrite code that relies on it");
|
|
|
|
}
|
2013-10-02 20:10:16 -05:00
|
|
|
Some(&(_, Removed)) => {
|
2014-09-10 19:55:42 -05:00
|
|
|
span_handler.span_err(mi.span, "feature has been removed");
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
Some(&(_, Accepted)) => {
|
2014-09-10 19:55:42 -05:00
|
|
|
span_handler.span_warn(mi.span, "feature has been added to Rust, \
|
|
|
|
directive not necessary");
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
None => {
|
2014-09-10 19:55:42 -05:00
|
|
|
unknown_features.push(mi.span);
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 23:44:13 -06:00
|
|
|
check(&mut cx, krate);
|
2013-10-02 20:10:16 -05:00
|
|
|
|
2014-09-10 19:55:42 -05:00
|
|
|
(Features {
|
2014-11-15 18:10:22 -06:00
|
|
|
unboxed_closures: cx.has_feature("unboxed_closures"),
|
2014-09-10 19:55:42 -05:00
|
|
|
rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
|
|
|
|
import_shadowing: cx.has_feature("import_shadowing"),
|
2014-09-19 14:30:07 -05:00
|
|
|
visible_private_types: cx.has_feature("visible_private_types"),
|
2014-09-26 19:14:23 -05:00
|
|
|
quote: cx.has_feature("quote"),
|
2014-12-08 12:21:35 -06:00
|
|
|
opt_out_copy: cx.has_feature("opt_out_copy"),
|
Fix orphan checking (cc #19470). (This is not a complete fix of #19470 because of the backwards compatibility feature gate.)
This is a [breaking-change]. The new rules require that, for an impl of a trait defined
in some other crate, two conditions must hold:
1. Some type must be local.
2. Every type parameter must appear "under" some local type.
Here are some examples that are legal:
```rust
struct MyStruct<T> { ... }
// Here `T` appears "under' `MyStruct`.
impl<T> Clone for MyStruct<T> { }
// Here `T` appears "under' `MyStruct` as well. Note that it also appears
// elsewhere.
impl<T> Iterator<T> for MyStruct<T> { }
```
Here is an illegal example:
```rust
// Here `U` does not appear "under" `MyStruct` or any other local type.
// We call `U` "uncovered".
impl<T,U> Iterator<U> for MyStruct<T> { }
```
There are a couple of ways to rewrite this last example so that it is
legal:
1. In some cases, the uncovered type parameter (here, `U`) should be converted
into an associated type. This is however a non-local change that requires access
to the original trait. Also, associated types are not fully baked.
2. Add `U` as a type parameter of `MyStruct`:
```rust
struct MyStruct<T,U> { ... }
impl<T,U> Iterator<U> for MyStruct<T,U> { }
```
3. Create a newtype wrapper for `U`
```rust
impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { }
```
Because associated types are not fully baked, which in the case of the
`Hash` trait makes adhering to this rule impossible, you can
temporarily disable this rule in your crate by using
`#![feature(old_orphan_check)]`. Note that the `old_orphan_check`
feature will be removed before 1.0 is released.
2014-12-26 02:30:51 -06:00
|
|
|
old_orphan_check: cx.has_feature("old_orphan_check"),
|
2014-09-10 19:55:42 -05:00
|
|
|
},
|
|
|
|
unknown_features)
|
2013-10-02 20:10:16 -05:00
|
|
|
}
|
2014-12-23 23:44:13 -06:00
|
|
|
|
|
|
|
pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
|
|
|
|
-> (Features, Vec<Span>) {
|
|
|
|
check_crate_inner(cm, span_handler, krate,
|
|
|
|
|ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
|
|
|
|
-> (Features, Vec<Span>) {
|
|
|
|
check_crate_inner(cm, span_handler, krate,
|
|
|
|
|ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx },
|
|
|
|
krate))
|
|
|
|
}
|