Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #42022

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@
- [unique](library-features/unique.md)
- [unsize](library-features/unsize.md)
- [utf8_error_error_len](library-features/utf8-error-error-len.md)
- [vec_resize_default](library-features/vec-resize-default.md)
- [vec_remove_item](library-features/vec-remove-item.md)
- [windows_c](library-features/windows-c.md)
- [windows_handle](library-features/windows-handle.md)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# `vec_resize_default`

The tracking issue for this feature is: [#41758]

[#41758]: https://github.com/rust-lang/rust/issues/41758

------------------------
128 changes: 95 additions & 33 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,11 +1220,14 @@ impl<T> Vec<T> {
}

impl<T: Clone> Vec<T> {
/// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
/// Resizes the `Vec` in-place so that `len` is equal to `new_len`.
///
/// If `new_len` is greater than `len()`, the `Vec` is extended by the
/// If `new_len` is greater than `len`, the `Vec` is extended by the
/// difference, with each additional slot filled with `value`.
/// If `new_len` is less than `len()`, the `Vec` is simply truncated.
/// If `new_len` is less than `len`, the `Vec` is simply truncated.
///
/// This method requires `Clone` to clone the passed value. If you'd
/// rather create a value with `Default` instead, see [`resize_default`].
///
/// # Examples
///
Expand All @@ -1237,19 +1240,100 @@ impl<T: Clone> Vec<T> {
/// vec.resize(2, 0);
/// assert_eq!(vec, [1, 2]);
/// ```
///
/// [`resize_default`]: #method.resize_default
#[stable(feature = "vec_resize", since = "1.5.0")]
pub fn resize(&mut self, new_len: usize, value: T) {
let len = self.len();

if new_len > len {
self.extend_with_element(new_len - len, value);
self.extend_with(new_len - len, ExtendElement(value))
} else {
self.truncate(new_len);
}
}

/// Clones and appends all elements in a slice to the `Vec`.
///
/// Iterates over the slice `other`, clones each element, and then appends
/// it to this `Vec`. The `other` vector is traversed in-order.
///
/// Note that this function is same as `extend` except that it is
/// specialized to work with slices instead. If and when Rust gets
/// specialization this function will likely be deprecated (but still
/// available).
///
/// # Examples
///
/// ```
/// let mut vec = vec![1];
/// vec.extend_from_slice(&[2, 3, 4]);
/// assert_eq!(vec, [1, 2, 3, 4]);
/// ```
#[stable(feature = "vec_extend_from_slice", since = "1.6.0")]
pub fn extend_from_slice(&mut self, other: &[T]) {
self.spec_extend(other.iter())
}
}

impl<T: Default> Vec<T> {
/// Resizes the `Vec` in-place so that `len` is equal to `new_len`.
///
/// If `new_len` is greater than `len`, the `Vec` is extended by the
/// difference, with each additional slot filled with `Default::default()`.
/// If `new_len` is less than `len`, the `Vec` is simply truncated.
///
/// This method uses `Default` to create new values on every push. If
/// you'd rather `Clone` a given value, use [`resize`].
///
///
/// # Examples
///
/// ```
/// #![feature(vec_resize_default)]
///
/// let mut vec = vec![1, 2, 3];
/// vec.resize_default(5);
/// assert_eq!(vec, [1, 2, 3, 0, 0]);
///
/// let mut vec = vec![1, 2, 3, 4];
/// vec.resize_default(2);
/// assert_eq!(vec, [1, 2]);
/// ```
///
/// [`resize`]: #method.resize
#[unstable(feature = "vec_resize_default", issue = "41758")]
pub fn resize_default(&mut self, new_len: usize) {
let len = self.len();

if new_len > len {
self.extend_with(new_len - len, ExtendDefault);
} else {
self.truncate(new_len);
}
}
}

/// Extend the vector by `n` additional clones of `value`.
fn extend_with_element(&mut self, n: usize, value: T) {
// This code generalises `extend_with_{element,default}`.
trait ExtendWith<T> {
fn next(&self) -> T;
fn last(self) -> T;
}

struct ExtendElement<T>(T);
impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
fn next(&self) -> T { self.0.clone() }
fn last(self) -> T { self.0 }
}

struct ExtendDefault;
impl<T: Default> ExtendWith<T> for ExtendDefault {
fn next(&self) -> T { Default::default() }
fn last(self) -> T { Default::default() }
}
impl<T> Vec<T> {
/// Extend the vector by `n` values, using the given generator.
fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, value: E) {
self.reserve(n);

unsafe {
Expand All @@ -1261,43 +1345,21 @@ impl<T: Clone> Vec<T> {

// Write all elements except the last one
for _ in 1..n {
ptr::write(ptr, value.clone());
ptr::write(ptr, value.next());
ptr = ptr.offset(1);
// Increment the length in every step in case clone() panics
// Increment the length in every step in case next() panics
local_len.increment_len(1);
}

if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, value);
ptr::write(ptr, value.last());
local_len.increment_len(1);
}

// len set by scope guard
}
}

/// Clones and appends all elements in a slice to the `Vec`.
///
/// Iterates over the slice `other`, clones each element, and then appends
/// it to this `Vec`. The `other` vector is traversed in-order.
///
/// Note that this function is same as `extend` except that it is
/// specialized to work with slices instead. If and when Rust gets
/// specialization this function will likely be deprecated (but still
/// available).
///
/// # Examples
///
/// ```
/// let mut vec = vec![1];
/// vec.extend_from_slice(&[2, 3, 4]);
/// assert_eq!(vec, [1, 2, 3, 4]);
/// ```
#[stable(feature = "vec_extend_from_slice", since = "1.6.0")]
pub fn extend_from_slice(&mut self, other: &[T]) {
self.spec_extend(other.iter())
}
}

// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
Expand Down Expand Up @@ -1389,7 +1451,7 @@ trait SpecFromElem: Sized {
impl<T: Clone> SpecFromElem for T {
default fn from_elem(elem: Self, n: usize) -> Vec<Self> {
let mut v = Vec::with_capacity(n);
v.extend_with_element(n, elem);
v.extend_with(n, ExtendElement(elem));
v
}
}
Expand Down Expand Up @@ -1424,7 +1486,7 @@ macro_rules! impl_spec_from_elem {
}
}
let mut v = Vec::with_capacity(n);
v.extend_with_element(n, elem);
v.extend_with(n, ExtendElement(elem));
v
}
}
Expand Down
1 change: 1 addition & 0 deletions src/libcore/num/wrapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use super::Wrapping;

use ops::*;

#[allow(unused_macros)]
macro_rules! sh_impl_signed {
($t:ident, $f:ident) => (
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
1 change: 1 addition & 0 deletions src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,7 @@ macro_rules! neg_impl_numeric {
($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} }
}

#[allow(unused_macros)]
macro_rules! neg_impl_unsigned {
($($t:ty)*) => {
neg_impl_core!{ x => {
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ declare_lint! {
"detects unreachable patterns"
}

declare_lint! {
pub UNUSED_MACROS,
Warn,
"detects macros that were not used"
}

declare_lint! {
pub WARNINGS,
Warn,
Expand Down Expand Up @@ -259,6 +265,7 @@ impl LintPass for HardwiredLints {
DEAD_CODE,
UNREACHABLE_CODE,
UNREACHABLE_PATTERNS,
UNUSED_MACROS,
WARNINGS,
UNUSED_FEATURES,
STABLE_FEATURES,
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ use hir;
use hir::def_id::LOCAL_CRATE;
use hir::intravisit as hir_visit;
use syntax::visit as ast_visit;
use syntax::tokenstream::ThinTokenStream;

/// Information about the registered lints.
///
Expand Down Expand Up @@ -1125,6 +1126,13 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
run_lints!(self, check_attribute, early_passes, attr);
}

fn visit_mac_def(&mut self, _mac: &'a ThinTokenStream, id: ast::NodeId) {
let lints = self.sess.lints.borrow_mut().take(id);
for early_lint in lints {
self.early_lint(&early_lint);
}
}
}

enum CheckLintNameResult {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,8 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,

let krate = ecx.monotonic_expander().expand_crate(krate);

ecx.check_unused_macros();

let mut missing_fragment_specifiers: Vec<_> =
ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
missing_fragment_specifiers.sort();
Expand Down
11 changes: 0 additions & 11 deletions src/librustc_incremental/persist/preds/compress/test_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,3 @@ macro_rules! graph {
}
}
}

macro_rules! set {
($( $value:expr ),*) => {
{
use $crate::rustc_data_structures::fx::FxHashSet;
let mut set = FxHashSet();
$(set.insert($value);)*
set
}
}
}
3 changes: 2 additions & 1 deletion src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UNUSED_MUST_USE,
UNUSED_UNSAFE,
PATH_STATEMENTS,
UNUSED_ATTRIBUTES);
UNUSED_ATTRIBUTES,
UNUSED_MACROS);

// Guidelines for creating a future incompatibility lint:
//
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_plugin/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ impl<'a> Registry<'a> {
}
self.syntax_exts.push((name, match extension {
NormalTT(ext, _, allow_internal_unstable) => {
NormalTT(ext, Some(self.krate_span), allow_internal_unstable)
let nid = ast::CRATE_NODE_ID;
NormalTT(ext, Some((nid, self.krate_span)), allow_internal_unstable)
}
IdentTT(ext, _, allow_internal_unstable) => {
IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,10 @@ pub struct Resolver<'a> {
pub whitelisted_legacy_custom_derives: Vec<Name>,
pub found_unresolved_macro: bool,

// List of crate local macros that we need to warn about as being unused.
// Right now this only includes macro_rules! macros.
unused_macros: FxHashSet<DefId>,

// Maps the `Mark` of an expansion to its containing module or block.
invocations: FxHashMap<Mark, &'a InvocationData<'a>>,

Expand Down Expand Up @@ -1392,6 +1396,7 @@ impl<'a> Resolver<'a> {
potentially_unused_imports: Vec::new(),
struct_constructors: DefIdMap(),
found_unresolved_macro: false,
unused_macros: FxHashSet(),
}
}

Expand Down
26 changes: 24 additions & 2 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
use rustc::hir::def::{Def, Export};
use rustc::hir::map::{self, DefCollector};
use rustc::ty;
use rustc::{ty, lint};
use syntax::ast::{self, Name, Ident};
use syntax::attr::{self, HasAttrs};
use syntax::errors::DiagnosticBuilder;
Expand Down Expand Up @@ -291,12 +291,32 @@ impl<'a> base::Resolver for Resolver<'a> {
},
};
self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
self.unused_macros.remove(&def.def_id());
Ok(Some(self.get_macro(def)))
}

fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-> Result<Rc<SyntaxExtension>, Determinacy> {
self.resolve_macro_to_def(scope, path, kind, force).map(|def| self.get_macro(def))
self.resolve_macro_to_def(scope, path, kind, force).map(|def| {
self.unused_macros.remove(&def.def_id());
self.get_macro(def)
})
}

fn check_unused_macros(&self) {
for did in self.unused_macros.iter() {
let id_span = match *self.macro_map[did] {
SyntaxExtension::NormalTT(_, isp, _) => isp,
_ => None,
};
if let Some((id, span)) = id_span {
let lint = lint::builtin::UNUSED_MACROS;
let msg = "unused macro definition".to_string();
self.session.add_lint(lint, id, span, msg);
} else {
bug!("attempted to create unused macro error, but span not available");
}
}
}
}

Expand Down Expand Up @@ -687,6 +707,8 @@ impl<'a> Resolver<'a> {
if attr::contains_name(&item.attrs, "macro_export") {
let def = Def::Macro(def_id, MacroKind::Bang);
self.macro_exports.push(Export { name: ident.name, def: def, span: item.span });
} else {
self.unused_macros.insert(def_id);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let bound_list = unsatisfied_predicates.iter()
.map(|p| format!("`{} : {}`", p.self_ty(), p))
.collect::<Vec<_>>()
.join(", ");
.join("\n");
err.note(&format!("the method `{}` exists but the following trait bounds \
were not satisfied: {}",
were not satisfied:\n{}",
item_name,
bound_list));
}
Expand Down
Loading