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

Merged
merged 14 commits into from
Nov 21, 2024
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
2 changes: 2 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3685,6 +3685,8 @@ version = "0.0.0"
dependencies = [
"rustc_data_structures",
"rustc_span",
"serde",
"serde_json",
]

[[package]]
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_abi/src/layout/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,24 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
}
}

pub fn is_single_vector_element<C>(self, cx: &C, expected_size: Size) -> bool
where
Ty: TyAbiInterface<'a, C>,
C: HasDataLayout,
{
match self.backend_repr {
BackendRepr::Vector { .. } => self.size == expected_size,
BackendRepr::Memory { .. } => {
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
self.field(cx, 0).is_single_vector_element(cx, expected_size)
} else {
false
}
}
_ => false,
}
}

pub fn is_adt<C>(self) -> bool
where
Ty: TyAbiInterface<'a, C>,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_driver_impl/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc ver
driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`

driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file

driver_impl_unstable_feature_usage = cannot dump feature usage metrics: {$error}
24 changes: 23 additions & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use rustc_interface::{Linker, Queries, interface, passes};
use rustc_lint::unerased_lint_store;
use rustc_metadata::creader::MetadataLoader;
use rustc_metadata::locator;
use rustc_middle::ty::TyCtxt;
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_session::config::{
CG_OPTIONS, ErrorOutputType, Input, OutFileName, OutputType, UnstableOptions, Z_OPTIONS,
Expand Down Expand Up @@ -103,7 +104,7 @@ mod signal_handler {

use crate::session_diagnostics::{
RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead,
RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage,
};

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
Expand Down Expand Up @@ -431,6 +432,10 @@ fn run_compiler(
// Make sure name resolution and macro expansion is run.
queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering());

if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
queries.global_ctxt()?.enter(|tcxt| dump_feature_usage_metrics(tcxt, metrics_dir));
}

if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
return early_exit();
}
Expand Down Expand Up @@ -475,6 +480,23 @@ fn run_compiler(
})
}

fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &PathBuf) {
let output_filenames = tcxt.output_filenames(());
let mut metrics_file_name = std::ffi::OsString::from("unstable_feature_usage_metrics-");
let mut metrics_path = output_filenames.with_directory_and_extension(metrics_dir, "json");
let metrics_file_stem =
metrics_path.file_name().expect("there should be a valid default output filename");
metrics_file_name.push(metrics_file_stem);
metrics_path.pop();
metrics_path.push(metrics_file_name);
if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) {
// FIXME(yaahc): once metrics can be enabled by default we will want "failure to emit
// default metrics" to only produce a warning when metrics are enabled by default and emit
// an error only when the user manually enables metrics
tcxt.dcx().emit_err(UnstableFeatureUsage { error });
}
}

// Extract output directory and file from matches.
fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileName>) {
let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_driver_impl/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::error::Error;

use rustc_macros::{Diagnostic, Subdiagnostic};

#[derive(Diagnostic)]
Expand Down Expand Up @@ -93,3 +95,9 @@ pub(crate) struct IceFlags {
#[derive(Diagnostic)]
#[diag(driver_impl_ice_exclude_cargo_defaults)]
pub(crate) struct IceExcludeCargoDefaults;

#[derive(Diagnostic)]
#[diag(driver_impl_unstable_feature_usage)]
pub(crate) struct UnstableFeatureUsage {
pub error: Box<dyn Error>,
}
2 changes: 2 additions & 0 deletions compiler/rustc_feature/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ edition = "2021"
# tidy-alphabetical-start
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_span = { path = "../rustc_span" }
serde = { version = "1.0.125", features = [ "derive" ] }
serde_json = "1.0.59"
# tidy-alphabetical-end
50 changes: 50 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! List of the unstable feature gates.

use std::path::PathBuf;

use rustc_data_structures::fx::FxHashSet;
use rustc_span::Span;
use rustc_span::symbol::{Symbol, sym};
Expand Down Expand Up @@ -651,6 +653,54 @@ declare_features! (
// -------------------------------------------------------------------------
);

impl Features {
pub fn dump_feature_usage_metrics(
&self,
metrics_path: PathBuf,
) -> Result<(), Box<dyn std::error::Error>> {
#[derive(serde::Serialize)]
struct LibFeature {
symbol: String,
}

#[derive(serde::Serialize)]
struct LangFeature {
symbol: String,
since: Option<String>,
}

#[derive(serde::Serialize)]
struct FeatureUsage {
lib_features: Vec<LibFeature>,
lang_features: Vec<LangFeature>,
}

let metrics_file = std::fs::File::create(metrics_path)?;
let metrics_file = std::io::BufWriter::new(metrics_file);

let lib_features = self
.enabled_lib_features
.iter()
.map(|EnabledLibFeature { gate_name, .. }| LibFeature { symbol: gate_name.to_string() })
.collect();

let lang_features = self
.enabled_lang_features
.iter()
.map(|EnabledLangFeature { gate_name, stable_since, .. }| LangFeature {
symbol: gate_name.to_string(),
since: stable_since.map(|since| since.to_string()),
})
.collect();

let feature_usage = FeatureUsage { lib_features, lang_features };

serde_json::to_writer(metrics_file, &feature_usage)?;

Ok(())
}
}

/// Some features are not allowed to be used together at the same time, if
/// the two are present, produce an error.
///
Expand Down
55 changes: 8 additions & 47 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use rustc_span::symbol::{Ident, kw, sym};
use rustc_span::{
DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span, Symbol, edit_distance,
};
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedNote;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
Expand All @@ -45,50 +46,6 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
use crate::{Expectation, FnCtxt};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
let tcx = self.tcx;
match ty.kind() {
// Not all of these (e.g., unsafe fns) implement `FnOnce`,
// so we look for these beforehand.
// FIXME(async_closures): These don't impl `FnOnce` by default.
ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(..) => true,
// If it's not a simple function, look for things which implement `FnOnce`.
_ => {
let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
return false;
};

// This conditional prevents us from asking to call errors and unresolved types.
// It might seem that we can use `predicate_must_hold_modulo_regions`,
// but since a Dummy binder is used to fill in the FnOnce trait's arguments,
// type resolution always gives a "maybe" here.
if self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
info!("check deref {:?} error", ty);
matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
}) {
return false;
}

self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
info!("check deref {:?} impl FnOnce", ty);
self.probe(|_| {
let trait_ref =
ty::TraitRef::new(tcx, fn_once, [ty, self.next_ty_var(span)]);
let poly_trait_ref = ty::Binder::dummy(trait_ref);
let obligation = Obligation::misc(
tcx,
span,
self.body_id,
self.param_env,
poly_trait_ref,
);
self.predicate_may_hold(&obligation)
})
})
}
}
}

fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
self.autoderef(span, ty)
.silence_errors()
Expand Down Expand Up @@ -2367,12 +2324,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let is_accessible = field.vis.is_accessible_from(scope, tcx);

if is_accessible {
if self.is_fn_ty(field_ty, span) {
if let Some((what, _, _)) = self.extract_callable_info(field_ty) {
let what = match what {
DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id),
DefIdOrName::Name(what) => what,
};
let expr_span = expr.span.to(item_name.span);
err.multipart_suggestion(
format!(
"to call the function stored in `{item_name}`, \
surround the field access with parentheses",
"to call the {what} stored in `{item_name}`, \
surround the field access with parentheses",
),
vec![
(expr_span.shrink_to_lo(), '('.to_string()),
Expand Down
39 changes: 38 additions & 1 deletion compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,8 +537,45 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
self.requires_unsafe(expr.span, DerefOfRawPointer);
}
}
ExprKind::InlineAsm { .. } => {
ExprKind::InlineAsm(box InlineAsmExpr {
asm_macro: _,
ref operands,
template: _,
options: _,
line_spans: _,
}) => {
self.requires_unsafe(expr.span, UseOfInlineAssembly);

// For inline asm, do not use `walk_expr`, since we want to handle the label block
// specially.
for op in &**operands {
use rustc_middle::thir::InlineAsmOperand::*;
match op {
In { expr, reg: _ }
| Out { expr: Some(expr), reg: _, late: _ }
| InOut { expr, reg: _, late: _ } => self.visit_expr(&self.thir()[*expr]),
SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
self.visit_expr(&self.thir()[*in_expr]);
if let Some(out_expr) = out_expr {
self.visit_expr(&self.thir()[*out_expr]);
}
}
Out { expr: None, reg: _, late: _ }
| Const { value: _, span: _ }
| SymFn { value: _, span: _ }
| SymStatic { def_id: _ } => {}
Label { block } => {
// Label blocks are safe context.
// `asm!()` is forced to be wrapped inside unsafe. If there's no special
// treatment, the label blocks would also always be unsafe with no way
// of opting out.
self.in_safety_context(SafetyContext::Safe, |this| {
visit::walk_block(this, &this.thir()[*block])
});
}
}
}
return;
}
ExprKind::Adt(box AdtExpr {
adt_def,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,7 @@ impl OutputFilenames {
self.with_directory_and_extension(&self.out_directory, extension)
}

fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf {
pub fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf {
let mut path = directory.join(&self.filestem);
path.set_extension(extension);
path
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1887,7 +1887,7 @@ options! {
meta_stats: bool = (false, parse_bool, [UNTRACKED],
"gather metadata statistics (default: no)"),
metrics_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"stores metrics about the errors being emitted by rustc to disk"),
"the directory metrics emitted by rustc are dumped into (implicitly enables default set of metrics)"),
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
(default: no)"),
Expand Down
26 changes: 18 additions & 8 deletions compiler/rustc_target/src/callconv/s390x.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
// FIXME: The assumes we're using the non-vector ABI, i.e., compiling
// for a pre-z13 machine or using -mno-vx.
// Reference: ELF Application Binary Interface s390x Supplement
// https://github.com/IBM/s390x-abi

use crate::abi::call::{ArgAbi, FnAbi, Reg};
use crate::abi::{HasDataLayout, TyAbiInterface};
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind};
use crate::abi::{BackendRepr, HasDataLayout, TyAbiInterface};
use crate::spec::HasTargetSpec;

fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
let size = ret.layout.size;
if size.bits() <= 128 && matches!(ret.layout.backend_repr, BackendRepr::Vector { .. }) {
return;
}
if !ret.layout.is_aggregate() && size.bits() <= 64 {
ret.extend_integer_width_to(64);
} else {
ret.make_indirect();
Expand All @@ -32,19 +36,25 @@ where
}
return;
}
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {

let size = arg.layout.size;
if size.bits() <= 128 && arg.layout.is_single_vector_element(cx, size) {
arg.cast_to(Reg { kind: RegKind::Vector, size });
return;
}
if !arg.layout.is_aggregate() && size.bits() <= 64 {
arg.extend_integer_width_to(64);
return;
}

if arg.layout.is_single_fp_element(cx) {
match arg.layout.size.bytes() {
match size.bytes() {
4 => arg.cast_to(Reg::f32()),
8 => arg.cast_to(Reg::f64()),
_ => arg.make_indirect(),
}
} else {
match arg.layout.size.bytes() {
match size.bytes() {
1 => arg.cast_to(Reg::i8()),
2 => arg.cast_to(Reg::i16()),
4 => arg.cast_to(Reg::i32()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target {
base.endian = Endian::Big;
// z10 is the oldest CPU supported by LLVM
base.cpu = "z10".into();
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
base.features = "-vector".into();
base.max_atomic_width = Some(128);
base.min_global_align = Some(16);
base.stack_probes = StackProbeType::Inline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target {
base.endian = Endian::Big;
// z10 is the oldest CPU supported by LLVM
base.cpu = "z10".into();
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
base.features = "-vector".into();
base.max_atomic_width = Some(128);
base.min_global_align = Some(16);
base.static_position_independent_executables = true;
Expand Down
Loading
Loading