Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ impl CodegenBackend for CraneliftCodegenBackend {
""
}

fn name(&self) -> &'static str {
"cranelift"
}

fn init(&self, sess: &Session) {
use rustc_session::config::{InstrumentCoverage, Lto};
match sess.lto() {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ impl CodegenBackend for GccCodegenBackend {
crate::DEFAULT_LOCALE_RESOURCE
}

fn name(&self) -> &'static str {
"gcc"
}

fn init(&self, _sess: &Session) {
#[cfg(feature = "master")]
{
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ impl CodegenBackend for LlvmCodegenBackend {
crate::DEFAULT_LOCALE_RESOURCE
}

fn name(&self) -> &'static str {
"llvm"
}

fn init(&self, sess: &Session) {
llvm_util::init(sess); // Make sure llvm is inited
}
Expand Down Expand Up @@ -350,7 +354,14 @@ impl CodegenBackend for LlvmCodegenBackend {

// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, metadata, outputs);
link_binary(
sess,
&LlvmArchiveBuilderBuilder,
codegen_results,
metadata,
outputs,
self.name(),
);
}
}

Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub fn link_binary(
codegen_results: CodegenResults,
metadata: EncodedMetadata,
outputs: &OutputFilenames,
codegen_backend: &'static str,
) {
let _timer = sess.timer("link_binary");
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
Expand Down Expand Up @@ -154,6 +155,7 @@ pub fn link_binary(
&codegen_results,
&metadata,
path.as_ref(),
codegen_backend,
);
}
}
Expand Down Expand Up @@ -680,6 +682,7 @@ fn link_natively(
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
tmpdir: &Path,
codegen_backend: &'static str,
) {
info!("preparing {:?} to {:?}", crate_type, out_filename);
let (linker_path, flavor) = linker_and_flavor(sess);
Expand All @@ -705,6 +708,7 @@ fn link_natively(
codegen_results,
metadata,
self_contained_components,
codegen_backend,
);

linker::disable_localization(&mut cmd);
Expand Down Expand Up @@ -2208,6 +2212,7 @@ fn linker_with_args(
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
self_contained_components: LinkSelfContainedComponents,
codegen_backend: &'static str,
) -> Command {
let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
let cmd = &mut *super::linker::get_linker(
Expand All @@ -2216,6 +2221,7 @@ fn linker_with_args(
flavor,
self_contained_components.are_any_components_enabled(),
&codegen_results.crate_info.target_cpu,
codegen_backend,
);
let link_output_kind = link_output_kind(sess, crate_type);

Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub(crate) fn get_linker<'a>(
flavor: LinkerFlavor,
self_contained: bool,
target_cpu: &'a str,
codegen_backend: &'static str,
) -> Box<dyn Linker + 'a> {
let msvc_tool = find_msvc_tools::find_tool(&sess.target.arch, "link.exe");

Expand Down Expand Up @@ -154,6 +155,7 @@ pub(crate) fn get_linker<'a>(
is_ld: cc == Cc::No,
is_gnu: flavor.is_gnu(),
uses_lld: flavor.uses_lld(),
codegen_backend,
}) as Box<dyn Linker>,
LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
Expand Down Expand Up @@ -367,6 +369,7 @@ struct GccLinker<'a> {
is_ld: bool,
is_gnu: bool,
uses_lld: bool,
codegen_backend: &'static str,
}

impl<'a> GccLinker<'a> {
Expand Down Expand Up @@ -423,9 +426,15 @@ impl<'a> GccLinker<'a> {
if let Some(path) = &self.sess.opts.unstable_opts.profile_sample_use {
self.link_arg(&format!("-plugin-opt=sample-profile={}", path.display()));
};
let prefix = if self.codegen_backend == "gcc" {
// The GCC linker plugin requires a leading dash.
"-"
} else {
""
};
self.link_args(&[
&format!("-plugin-opt={opt_level}"),
&format!("-plugin-opt=mcpu={}", self.target_cpu),
&format!("-plugin-opt={prefix}{opt_level}"),
&format!("-plugin-opt={prefix}mcpu={}", self.target_cpu),
]);
}

Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub trait CodegenBackend {
/// Called before `init` so that all other functions are able to emit translatable diagnostics.
fn locale_resource(&self) -> &'static str;

fn name(&self) -> &'static str;

fn init(&self, _sess: &Session) {}

fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
Expand Down Expand Up @@ -96,7 +98,14 @@ pub trait CodegenBackend {
metadata: EncodedMetadata,
outputs: &OutputFilenames,
) {
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, metadata, outputs);
link_binary(
sess,
&ArArchiveBuilderBuilder,
codegen_results,
metadata,
outputs,
self.name(),
);
}
}

Expand Down
26 changes: 14 additions & 12 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1122,18 +1122,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {

sess.time("layout_testing", || layout_test::test_layout(tcx));
sess.time("abi_testing", || abi_test::test_abi(tcx));

// If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
// (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
// in MIR optimizations that may only be reachable through codegen, or other codepaths
// that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
if tcx.sess.opts.unstable_opts.validate_mir {
sess.time("ensuring_final_MIR_is_computable", || {
tcx.par_hir_body_owners(|def_id| {
tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
});
});
}
}

/// Runs the type-checking, region checking and other miscellaneous analysis
Expand Down Expand Up @@ -1199,6 +1187,20 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
// we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
let _ = tcx.all_diagnostic_items(());
});

// If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
// (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
// in MIR optimizations that may only be reachable through codegen, or other codepaths
// that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
// Nevertheless, wait after type checking is finished, as optimizing code that does not
// type-check is very prone to ICEs.
if tcx.sess.opts.unstable_opts.validate_mir {
sess.time("ensuring_final_MIR_is_computable", || {
tcx.par_hir_body_owners(|def_id| {
tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
});
});
}
}

/// Runs the codegen backend, after which the AST and analysis can
Expand Down
33 changes: 33 additions & 0 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
binding,
if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
parent_scope,
module,
finalize,
shadowing,
);
Expand Down Expand Up @@ -1025,6 +1026,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
binding: Option<NameBinding<'ra>>,
shadowed_glob: Option<NameBinding<'ra>>,
parent_scope: &ParentScope<'ra>,
module: Module<'ra>,
finalize: Finalize,
shadowing: Shadowing,
) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
Expand Down Expand Up @@ -1076,6 +1078,37 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
}

// If we encounter a re-export for a type with private fields, it will not be able to
// be constructed through this re-export. We track that case here to expand later
// privacy errors with appropriate information.
if let Res::Def(_, def_id) = binding.res() {
let struct_ctor = match def_id.as_local() {
Some(def_id) => self.struct_constructors.get(&def_id).cloned(),
None => {
let ctor = self.cstore().ctor_untracked(def_id);
ctor.map(|(ctor_kind, ctor_def_id)| {
let ctor_res = Res::Def(
DefKind::Ctor(rustc_hir::def::CtorOf::Struct, ctor_kind),
ctor_def_id,
);
let ctor_vis = self.tcx.visibility(ctor_def_id);
let field_visibilities = self
.tcx
.associated_item_def_ids(def_id)
.iter()
.map(|field_id| self.tcx.visibility(field_id))
.collect();
(ctor_res, ctor_vis, field_visibilities)
})
}
};
if let Some((_, _, fields)) = struct_ctor
&& fields.iter().any(|vis| !self.is_accessible_from(*vis, module))
{
self.inaccessible_ctor_reexport.insert(path_span, binding.span);
}
}

self.record_use(ident, binding, used);
return Ok(binding);
}
Expand Down
99 changes: 66 additions & 33 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1942,44 +1942,77 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
return true;
};

let update_message =
|this: &mut Self, err: &mut Diag<'_>, source: &PathSource<'_, '_, '_>| {
match source {
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
PathSource::TupleStruct(_, pattern_spans) => {
err.primary_message(
"cannot match against a tuple struct which contains private fields",
);

// Use spans of the tuple struct pattern.
Some(Vec::from(*pattern_spans))
}
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
PathSource::Expr(Some(Expr {
kind: ExprKind::Call(path, args),
span: call_span,
..
})) => {
err.primary_message(
"cannot initialize a tuple struct which contains private fields",
);
this.suggest_alternative_construction_methods(
def_id,
err,
path.span,
*call_span,
&args[..],
);
// Use spans of the tuple struct definition.
this.r
.field_idents(def_id)
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
}
_ => None,
}
};
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
if let Some(use_span) = self.r.inaccessible_ctor_reexport.get(&span)
&& is_accessible
{
err.span_note(
*use_span,
"the type is accessed through this re-export, but the type's constructor \
is not visible in this import's scope due to private fields",
);
if is_accessible
&& fields
.iter()
.all(|vis| self.r.is_accessible_from(*vis, self.parent_scope.module))
{
err.span_suggestion_verbose(
span,
"the type can be constructed directly, because its fields are \
available from the current scope",
// Using `tcx.def_path_str` causes the compiler to hang.
// We don't need to handle foreign crate types because in that case you
// can't access the ctor either way.
format!(
"crate{}", // The method already has leading `::`.
self.r.tcx.def_path(def_id).to_string_no_crate_verbose(),
),
Applicability::MachineApplicable,
);
}
update_message(self, err, &source);
}
if !is_expected(ctor_def) || is_accessible {
return true;
}

let field_spans = match source {
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
PathSource::TupleStruct(_, pattern_spans) => {
err.primary_message(
"cannot match against a tuple struct which contains private fields",
);

// Use spans of the tuple struct pattern.
Some(Vec::from(pattern_spans))
}
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
PathSource::Expr(Some(Expr {
kind: ExprKind::Call(path, args),
span: call_span,
..
})) => {
err.primary_message(
"cannot initialize a tuple struct which contains private fields",
);
self.suggest_alternative_construction_methods(
def_id,
err,
path.span,
*call_span,
&args[..],
);
// Use spans of the tuple struct definition.
self.r
.field_idents(def_id)
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
}
_ => None,
};
let field_spans = update_message(self, err, &source);

if let Some(spans) =
field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,11 @@ pub struct Resolver<'ra, 'tcx> {
/// Crate-local macro expanded `macro_export` referred to by a module-relative path.
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(),

/// When a type is re-exported that has an inaccessible constructor because it has fields that
/// are inaccessible from the import's scope, we mark that as the type won't be able to be built
/// through the re-export. We use this information to extend the existing diagnostic.
inaccessible_ctor_reexport: FxHashMap<Span, Span>,

arenas: &'ra ResolverArenas<'ra>,
dummy_binding: NameBinding<'ra>,
builtin_types_bindings: FxHashMap<Symbol, NameBinding<'ra>>,
Expand Down Expand Up @@ -1595,6 +1600,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
glob_map: Default::default(),
used_imports: FxHashSet::default(),
maybe_unused_trait_imports: Default::default(),
inaccessible_ctor_reexport: Default::default(),

arenas,
dummy_binding: arenas.new_pub_res_binding(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/num/niche_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ impl Nanoseconds {
pub const ZERO: Self = unsafe { Nanoseconds::new_unchecked(0) };
}

impl Default for Nanoseconds {
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
impl const Default for Nanoseconds {
#[inline]
fn default() -> Self {
Self::ZERO
Expand Down
Loading
Loading