From 58d2c7909f9f9310971fcd517fc895cb878b74c3 Mon Sep 17 00:00:00 2001 From: Thomas Wickham Date: Thu, 14 Jan 2016 16:06:53 +0100 Subject: [PATCH 1/9] Doc:std::convert explicitely list generic impls Also add a note about the necessary simplicity of the conversion. Related issue: #29349 --- src/libcore/convert.rs | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index b02b2a06b75..a0021d2adda 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -17,6 +17,26 @@ //! Like many traits, these are often used as bounds for generic functions, to //! support arguments of multiple types. //! +//! - Use `as` for reference-to-reference conversions +//! - Use `into` when you want to consume the value +//! - `from` is the more flexible way, which can convert values and references +//! +//! As a library writer, you should prefer implementing `From` rather than +//! `Into`, as `From` is more flexible (you can't `Into` a reference, where +//! you can impl `From` for a reference). `From` is also used for generic +//! implementations. +//! +//! **Note:** these traits are for trivial conversion. **They must not fail**. If +//! they can fail, use a dedicated method which return an `Option` or +//! a `Result`. +//! +//! # Generic impl +//! +//! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference +//! - `From for T` implies `Into for U` +//! - `From` and `Into` are reflexive, which means that all types can `into()` +//! themselve and `from()` themselve +//! //! See each trait for usage examples. #![stable(feature = "rust1", since = "1.0.0")] @@ -30,6 +50,10 @@ use marker::Sized; /// /// [book]: ../../book/borrow-and-asref.html /// +/// **Note:** these traits are for trivial conversion. **They must not fail**. If +/// they can fail, use a dedicated method which return an `Option` or +/// a `Result`. +/// /// # Examples /// /// Both `String` and `&str` implement `AsRef`: @@ -45,6 +69,12 @@ use marker::Sized; /// let s = "hello".to_string(); /// is_hello(s); /// ``` +/// +/// # Generic Impls +/// +/// - `AsRef` auto-dereference if the inner type is a reference or a mutable +/// reference +/// #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRef { /// Performs the conversion. @@ -53,6 +83,16 @@ pub trait AsRef { } /// A cheap, mutable reference-to-mutable reference conversion. +/// +/// **Note:** these traits are for trivial conversion. **They must not fail**. If +/// they can fail, use a dedicated method which return an `Option` or +/// a `Result`. +/// +/// # Generic Impls +/// +/// - `AsMut` auto-dereference if the inner type is a reference or a mutable +/// reference +/// #[stable(feature = "rust1", since = "1.0.0")] pub trait AsMut { /// Performs the conversion. @@ -62,6 +102,10 @@ pub trait AsMut { /// A conversion that consumes `self`, which may or may not be expensive. /// +/// **Note:** these traits are for trivial conversion. **They must not fail**. If +/// they can fail, use a dedicated method which return an `Option` or +/// a `Result`. +/// /// # Examples /// /// `String` implements `Into>`: @@ -75,6 +119,12 @@ pub trait AsMut { /// let s = "hello".to_string(); /// is_hello(s); /// ``` +/// +/// #Generic Impls +/// +/// - `From for U` implies `Into for T` +/// - `into()` is reflexive, which means that `Into for T` is implemented +/// #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. @@ -84,6 +134,10 @@ pub trait Into: Sized { /// Construct `Self` via a conversion. /// +/// **Note:** these traits are for trivial conversion. **They must not fail**. If +/// they can fail, use a dedicated method which return an `Option` or +/// a `Result`. +/// /// # Examples /// /// `String` implements `From<&str>`: @@ -94,6 +148,11 @@ pub trait Into: Sized { /// /// assert_eq!(string, other_string); /// ``` +/// # Generic impls +/// +/// - `From for U` implies `Into for T` +/// - `from()` is reflexive, which means that `From for T` is implemented +/// #[stable(feature = "rust1", since = "1.0.0")] pub trait From: Sized { /// Performs the conversion. From 6cda8e4eaac843471dd33d93d9d5cc892d29cc4c Mon Sep 17 00:00:00 2001 From: Thomas Wickham Date: Fri, 15 Jan 2016 01:24:33 +0100 Subject: [PATCH 2/9] Doc:std::convert: be more specific + typo --- src/libcore/convert.rs | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index a0021d2adda..f67bfe34e8f 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -22,20 +22,18 @@ //! - `from` is the more flexible way, which can convert values and references //! //! As a library writer, you should prefer implementing `From` rather than -//! `Into`, as `From` is more flexible (you can't `Into` a reference, where -//! you can impl `From` for a reference). `From` is also used for generic -//! implementations. +//! `Into`, as `From` provides greater flexibility and offer the equivalent `Into` +//! implementation for free thanks to a blanket implementation in the standard library. //! -//! **Note:** these traits are for trivial conversion. **They must not fail**. If -//! they can fail, use a dedicated method which return an `Option` or -//! a `Result`. +//! **Note: these traits must not fail**. If the conversion can fail, you must use a dedicated +//! method which return an `Option` or a `Result`. //! //! # Generic impl //! //! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference //! - `From for T` implies `Into for U` //! - `From` and `Into` are reflexive, which means that all types can `into()` -//! themselve and `from()` themselve +//! themselves and `from()` themselves //! //! See each trait for usage examples. @@ -50,9 +48,8 @@ use marker::Sized; /// /// [book]: ../../book/borrow-and-asref.html /// -/// **Note:** these traits are for trivial conversion. **They must not fail**. If -/// they can fail, use a dedicated method which return an `Option` or -/// a `Result`. +/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which +/// return an `Option` or a `Result`. /// /// # Examples /// @@ -73,7 +70,7 @@ use marker::Sized; /// # Generic Impls /// /// - `AsRef` auto-dereference if the inner type is a reference or a mutable -/// reference +/// reference (eg: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`) /// #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRef { @@ -84,14 +81,13 @@ pub trait AsRef { /// A cheap, mutable reference-to-mutable reference conversion. /// -/// **Note:** these traits are for trivial conversion. **They must not fail**. If -/// they can fail, use a dedicated method which return an `Option` or -/// a `Result`. +/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which +/// return an `Option` or a `Result`. /// /// # Generic Impls /// /// - `AsMut` auto-dereference if the inner type is a reference or a mutable -/// reference +/// reference (eg: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`) /// #[stable(feature = "rust1", since = "1.0.0")] pub trait AsMut { @@ -102,9 +98,12 @@ pub trait AsMut { /// A conversion that consumes `self`, which may or may not be expensive. /// -/// **Note:** these traits are for trivial conversion. **They must not fail**. If -/// they can fail, use a dedicated method which return an `Option` or -/// a `Result`. +/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which +/// return an `Option` or a `Result`. +/// +/// Library writer should not implement directly this trait, but should prefer the implementation +/// of the `From` trait, which offer greater flexibility and provide the equivalent `Into` +/// implementation for free thanks to a blanket implementation in the standard library. /// /// # Examples /// @@ -134,9 +133,8 @@ pub trait Into: Sized { /// Construct `Self` via a conversion. /// -/// **Note:** these traits are for trivial conversion. **They must not fail**. If -/// they can fail, use a dedicated method which return an `Option` or -/// a `Result`. +/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which +/// return an `Option` or a `Result`. /// /// # Examples /// From 641267e4c20edda3e7b96c58547542e245af5553 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 27 Jan 2016 04:50:04 +0300 Subject: [PATCH 3/9] Allow #[repr(i32)] for univariant enum ``` #[repr(i32)] enum Univariant { X = 17 } ``` Fixes #10292 --- src/librustc_typeck/check/mod.rs | 11 ++---- src/librustc_typeck/diagnostics.rs | 7 ---- src/test/run-pass/enum-univariant-repr.rs | 47 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 src/test/run-pass/enum-univariant-repr.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a8697f45d91..e04c6a6cc38 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4250,14 +4250,9 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let def_id = ccx.tcx.map.local_def_id(id); let hint = *ccx.tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny); - if hint != attr::ReprAny && vs.len() <= 1 { - if vs.len() == 1 { - span_err!(ccx.tcx.sess, sp, E0083, - "unsupported representation for univariant enum"); - } else { - span_err!(ccx.tcx.sess, sp, E0084, - "unsupported representation for zero-variant enum"); - }; + if hint != attr::ReprAny && vs.is_empty() { + span_err!(ccx.tcx.sess, sp, E0084, + "unsupported representation for zero-variant enum"); } do_check(ccx, vs, id, hint); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 8f7692c7945..df09cd26134 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1062,13 +1062,6 @@ Note also that without a representation manually defined, the compiler will optimize by using the smallest integer type possible. "##, -E0083: r##" -At present, it's not possible to define a custom representation for an enum with -a single variant. As a workaround you can add a `Dummy` variant. - -See: https://github.com/rust-lang/rust/issues/10292 -"##, - E0084: r##" It is impossible to define an integer type to be used to represent zero-variant enum values because there are no zero-variant enum values. There is no way to diff --git a/src/test/run-pass/enum-univariant-repr.rs b/src/test/run-pass/enum-univariant-repr.rs new file mode 100644 index 00000000000..ef4cc60bf0d --- /dev/null +++ b/src/test/run-pass/enum-univariant-repr.rs @@ -0,0 +1,47 @@ +// Copyright 2016 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 std::mem; + +// Univariant C-like enum +#[repr(i32)] +enum Univariant { + X = 17 +} + +#[repr(u16)] +enum UnivariantWithoutDescr { + Y +} + +pub fn main() { + { + assert_eq!(4, mem::size_of::()); + assert_eq!(17, Univariant::X as i32); + + let enums: &[Univariant] = + &[Univariant::X, Univariant::X, Univariant::X]; + let ints: &[i32] = unsafe { mem::transmute(enums) }; + // check it has the same memory layout as i32 + assert_eq!(&[17, 17, 17], ints); + } + + { + assert_eq!(2, mem::size_of::()); + let descr = UnivariantWithoutDescr::Y as u16; + + let enums: &[UnivariantWithoutDescr] = + &[UnivariantWithoutDescr::Y, UnivariantWithoutDescr::Y, UnivariantWithoutDescr::Y]; + let ints: &[u16] = unsafe { mem::transmute(enums) }; + // check it has the same memory layout as u16 + assert_eq!(&[descr, descr, descr], ints); + } +} From 0316013b49614aef084a9b2357a3bd335dcc3a7b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 29 Jan 2016 23:44:46 -0800 Subject: [PATCH 4/9] rustc: Set MIPS cpu/features in the compiler Currently any compilation to MIPS spits out the warning: 'generic' is not a recognized processor for this target (ignoring processor) Doesn't make for a great user experience! We don't encounter this in the normal bootstrap because the cpu/feature set are set by the makefiles. Instead let's just propagate these to the defaults for the entire target all the time (still overridable from the command line) and prevent warnings from being emitted by default. --- mk/cfg/mips-unknown-linux-gnu.mk | 2 +- mk/cfg/mipsel-unknown-linux-gnu.mk | 2 +- src/librustc_back/target/mips_unknown_linux_gnu.rs | 8 ++++++-- src/librustc_back/target/mipsel_unknown_linux_gnu.rs | 8 ++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mk/cfg/mips-unknown-linux-gnu.mk b/mk/cfg/mips-unknown-linux-gnu.mk index 65b08774d49..9e7042befa9 100644 --- a/mk/cfg/mips-unknown-linux-gnu.mk +++ b/mk/cfg/mips-unknown-linux-gnu.mk @@ -20,5 +20,5 @@ CFG_UNIXY_mips-unknown-linux-gnu := 1 CFG_LDPATH_mips-unknown-linux-gnu := CFG_RUN_mips-unknown-linux-gnu= CFG_RUN_TARG_mips-unknown-linux-gnu= -RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2" -C soft-float +RUSTC_FLAGS_mips-unknown-linux-gnu := CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu diff --git a/mk/cfg/mipsel-unknown-linux-gnu.mk b/mk/cfg/mipsel-unknown-linux-gnu.mk index 4dadfc275d3..f15a086b64e 100644 --- a/mk/cfg/mipsel-unknown-linux-gnu.mk +++ b/mk/cfg/mipsel-unknown-linux-gnu.mk @@ -20,5 +20,5 @@ CFG_UNIXY_mipsel-unknown-linux-gnu := 1 CFG_LDPATH_mipsel-unknown-linux-gnu := CFG_RUN_mipsel-unknown-linux-gnu= CFG_RUN_TARG_mipsel-unknown-linux-gnu= -RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32" +RUSTC_FLAGS_mipsel-unknown-linux-gnu := CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs index 357499c48ec..01f2de4a269 100644 --- a/src/librustc_back/target/mips_unknown_linux_gnu.rs +++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::Target; +use target::{Target, TargetOptions}; pub fn target() -> Target { Target { @@ -19,6 +19,10 @@ pub fn target() -> Target { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), - options: super::linux_base::opts() + options: TargetOptions { + cpu: "mips32r2".to_string(), + features: "+mips32r2,+soft-float".to_string(), + ..super::linux_base::opts() + }, } } diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs index 3d0088add0d..e9eef72e8c3 100644 --- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs +++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::Target; +use target::{Target, TargetOptions}; pub fn target() -> Target { Target { @@ -20,6 +20,10 @@ pub fn target() -> Target { target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), - options: super::linux_base::opts() + options: TargetOptions { + cpu: "mips32".to_string(), + features: "+mips32".to_string(), + ..super::linux_base::opts() + }, } } From 7a69ee0c4806d30bbda5cc0277f3d0f38c3266c8 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 18 Dec 2015 10:10:31 +0000 Subject: [PATCH 5/9] Revert PR #30324, fixing a bug in which a public glob import can make preceding imports public (fixes #30159). --- src/librustc_resolve/resolve_imports.rs | 3 --- src/test/compile-fail/shadowed-use-visibility.rs | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 07f6a0f9549..50537a6b936 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -798,9 +798,6 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { dest_import_resolution.is_public = is_public; self.add_export(module_, name, &dest_import_resolution); } - } else { - // FIXME #30159: This is required for backwards compatability. - dest_import_resolution.is_public |= is_public; } self.check_for_conflicts_between_imports_and_items(module_, diff --git a/src/test/compile-fail/shadowed-use-visibility.rs b/src/test/compile-fail/shadowed-use-visibility.rs index bfc6a4ec9b8..1bf7f393384 100644 --- a/src/test/compile-fail/shadowed-use-visibility.rs +++ b/src/test/compile-fail/shadowed-use-visibility.rs @@ -17,6 +17,10 @@ mod foo { mod bar { use foo::bar::f as g; //~ ERROR unresolved import + + use foo as f; + pub use foo::*; } +use bar::f::f; //~ ERROR unresolved import fn main() {} From e768fa729fb21549a39744bd3bfad03643cc10da Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 29 Jan 2016 22:21:36 +0000 Subject: [PATCH 6/9] Refactor away the field Module::external_module_children in resolve --- src/librustc_resolve/build_reduced_graph.rs | 36 ++++-- src/librustc_resolve/lib.rs | 104 ++++++------------ src/librustc_resolve/resolve_imports.rs | 46 +++----- .../resolve-conflict-item-vs-extern-crate.rs | 3 +- 4 files changed, 75 insertions(+), 114 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a1d866fc48b..8f4913f0420 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -107,20 +107,37 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. fn define>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) { - let name_binding = def.to_name_binding(); - let span = name_binding.span.unwrap_or(DUMMY_SP); - self.check_for_conflicts_between_external_crates_and_items(&parent, name, span); - if !parent.try_define_child(name, ns, name_binding) { + let binding = def.to_name_binding(); + let old_binding = match parent.try_define_child(name, ns, binding.clone()) { + Some(old_binding) => old_binding, + None => return, + }; + + let span = binding.span.unwrap_or(DUMMY_SP); + if !old_binding.is_extern_crate() && !binding.is_extern_crate() { // Record an error here by looking up the namespace that had the duplicate let ns_str = match ns { TypeNS => "type or module", ValueNS => "value" }; let resolution_error = ResolutionError::DuplicateDefinition(ns_str, name); let mut err = resolve_struct_error(self, span, resolution_error); - if let Some(sp) = parent.children.borrow().get(&(name, ns)).unwrap().span { + if let Some(sp) = old_binding.span { let note = format!("first definition of {} `{}` here", ns_str, name); err.span_note(sp, ¬e); } err.emit(); + } else if old_binding.is_extern_crate() && binding.is_extern_crate() { + span_err!(self.session, + span, + E0259, + "an external crate named `{}` has already been imported into this module", + name); + } else { + span_err!(self.session, + span, + E0260, + "the name `{}` conflicts with an external crate \ + that has been imported into this module", + name); } } @@ -289,14 +306,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.external_exports.insert(def_id); let parent_link = ModuleParentLink(parent, name); let def = Def::Mod(def_id); - let external_module = self.new_module(parent_link, Some(def), false, true); + let external_module = self.new_extern_crate_module(parent_link, def); + self.define(parent, name, TypeNS, (external_module, sp)); - debug!("(build reduced graph for item) found extern `{}`", - module_to_string(&*external_module)); - self.check_for_conflicts_for_external_crate(parent, name, sp); - parent.external_module_children - .borrow_mut() - .insert(name, external_module); self.build_reduced_graph_for_external_crate(&external_module); } parent diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6c78f98c0cb..6f35d10c994 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -120,8 +120,6 @@ enum SuggestionType { } pub enum ResolutionError<'a> { - /// error E0260: name conflicts with an extern crate - NameConflictsWithExternCrate(Name), /// error E0401: can't use type parameters from outer function TypeParametersFromOuterFunction, /// error E0402: cannot use an outer type parameter in this context @@ -228,14 +226,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, } match resolution_error { - ResolutionError::NameConflictsWithExternCrate(name) => { - struct_span_err!(resolver.session, - span, - E0260, - "the name `{}` conflicts with an external crate \ - that has been imported into this module", - name) - } ResolutionError::TypeParametersFromOuterFunction => { struct_span_err!(resolver.session, span, @@ -801,14 +791,11 @@ pub struct ModuleS<'a> { parent_link: ParentLink<'a>, def: Cell>, is_public: bool, + is_extern_crate: bool, children: RefCell>>, imports: RefCell>, - // The external module children of this node that were declared with - // `extern crate`. - external_module_children: RefCell>>, - // The anonymous children of this node. Anonymous children are pseudo- // modules that are implicitly created around items contained within // blocks. @@ -854,9 +841,9 @@ impl<'a> ModuleS<'a> { parent_link: parent_link, def: Cell::new(def), is_public: is_public, + is_extern_crate: false, children: RefCell::new(HashMap::new()), imports: RefCell::new(Vec::new()), - external_module_children: RefCell::new(HashMap::new()), anonymous_children: RefCell::new(NodeMap()), import_resolutions: RefCell::new(HashMap::new()), glob_count: Cell::new(0), @@ -871,10 +858,21 @@ impl<'a> ModuleS<'a> { self.children.borrow().get(&(name, ns)).cloned() } - fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>) -> bool { + // If the name is not yet defined, define the name and return None. + // Otherwise, return the existing definition. + fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>) + -> Option> { match self.children.borrow_mut().entry((name, ns)) { - hash_map::Entry::Vacant(entry) => { entry.insert(binding); true } - hash_map::Entry::Occupied(_) => false, + hash_map::Entry::Vacant(entry) => { entry.insert(binding); None } + hash_map::Entry::Occupied(entry) => { Some(entry.get().clone()) }, + } + } + + fn for_each_local_child)>(&self, mut f: F) { + for (&(name, ns), name_binding) in self.children.borrow().iter() { + if !name_binding.is_extern_crate() { + f(name, ns, name_binding) + } } } @@ -1005,6 +1003,10 @@ impl<'a> NameBinding<'a> { let def = self.def().unwrap(); (def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) })) } + + fn is_extern_crate(&self) -> bool { + self.module().map(|module| module.is_extern_crate).unwrap_or(false) + } } /// Interns the names of the primitive types. @@ -1184,6 +1186,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.arenas.modules.alloc(ModuleS::new(parent_link, def, external, is_public)) } + fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def) -> Module<'a> { + let mut module = ModuleS::new(parent_link, Some(def), false, true); + module.is_extern_crate = true; + self.arenas.modules.alloc(module) + } + fn get_ribs<'b>(&'b mut self, ns: Namespace) -> &'b mut Vec> { match ns { ValueNS => &mut self.value_ribs, TypeNS => &mut self.type_ribs } } @@ -1211,32 +1219,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - /// Check that an external crate doesn't collide with items or other external crates. - fn check_for_conflicts_for_external_crate(&self, module: Module<'a>, name: Name, span: Span) { - if module.external_module_children.borrow().contains_key(&name) { - span_err!(self.session, - span, - E0259, - "an external crate named `{}` has already been imported into this module", - name); - } - if let Some(name_binding) = module.get_child(name, TypeNS) { - resolve_error(self, - name_binding.span.unwrap_or(codemap::DUMMY_SP), - ResolutionError::NameConflictsWithExternCrate(name)); - } - } - - /// Checks that the names of items don't collide with external crates. - fn check_for_conflicts_between_external_crates_and_items(&self, - module: Module<'a>, - name: Name, - span: Span) { - if module.external_module_children.borrow().contains_key(&name) { - resolve_error(self, span, ResolutionError::NameConflictsWithExternCrate(name)); - } - } - /// Resolves the given module path from the given root `module_`. fn resolve_module_path_from_root(&mut self, module_: Module<'a>, @@ -1245,11 +1227,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span: Span, lp: LastPrivate) -> ResolveResult<(Module<'a>, LastPrivate)> { - fn search_parent_externals<'a>(needle: Name, module: Module<'a>) - -> Option> { - match module.external_module_children.borrow().get(&needle) { - Some(_) => Some(module), - None => match module.parent_link { + fn search_parent_externals<'a>(needle: Name, module: Module<'a>) -> Option> { + match module.get_child(needle, TypeNS) { + Some(ref binding) if binding.is_extern_crate() => Some(module), + _ => match module.parent_link { ModuleParentLink(ref parent, _) => { search_parent_externals(needle, parent) } @@ -1480,17 +1461,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - // Search for external modules. - if namespace == TypeNS { - let children = module_.external_module_children.borrow(); - if let Some(module) = children.get(&name) { - let name_binding = NameBinding::create_from_module(module, None); - debug!("lower name bindings succeeded"); - return Success((Target::new(module_, name_binding, Shadowable::Never), - false)); - } - } - // Finally, proceed up the scope chain looking for parent modules. let mut search_module = module_; loop { @@ -1684,16 +1654,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(..) | None => {} // Continue. } - // Finally, search through external children. - if namespace == TypeNS { - let children = module_.external_module_children.borrow(); - if let Some(module) = children.get(&name) { - let name_binding = NameBinding::create_from_module(module, None); - return Success((Target::new(module_, name_binding, Shadowable::Never), - false)); - } - } - // We're out of luck. debug!("(resolving name in module) failed to resolve `{}`", name); return Failed(None); @@ -1712,7 +1672,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Descend into children and anonymous children. build_reduced_graph::populate_module_if_necessary(self, &module_); - for (_, child_node) in module_.children.borrow().iter() { + module_.for_each_local_child(|_, _, child_node| { match child_node.module() { None => { // Continue. @@ -1721,7 +1681,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_unresolved_imports(child_module); } } - } + }); for (_, module_) in module_.anonymous_children.borrow().iter() { self.report_unresolved_imports(module_); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 07f6a0f9549..53f25cbb304 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -213,7 +213,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { self.resolver.current_module = orig_module; build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); - for (_, child_node) in module_.children.borrow().iter() { + module_.for_each_local_child(|_, _, child_node| { match child_node.module() { None => { // Nothing to do. @@ -222,7 +222,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { errors.extend(self.resolve_imports_for_module_subtree(child_module)); } } - } + }); for (_, child_module) in module_.anonymous_children.borrow().iter() { errors.extend(self.resolve_imports_for_module_subtree(child_module)); @@ -386,18 +386,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { -> (ResolveResult<(Module<'b>, NameBinding<'b>)>, bool) { build_reduced_graph::populate_module_if_necessary(self.resolver, module); if let Some(name_binding) = module.get_child(name, ns) { - return (Success((module, name_binding)), false); - } - - if ns == TypeNS { - if let Some(extern_crate) = module.external_module_children.borrow().get(&name) { + if name_binding.is_extern_crate() { // track the extern crate as used. - if let Some(DefId{ krate: kid, .. }) = extern_crate.def_id() { - self.resolver.used_crates.insert(kid); + if let Some(DefId { krate, .. }) = name_binding.module().unwrap().def_id() { + self.resolver.used_crates.insert(krate); } - let name_binding = NameBinding::create_from_module(extern_crate, None); - return (Success((module, name_binding)), false); } + return (Success((module, name_binding)), false) } // If there is an unresolved glob at this point in the containing module, bail out. @@ -725,13 +720,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // Add all children from the containing module. build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module); - for (&name, name_binding) in target_module.children.borrow().iter() { + target_module.for_each_local_child(|name, ns, name_binding| { self.merge_import_resolution(module_, target_module, import_directive, - name, + (name, ns), name_binding.clone()); - } + }); // Record the destination of this import if let Some(did) = target_module.def_id() { @@ -881,21 +876,6 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { import: &ImportResolution<'b>, import_span: Span, (name, ns): (Name, Namespace)) { - // First, check for conflicts between imports and `extern crate`s. - if ns == TypeNS { - if module.external_module_children.borrow().contains_key(&name) { - match import.target { - Some(ref target) if target.shadowable != Shadowable::Always => { - let msg = format!("import `{0}` conflicts with imported crate \ - in this module (maybe you meant `use {0}::*`?)", - name); - span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]); - } - Some(_) | None => {} - } - } - } - // Check for item conflicts. let name_binding = match module.get_child(name, ns) { None => { @@ -924,6 +904,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } else { match import.target { Some(ref target) if target.shadowable != Shadowable::Always => { + if name_binding.is_extern_crate() { + let msg = format!("import `{0}` conflicts with imported crate \ + in this module (maybe you meant `use {0}::*`?)", + name); + span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]); + return; + } + let (what, note) = match name_binding.module() { Some(ref module) if module.is_normal() => ("existing submodule", "note conflicting module here"), diff --git a/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs index e685353592f..07f80cf03d1 100644 --- a/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn std() {} //~ ERROR the name `std` conflicts with an external crate +fn std() {} +mod std {} //~ ERROR the name `std` conflicts with an external crate fn main() { } From a0cd46554d850d99f985be911215ac41978533a2 Mon Sep 17 00:00:00 2001 From: Thomas Wickham Date: Sun, 31 Jan 2016 12:26:15 +0100 Subject: [PATCH 7/9] Doc:std::convert: disambiguate traits and keywords --- src/libcore/convert.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index f67bfe34e8f..c207ad16595 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -17,13 +17,13 @@ //! Like many traits, these are often used as bounds for generic functions, to //! support arguments of multiple types. //! -//! - Use `as` for reference-to-reference conversions -//! - Use `into` when you want to consume the value -//! - `from` is the more flexible way, which can convert values and references +//! - Impl the `As*` traits for reference-to-reference conversions +//! - Impl the `Into` trait when you want to consume the value in the conversion +//! - The `From` trait is the most flexible, usefull for values _and_ references conversions //! //! As a library writer, you should prefer implementing `From` rather than //! `Into`, as `From` provides greater flexibility and offer the equivalent `Into` -//! implementation for free thanks to a blanket implementation in the standard library. +//! implementation for free, thanks to a blanket implementation in the standard library. //! //! **Note: these traits must not fail**. If the conversion can fail, you must use a dedicated //! method which return an `Option` or a `Result`. @@ -103,7 +103,7 @@ pub trait AsMut { /// /// Library writer should not implement directly this trait, but should prefer the implementation /// of the `From` trait, which offer greater flexibility and provide the equivalent `Into` -/// implementation for free thanks to a blanket implementation in the standard library. +/// implementation for free, thanks to a blanket implementation in the standard library. /// /// # Examples /// @@ -119,7 +119,7 @@ pub trait AsMut { /// is_hello(s); /// ``` /// -/// #Generic Impls +/// # Generic Impls /// /// - `From for U` implies `Into for T` /// - `into()` is reflexive, which means that `Into for T` is implemented From e1be504068d827e4a8e42bf63a355fea9484ef5d Mon Sep 17 00:00:00 2001 From: Daniel Campbell Date: Fri, 29 Jan 2016 19:33:14 +1300 Subject: [PATCH 8/9] Spans now derive equality --- src/librustc_resolve/check_unused.rs | 2 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/codemap.rs | 25 ++++++++++++------------- src/libsyntax/errors/emitter.rs | 8 +++----- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 7f740f9c033..178e2a4d1bc 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -117,7 +117,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { // whether they're used or not. Also ignore imports with a dummy span // because this means that they were generated in some fashion by the // compiler and we don't need to consider them. - if item.vis == hir::Public || item.span == DUMMY_SP { + if item.vis == hir::Public || item.span.source_equal(&DUMMY_SP) { return; } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index ba4d1e2193e..03dc25e1b3c 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -356,7 +356,7 @@ pub fn pat_is_ident(pat: P) -> bool { // since I'm using this to replace ==, it seems appropriate // to compare the span, global, etc. fields as well. pub fn path_name_eq(a : &ast::Path, b : &ast::Path) -> bool { - (a.span == b.span) + (a.span.source_equal(&b.span)) && (a.global == b.global) && (segments_name_eq(&a.segments[..], &b.segments[..])) } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index ca01623fef9..9557310f318 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -123,7 +123,7 @@ impl Sub for CharPos { /// able to use many of the functions on spans in codemap and you cannot assume /// that the length of the span = hi - lo; there may be space in the BytePos /// range between files. -#[derive(Clone, Copy, Hash)] +#[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct Span { pub lo: BytePos, pub hi: BytePos, @@ -151,13 +151,21 @@ pub const COMMAND_LINE_SP: Span = Span { lo: BytePos(0), impl Span { /// Returns `self` if `self` is not the dummy span, and `other` otherwise. pub fn substitute_dummy(self, other: Span) -> Span { - if self == DUMMY_SP { other } else { self } + if self.source_equal(&DUMMY_SP) { other } else { self } } pub fn contains(self, other: Span) -> bool { self.lo <= other.lo && other.hi <= self.hi } + /// Return true if the spans are equal with regards to the source text. + /// + /// Use this instead of `==` when either span could be generated code, + /// and you only care that they point to the same bytes of source text. + pub fn source_equal(&self, other: &Span) -> bool { + self.lo == other.lo && self.hi == other.hi + } + /// Returns `Some(span)`, a union of `self` and `other`, on overlap. pub fn merge(self, other: Span) -> Option { if self.expn_id != other.expn_id { @@ -192,15 +200,6 @@ pub struct Spanned { pub span: Span, } -impl PartialEq for Span { - fn eq(&self, other: &Span) -> bool { - return (*self).lo == (*other).lo && (*self).hi == (*other).hi; - } - fn ne(&self, other: &Span) -> bool { !(*self).eq(other) } -} - -impl Eq for Span {} - impl Encodable for Span { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_struct("Span", 2, |s| { @@ -940,7 +939,7 @@ impl CodeMap { } pub fn span_to_string(&self, sp: Span) -> String { - if self.files.borrow().is_empty() && sp == DUMMY_SP { + if self.files.borrow().is_empty() && sp.source_equal(&DUMMY_SP) { return "no-location".to_string(); } @@ -1307,7 +1306,7 @@ impl CodeMap { expninfo.map_or(/* hit the top level */ true, |info| { let span_comes_from_this_expansion = - info.callee.span.map_or(span == info.call_site, |mac_span| { + info.callee.span.map_or(span.source_equal(&info.call_site), |mac_span| { mac_span.contains(span) }); diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs index c1239bfd66d..7e0e17423de 100644 --- a/src/libsyntax/errors/emitter.rs +++ b/src/libsyntax/errors/emitter.rs @@ -10,7 +10,7 @@ use self::Destination::*; -use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, DUMMY_SP, Pos, Span, MultiSpan}; +use codemap::{self, COMMAND_LINE_SP, DUMMY_SP, Pos, Span, MultiSpan}; use diagnostics; use errors::{Level, RenderSpan, CodeSuggestion, DiagnosticBuilder}; @@ -175,9 +175,7 @@ impl EmitterWriter { let msp = rsp.span(); let bounds = msp.to_span_bounds(); - // We cannot check equality directly with COMMAND_LINE_SP - // since PartialEq is manually implemented to ignore the ExpnId - let ss = if bounds.expn_id == COMMAND_LINE_EXPN { + let ss = if bounds == COMMAND_LINE_SP { "".to_string() } else if let EndSpan(_) = *rsp { let span_end = Span { lo: bounds.hi, hi: bounds.hi, expn_id: bounds.expn_id}; @@ -606,7 +604,7 @@ impl EmitterWriter { }; // Don't print recursive invocations - if span != last_span { + if !span.source_equal(&last_span) { let mut diag_string = macro_decl_name; if let Some(def_site_span) = def_site_span { diag_string.push_str(&format!(" (defined in {})", From d03712977d7c913044f2b863269c4491d7fa7c36 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 13 Dec 2015 12:19:27 -0500 Subject: [PATCH 9/9] mk: fix some undefined variable warnings Some of this is scary stuff. Probably time to lint against this. Found with `make --warn-undefined-variables`. --- mk/cfg/aarch64-linux-android.mk | 1 - mk/cfg/x86_64-apple-ios.mk | 2 +- mk/cfg/x86_64-unknown-bitrig.mk | 2 +- mk/crates.mk | 6 +++--- mk/docs.mk | 4 ++-- mk/grammar.mk | 4 ++-- mk/host.mk | 2 +- mk/install.mk | 2 +- mk/llvm.mk | 5 +---- mk/main.mk | 30 ++++++++++++++++++++---------- mk/platform.mk | 31 ++++++++++++++++--------------- mk/rt.mk | 4 +--- mk/target.mk | 4 ++-- mk/tests.mk | 24 ++++++++++++++---------- 14 files changed, 65 insertions(+), 56 deletions(-) diff --git a/mk/cfg/aarch64-linux-android.mk b/mk/cfg/aarch64-linux-android.mk index 274f73834d4..140c4af8297 100644 --- a/mk/cfg/aarch64-linux-android.mk +++ b/mk/cfg/aarch64-linux-android.mk @@ -1,5 +1,4 @@ # aarch64-linux-android configuration -# CROSS_PREFIX_aarch64-linux-android- CC_aarch64-linux-android=$(CFG_AARCH64_LINUX_ANDROID_NDK)/bin/aarch64-linux-android-gcc CXX_aarch64-linux-android=$(CFG_AARCH64_LINUX_ANDROID_NDK)/bin/aarch64-linux-android-g++ CPP_aarch64-linux-android=$(CFG_AARCH64_LINUX_ANDROID_NDK)/bin/aarch64-linux-android-gcc -E diff --git a/mk/cfg/x86_64-apple-ios.mk b/mk/cfg/x86_64-apple-ios.mk index dd6080fdb0b..3faf0c6a3f2 100644 --- a/mk/cfg/x86_64-apple-ios.mk +++ b/mk/cfg/x86_64-apple-ios.mk @@ -29,4 +29,4 @@ CFG_UNIXY_x86_64-apple-ios := 1 CFG_LDPATH_x86_64-apple-ios := CFG_RUN_x86_64-apple-ios = $(2) CFG_RUN_TARG_x86_64-apple-ios = $(call CFG_RUN_x86_64-apple-ios,,$(2)) -CFG_GNU_TRIPLE_i386-apple-ios := x86_64-apple-ios +CFG_GNU_TRIPLE_x86_64-apple-ios := x86_64-apple-ios diff --git a/mk/cfg/x86_64-unknown-bitrig.mk b/mk/cfg/x86_64-unknown-bitrig.mk index afffec1a53a..3ed94011c48 100644 --- a/mk/cfg/x86_64-unknown-bitrig.mk +++ b/mk/cfg/x86_64-unknown-bitrig.mk @@ -9,7 +9,7 @@ CFG_LIB_GLOB_x86_64-unknown-bitrig=lib$(1)-*.so CFG_LIB_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS) CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIE -fPIC -m64 -I/usr/include $(CFLAGS) -CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS) +CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list= CFG_LLC_FLAGS_x86_64-unknown-bitrig := CFG_INSTALL_NAME_x86_64-unknown-bitrig = diff --git a/mk/crates.mk b/mk/crates.mk index f47c4857ef8..4db8f32bb16 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -139,13 +139,13 @@ ONLY_RLIB_alloc_system := 1 # Documented-by-default crates DOC_CRATES := std alloc collections core libc rustc_unicode -ifeq ($(CFG_DISABLE_JEMALLOC),) +ifdef CFG_DISABLE_JEMALLOC +RUSTFLAGS_rustc_back := --cfg disable_jemalloc +else TARGET_CRATES += alloc_jemalloc DEPS_std += alloc_jemalloc DEPS_alloc_jemalloc := core libc native:jemalloc ONLY_RLIB_alloc_jemalloc := 1 -else -RUSTFLAGS_rustc_back := --cfg disable_jemalloc endif ################################################################################ diff --git a/mk/docs.mk b/mk/docs.mk index f76368e3d0b..81aabe60ff3 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -71,7 +71,7 @@ DOC_L10N_TARGETS := # If NO_REBUILD is set then break the dependencies on rustdoc so we # build the documentation without having to rebuild rustdoc. -ifeq ($(NO_REBUILD),) +ifndef NO_REBUILD HTML_DEPS := $(RUSTDOC_EXE) else HTML_DEPS := @@ -152,7 +152,7 @@ define DEF_LIB_DOC # If NO_REBUILD is set then break the dependencies on rustdoc so we # build crate documentation without having to rebuild rustdoc. -ifeq ($(NO_REBUILD),) +ifndef NO_REBUILD LIB_DOC_DEP_$(1) = \ $$(CRATEFILE_$(1)) \ $$(RSINPUTS_$(1)) \ diff --git a/mk/grammar.mk b/mk/grammar.mk index 0d527bd0688..8956983e3be 100644 --- a/mk/grammar.mk +++ b/mk/grammar.mk @@ -41,8 +41,8 @@ $(BG)RustLexer.class: $(BG) $(SG)RustLexer.g4 check-build-lexer-verifier: $(BG)verify -ifeq ($(NO_REBUILD),) -VERIFY_DEPS := rustc-stage2-H-$(CFG_BUILD) $(LD)stamp.rustc +ifndef NO_REBUILD +VERIFY_DEPS := rustc-stage2-H-$(CFG_BUILD) $(LD)stamp.rustc else VERIFY_DEPS := endif diff --git a/mk/host.mk b/mk/host.mk index 59a00950b5c..2faed75ac07 100644 --- a/mk/host.mk +++ b/mk/host.mk @@ -18,7 +18,7 @@ # $(5) - the name of the crate being processed define CP_HOST_STAGE_N_CRATE -ifeq ($$(ONLY_RLIB_$(5)),) +ifndef ONLY_RLIB_$(5) $$(HLIB$(2)_H_$(4))/stamp.$(5): \ $$(TLIB$(1)_T_$(3)_H_$(4))/stamp.$(5) \ $$(RUST_DEPS_$(5):%=$$(HLIB$(2)_H_$(4))/stamp.%) \ diff --git a/mk/install.mk b/mk/install.mk index af6f3ff6ad2..6d9d86c3eb8 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -121,7 +121,7 @@ install-runtime-target-$(1)-cleanup: endef $(foreach target,$(CFG_TARGET), \ - $(if $(findstring $(CFG_ADB_DEVICE_STATUS),"true"), \ + $(if $(findstring $(CFG_ADB_DEVICE_STATUS),true), \ $(eval $(call INSTALL_RUNTIME_TARGET_N,$(taget),$(CFG_BUILD))) \ $(eval $(call INSTALL_RUNTIME_TARGET_CLEANUP_N,$(target))) \ )) diff --git a/mk/llvm.mk b/mk/llvm.mk index a4174efa5ef..d250ede9958 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -71,7 +71,7 @@ $$(LLVM_STAMP_$(1)): $$(S)src/rustllvm/llvm-auto-clean-trigger @$$(call E, make: done cleaning llvm) touch -r $$@.start_time $$@ && rm $$@.start_time -ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1) +ifdef CFG_ENABLE_LLVM_STATIC_STDCPP LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \ -print-file-name=lib$(CFG_STDCPP_NAME).a))" else @@ -95,9 +95,6 @@ endef $(foreach host,$(CFG_HOST), \ $(eval $(call DEF_LLVM_RULES,$(host)))) -$(foreach host,$(CFG_HOST), \ - $(eval LLVM_CONFIGS := $(LLVM_CONFIGS) $(LLVM_CONFIG_$(host)))) - # This can't be done in target.mk because it's included before this file. define LLVM_LINKAGE_DEPS $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc_llvm: $$(LLVM_LINKAGE_PATH_$(2)) diff --git a/mk/main.mk b/mk/main.mk index 9d75771dc80..b272a80eaf7 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -86,13 +86,13 @@ CFG_INFO := $(info cfg: version $(CFG_VERSION)) MKFILE_DEPS := config.stamp $(call rwildcard,$(CFG_SRC_DIR)mk/,*) MKFILES_FOR_TARBALL:=$(MKFILE_DEPS) -ifneq ($(NO_MKFILE_DEPS),) +ifdef NO_MKFILE_DEPS MKFILE_DEPS := endif NON_BUILD_HOST = $(filter-out $(CFG_BUILD),$(CFG_HOST)) NON_BUILD_TARGET = $(filter-out $(CFG_BUILD),$(CFG_TARGET)) -ifneq ($(MAKE_RESTARTS),) +ifdef MAKE_RESTARTS CFG_INFO := $(info cfg: make restarts: $(MAKE_RESTARTS)) endif @@ -107,28 +107,40 @@ ifneq ($(wildcard $(NON_BUILD_TARGET)),) CFG_INFO := $(info cfg: non-build target triples $(NON_BUILD_TARGET)) endif -CFG_RUSTC_FLAGS := $(RUSTFLAGS) +CFG_RUSTC_FLAGS := +ifdef RUSTFLAGS + CFG_RUSTC_FLAGS += $(RUSTFLAGS) +endif CFG_GCCISH_CFLAGS := CFG_GCCISH_LINK_FLAGS := CFG_JEMALLOC_FLAGS := +ifdef JEMALLOC_FLAGS + CFG_JEMALLOC_FLAGS += $(JEMALLOC_FLAGS) +endif ifdef CFG_DISABLE_OPTIMIZE $(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE)) - CFG_RUSTC_FLAGS += CFG_JEMALLOC_FLAGS += --enable-debug else # The rtopt cfg turns off runtime sanity checks CFG_RUSTC_FLAGS += -O --cfg rtopt endif -CFG_JEMALLOC_FLAGS += $(JEMALLOC_FLAGS) - ifdef CFG_ENABLE_DEBUG_ASSERTIONS $(info cfg: enabling debug assertions (CFG_ENABLE_DEBUG_ASSERTIONS)) CFG_RUSTC_FLAGS += -C debug-assertions=on endif +define DEF_RUSTFLAGS_STAGE +RUSTFLAGS_STAGE$(1) := +endef + +STAGES = 0 1 2 3 + +$(foreach stage,$(STAGES), \ + $(eval $(call DEF_RUSTFLAGS_STAGE,$(stage)))) + ifdef CFG_ENABLE_DEBUGINFO $(info cfg: enabling debuginfo (CFG_ENABLE_DEBUGINFO)) CFG_RUSTC_FLAGS += -g @@ -186,9 +198,9 @@ endif ifndef CFG_DISABLE_VALGRIND_RPASS - $(info cfg: enabling valgrind run-pass tests (CFG_ENABLE_VALGRIND_RPASS)) + $(info cfg: enabling valgrind run-pass tests) $(info cfg: valgrind-rpass command set to $(CFG_VALGRIND)) - CFG_VALGRIND_RPASS :=$(CFG_VALGRIND) + CFG_VALGRIND_RPASS := $(CFG_VALGRIND) else $(info cfg: disabling valgrind run-pass tests) CFG_VALGRIND_RPASS := @@ -372,8 +384,6 @@ export CFG_BOOTSTRAP_KEY TRIPLE_TO_DEBUGGER_SCRIPT_SETTING=\ $(if $(findstring windows,$(1)),none,$(if $(findstring darwin,$(1)),lldb,gdb)) -STAGES = 0 1 2 3 - define SREQ # $(1) is the stage number # $(2) is the target triple diff --git a/mk/platform.mk b/mk/platform.mk index 9c74e657a84..d702cca209d 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -82,12 +82,11 @@ AR := ar define SET_FROM_CFG ifdef CFG_$(1) ifeq ($(origin $(1)),undefined) - $$(info cfg: using $(1)=$(CFG_$(1)) (CFG_$(1))) - $(1)=$(CFG_$(1)) - endif - ifeq ($(origin $(1)),default) - $$(info cfg: using $(1)=$(CFG_$(1)) (CFG_$(1))) - $(1)=$(CFG_$(1)) + $$(info cfg: using $(1)=$$(CFG_$(1)) (CFG_$(1))) + $(1)=$$(CFG_$(1)) + else ifeq ($(origin $(1)),default) + $$(info cfg: using $(1)=$$(CFG_$(1)) (CFG_$(1))) + $(1)=$$(CFG_$(1)) endif endif endef @@ -101,7 +100,9 @@ include $(wildcard $(CFG_SRC_DIR)mk/cfg/*.mk) define ADD_INSTALLED_OBJECTS INSTALLED_OBJECTS_$(1) += $$(CFG_INSTALLED_OBJECTS_$(1)) - REQUIRED_OBJECTS_$(1) += $$(CFG_THIRD_PARTY_OBJECTS_$(1)) + ifdef CFG_THIRD_PARTY_OBJECTS_$(1) + REQUIRED_OBJECTS_$(1) += $$(CFG_THIRD_PARTY_OBJECTS_$(1)) + endif INSTALLED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt) REQUIRED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt) endef @@ -163,15 +164,15 @@ define CFG_MAKE_TOOLCHAIN # Prepend the tools with their prefix if cross compiling ifneq ($(CFG_BUILD),$(1)) ifneq ($$(findstring msvc,$(1)),msvc) - CC_$(1)=$(CROSS_PREFIX_$(1))$(CC_$(1)) - CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1)) - CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1)) - AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1)) - LINK_$(1)=$(CROSS_PREFIX_$(1))$(LINK_$(1)) - RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(LINK_$(1))) \ - -C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1)) + CC_$(1)=$(CROSS_PREFIX_$(1))$(CC_$(1)) + CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1)) + CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1)) + AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1)) + LINK_$(1)=$(CROSS_PREFIX_$(1))$(LINK_$(1)) + RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(LINK_$(1))) \ + -C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1)) - RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1)) + RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1)) endif endif diff --git a/mk/rt.mk b/mk/rt.mk index 9dbbcbebb97..394fbe1ba0f 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -107,8 +107,6 @@ $$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1)) endef -$(foreach target,$(CFG_TARGET), \ - $(eval $(call RUNTIME_RULES,$(target)))) $(foreach lib,$(NATIVE_LIBS), \ $(foreach target,$(CFG_TARGET), \ $(eval $(call THIRD_PARTY_LIB,$(target),$(lib))))) @@ -171,7 +169,7 @@ endif # See #17183 for details, this file is touched during the build process so we # don't want to consider it as a dependency. -JEMALLOC_DEPS := $(filter-out $(S)src/jemalloc/VERSION,$(JEMALLOC_DEPS)) +JEMALLOC_DEPS := $(filter-out $(S)src/jemalloc/VERSION,$$(JEMALLOC_DEPS)) JEMALLOC_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc) ifeq ($$(CFG_WINDOWSY_$(1)),1) diff --git a/mk/target.mk b/mk/target.mk index 32a3eb5c20d..1fcc87f0c35 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -138,12 +138,12 @@ define TARGET_RUSTRT_STARTUP_OBJ $$(TLIB$(1)_T_$(2)_H_$(3))/$(4).o: \ $(S)src/rtstartup/$(4).rs \ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.core \ - $$(HSREQ$(1)_T_$(2)_H_$(3)) \ + $$(HSREQ$(1)_H_$(3)) \ | $$(TBIN$(1)_T_$(2)_H_$(3))/ @$$(call E, rustc: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) --emit=obj -o $$@ $$< -ifeq ($$(CFG_RUSTRT_HAS_STARTUP_OBJS_$(2)), 1) +ifdef CFG_RUSTRT_HAS_STARTUP_OBJS_$(2) # Add dependencies on Rust startup objects to all crates that depend on core. # This ensures that they are built after core (since they depend on it), # but before everything else (since they are needed for linking dylib crates). diff --git a/mk/tests.mk b/mk/tests.mk index 19587a28d55..bce5a52118b 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -36,6 +36,8 @@ TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) # Environment configuration ###################################################################### +TESTARGS := + # The arguments to all test runners ifdef TESTNAME TESTARGS += $(TESTNAME) @@ -48,6 +50,8 @@ endif # Arguments to the cfail/rfail/rpass tests ifdef CFG_VALGRIND CTEST_RUNTOOL = --runtool "$(CFG_VALGRIND)" +else + CTEST_RUNTOOL = endif CTEST_TESTARGS := $(TESTARGS) @@ -143,10 +147,11 @@ else CFG_ADB_TEST_DIR= endif +DOC_NAMES := # $(1) - name of doc test # $(2) - file of the test define DOCTEST -DOC_NAMES := $$(DOC_NAMES) $(1) +DOC_NAMES += $(1) DOCFILE_$(1) := $(2) endef @@ -362,7 +367,7 @@ define TEST_RUNNER # If NO_REBUILD is set then break the dependencies on everything but # the source files so we can test crates without rebuilding any of the # parent crates. -ifeq ($(NO_REBUILD),) +ifndef NO_REBUILD TESTDEP_$(1)_$(2)_$(3)_$(4) = $$(SREQ$(1)_T_$(2)_H_$(3)) \ $$(foreach crate,$$(TARGET_CRATES), \ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) \ @@ -447,7 +452,7 @@ $(foreach host,$(CFG_HOST), \ $(if $(findstring $(target),$(CFG_BUILD)), \ $(eval $(call DEF_TEST_CRATE_RULES,$(stage),$(target),$(host),$(crate))), \ $(if $(findstring android, $(target)), \ - $(if $(findstring $(CFG_ADB_DEVICE_STATUS),"true"), \ + $(if $(findstring $(CFG_ADB_DEVICE_STATUS),true), \ $(eval $(call DEF_TEST_CRATE_RULES_android,$(stage),$(target),$(host),$(crate))), \ $(eval $(call DEF_TEST_CRATE_RULES_null,$(stage),$(target),$(host),$(crate))) \ ), \ @@ -700,14 +705,14 @@ check-stage$(1)-T-$(2)-H-$(3)-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4 # (Encoded as a separate variable because GNU make does not have a # good way to express OR on ifeq commands) -ifneq ($$(CTEST_DISABLE_$(4)),) +ifdef CTEST_DISABLE_$(4) # Test suite is disabled for all configured targets. CTEST_DONT_RUN_$(1)-T-$(2)-H-$(3)-$(4) := $$(CTEST_DISABLE_$(4)) else # else, check if non-self-hosted target (i.e. target not-in hosts) ... ifeq ($$(findstring $(2),$$(CFG_HOST)),) # ... if so, then check if this test suite is disabled for non-selfhosts. -ifneq ($$(CTEST_DISABLE_NONSELFHOST_$(4)),) +ifdef CTEST_DISABLE_NONSELFHOST_$(4) # Test suite is disabled for this target. CTEST_DONT_RUN_$(1)-T-$(2)-H-$(3)-$(4) := $$(CTEST_DISABLE_NONSELFHOST_$(4)) endif @@ -715,7 +720,7 @@ endif # Neither DISABLE nor DISABLE_NONSELFHOST is set ==> okay, run the test. endif -ifeq ($$(CTEST_DONT_RUN_$(1)-T-$(2)-H-$(3)-$(4)),) +ifndef CTEST_DONT_RUN_$(1)-T-$(2)-H-$(3)-$(4) $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ $$(CTEST_DEPS_$(4)_$(1)-T-$(2)-H-$(3)) @@ -824,7 +829,7 @@ check-stage$(1)-T-$(2)-H-$(3)-doc-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3) # If NO_REBUILD is set then break the dependencies on everything but # the source files so we can test documentation without rebuilding # rustdoc etc. -ifeq ($(NO_REBUILD),) +ifndef NO_REBUILD DOCTESTDEP_$(1)_$(2)_$(3)_$(4) = \ $$(DOCFILE_$(4)) \ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ @@ -859,7 +864,7 @@ define DEF_CRATE_DOC_TEST # If NO_REBUILD is set then break the dependencies on everything but # the source files so we can test crate documentation without # rebuilding any of the parent crates. -ifeq ($(NO_REBUILD),) +ifndef NO_REBUILD CRATEDOCTESTDEP_$(1)_$(2)_$(3)_$(4) = \ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ @@ -922,8 +927,7 @@ TEST_GROUPS = \ pretty-rpass-full \ pretty-rfail-full \ pretty-rfail \ - pretty-pretty \ - $(NULL) + pretty-pretty define DEF_CHECK_FOR_STAGE_AND_TARGET_AND_HOST check-stage$(1)-T-$(2)-H-$(3): check-stage$(1)-T-$(2)-H-$(3)-exec