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 #118687

Merged
merged 17 commits into from
Dec 7, 2023
Merged
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
22 changes: 22 additions & 0 deletions compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,20 @@ impl DroplessArena {
}
}

/// Allocates a string slice that is copied into the `DroplessArena`, returning a
/// reference to it. Will panic if passed an empty string.
///
/// Panics:
///
/// - Zero-length string
#[inline]
pub fn alloc_str(&self, string: &str) -> &str {
let slice = self.alloc_slice(string.as_bytes());

// SAFETY: the result has a copy of the same valid UTF-8 bytes.
unsafe { std::str::from_utf8_unchecked(slice) }
}

/// # Safety
///
/// The caller must ensure that `mem` is valid for writes up to `size_of::<T>() * len`, and that
Expand Down Expand Up @@ -655,6 +669,14 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
self.dropless.alloc_slice(value)
}

#[inline]
pub fn alloc_str(&self, string: &str) -> &str {
if string.is_empty() {
return "";
}
self.dropless.alloc_str(string)
}

#[allow(clippy::mut_from_ref)]
pub fn alloc_from_iter<T: ArenaAllocatable<'tcx, C>, C>(
&self,
Expand Down
240 changes: 83 additions & 157 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use rustc_data_structures::sync::Lrc;
use rustc_errors::registry::Registry;
use rustc_errors::{ErrorGuaranteed, Handler};
use rustc_lint::LintStore;
use rustc_middle::ty;
use rustc_middle::util::Providers;
use rustc_middle::{bug, ty};
use rustc_parse::maybe_new_parser_from_source_str;
use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack;
Expand Down Expand Up @@ -104,7 +104,6 @@ pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -
let exhaustive_values = !specs.is_empty();
let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };

let mut old_syntax = None;
for s in specs {
let sess = ParseSess::with_silent_emitter(Some(format!(
"this error occurred on the command line: `--check-cfg={s}`"
Expand Down Expand Up @@ -142,174 +141,101 @@ pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -
expected_error();
};

let mut set_old_syntax = || {
// defaults are flipped for the old syntax
if old_syntax == None {
check_cfg.exhaustive_names = false;
check_cfg.exhaustive_values = false;
}
old_syntax = Some(true);
};

if meta_item.has_name(sym::names) {
set_old_syntax();

check_cfg.exhaustive_names = true;
for arg in args {
if arg.is_word()
&& let Some(ident) = arg.ident()
{
check_cfg.expecteds.entry(ident.name).or_insert(ExpectedValues::Any);
} else {
error!("`names()` arguments must be simple identifiers");
}
}
} else if meta_item.has_name(sym::values) {
set_old_syntax();

if let Some((name, values)) = args.split_first() {
if name.is_word()
&& let Some(ident) = name.ident()
{
let expected_values = check_cfg
.expecteds
.entry(ident.name)
.and_modify(|expected_values| match expected_values {
ExpectedValues::Some(_) => {}
ExpectedValues::Any => {
// handle the case where names(...) was done
// before values by changing to a list
*expected_values = ExpectedValues::Some(FxHashSet::default());
}
})
.or_insert_with(|| ExpectedValues::Some(FxHashSet::default()));
if !meta_item.has_name(sym::cfg) {
expected_error();
}

let ExpectedValues::Some(expected_values) = expected_values else {
bug!("`expected_values` should be a list a values")
};
let mut names = Vec::new();
let mut values: FxHashSet<_> = Default::default();

for val in values {
if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) {
expected_values.insert(Some(*s));
} else {
error!("`values()` arguments must be string literals");
}
}
let mut any_specified = false;
let mut values_specified = false;
let mut values_any_specified = false;

if values.is_empty() {
expected_values.insert(None);
}
} else {
error!("`values()` first argument must be a simple identifier");
for arg in args {
if arg.is_word()
&& let Some(ident) = arg.ident()
{
if values_specified {
error!("`cfg()` names cannot be after values");
}
} else if args.is_empty() {
check_cfg.exhaustive_values = true;
} else {
expected_error();
}
} else if meta_item.has_name(sym::cfg) {
old_syntax = Some(false);

let mut names = Vec::new();
let mut values: FxHashSet<_> = Default::default();

let mut any_specified = false;
let mut values_specified = false;
let mut values_any_specified = false;

for arg in args {
if arg.is_word()
&& let Some(ident) = arg.ident()
{
if values_specified {
error!("`cfg()` names cannot be after values");
}
names.push(ident);
} else if arg.has_name(sym::any)
&& let Some(args) = arg.meta_item_list()
{
if any_specified {
error!("`any()` cannot be specified multiple times");
}
any_specified = true;
if !args.is_empty() {
error!("`any()` must be empty");
}
} else if arg.has_name(sym::values)
&& let Some(args) = arg.meta_item_list()
{
if names.is_empty() {
error!("`values()` cannot be specified before the names");
} else if values_specified {
error!("`values()` cannot be specified multiple times");
}
values_specified = true;

for arg in args {
if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) {
values.insert(Some(*s));
} else if arg.has_name(sym::any)
&& let Some(args) = arg.meta_item_list()
{
if values_any_specified {
error!("`any()` in `values()` cannot be specified multiple times");
}
values_any_specified = true;
if !args.is_empty() {
error!("`any()` must be empty");
}
} else {
error!("`values()` arguments must be string literals or `any()`");
names.push(ident);
} else if arg.has_name(sym::any)
&& let Some(args) = arg.meta_item_list()
{
if any_specified {
error!("`any()` cannot be specified multiple times");
}
any_specified = true;
if !args.is_empty() {
error!("`any()` must be empty");
}
} else if arg.has_name(sym::values)
&& let Some(args) = arg.meta_item_list()
{
if names.is_empty() {
error!("`values()` cannot be specified before the names");
} else if values_specified {
error!("`values()` cannot be specified multiple times");
}
values_specified = true;

for arg in args {
if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) {
values.insert(Some(*s));
} else if arg.has_name(sym::any)
&& let Some(args) = arg.meta_item_list()
{
if values_any_specified {
error!("`any()` in `values()` cannot be specified multiple times");
}
values_any_specified = true;
if !args.is_empty() {
error!("`any()` must be empty");
}
} else {
error!("`values()` arguments must be string literals or `any()`");
}
} else {
error!(
"`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"
);
}
} else {
error!("`cfg()` arguments must be simple identifiers, `any()` or `values(...)`");
}
}

if values.is_empty() && !values_any_specified && !any_specified {
values.insert(None);
} else if !values.is_empty() && values_any_specified {
error!(
"`values()` arguments cannot specify string literals and `any()` at the same time"
);
}
if values.is_empty() && !values_any_specified && !any_specified {
values.insert(None);
} else if !values.is_empty() && values_any_specified {
error!(
"`values()` arguments cannot specify string literals and `any()` at the same time"
);
}

if any_specified {
if names.is_empty()
&& values.is_empty()
&& !values_specified
&& !values_any_specified
{
check_cfg.exhaustive_names = false;
} else {
error!("`cfg(any())` can only be provided in isolation");
}
if any_specified {
if names.is_empty() && values.is_empty() && !values_specified && !values_any_specified {
check_cfg.exhaustive_names = false;
} else {
for name in names {
check_cfg
.expecteds
.entry(name.name)
.and_modify(|v| match v {
ExpectedValues::Some(v) if !values_any_specified => {
v.extend(values.clone())
}
ExpectedValues::Some(_) => *v = ExpectedValues::Any,
ExpectedValues::Any => {}
})
.or_insert_with(|| {
if values_any_specified {
ExpectedValues::Any
} else {
ExpectedValues::Some(values.clone())
}
});
}
error!("`cfg(any())` can only be provided in isolation");
}
} else {
expected_error();
for name in names {
check_cfg
.expecteds
.entry(name.name)
.and_modify(|v| match v {
ExpectedValues::Some(v) if !values_any_specified => {
v.extend(values.clone())
}
ExpectedValues::Some(_) => *v = ExpectedValues::Any,
ExpectedValues::Any => {}
})
.or_insert_with(|| {
if values_any_specified {
ExpectedValues::Any
} else {
ExpectedValues::Some(values.clone())
}
});
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
.map(|inner| MustUsePath::Pinned(Box::new(inner)))
}
ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => {
elaborate(
cx.tcx,
cx.tcx.explicit_item_bounds(def).instantiate_identity_iter_copied(),
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3135,7 +3135,7 @@ declare_lint! {
/// ### Example
///
/// ```text
/// rustc --check-cfg 'names()'
/// rustc --check-cfg 'cfg()'
/// ```
///
/// ```rust,ignore (needs command line option)
Expand All @@ -3146,7 +3146,7 @@ declare_lint! {
/// This will produce:
///
/// ```text
/// warning: unknown condition name used
/// warning: unexpected `cfg` condition name: `widnows`
/// --> lint_example.rs:1:7
/// |
/// 1 | #[cfg(widnows)]
Expand All @@ -3157,9 +3157,10 @@ declare_lint! {
///
/// ### Explanation
///
/// This lint is only active when a `--check-cfg='names(...)'` option has been passed
/// to the compiler and triggers whenever an unknown condition name or value is used.
/// The known condition include names or values passed in `--check-cfg`, `--cfg`, and some
/// This lint is only active when `--check-cfg` arguments are being passed
/// to the compiler and triggers whenever an unexpected condition name or value is used.
///
/// The known condition include names or values passed in `--check-cfg`, and some
/// well-knows names and values built into the compiler.
pub UNEXPECTED_CFGS,
Warn,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ fn output(cmd: &mut Command) -> String {

fn main() {
for component in REQUIRED_COMPONENTS.iter().chain(OPTIONAL_COMPONENTS.iter()) {
println!("cargo:rustc-check-cfg=values(llvm_component,\"{component}\")");
println!("cargo:rustc-check-cfg=cfg(llvm_component,values(\"{component}\"))");
}

if tracked_env_var_os("RUST_CHECK").is_some() {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "SuppressLLVMWarnings.h"

#include "llvm-c/BitReader.h"
#include "llvm-c/Core.h"
#include "llvm-c/Object.h"
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_llvm/llvm-wrapper/Linker.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "SuppressLLVMWarnings.h"
#include "llvm/Linker/Linker.h"

#include "LLVMWrapper.h"
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef _rustc_llvm_SuppressLLVMWarnings_h
#define _rustc_llvm_SuppressLLVMWarnings_h

// LLVM currently generates many warnings when compiled using MSVC. These warnings make it difficult
// to diagnose real problems when working on C++ code, so we suppress them.

#ifdef _MSC_VER
#pragma warning(disable:4530) // C++ exception handler used, but unwind semantics are not enabled.
#pragma warning(disable:4624) // 'xxx': destructor was implicitly defined as deleted
#pragma warning(disable:4244) // conversion from 'xxx' to 'yyy', possible loss of data
#endif

#endif // _rustc_llvm_SuppressLLVMWarnings_h
1 change: 1 addition & 0 deletions compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp

#include "SuppressLLVMWarnings.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/ObjectFile.h"
Expand Down
Loading
Loading