Skip to content

Commit 5ae50d3

Browse files
committed
Auto merge of #140324 - matthiaskrgr:rollup-jlzvdre, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #139865 (Stabilize proc_macro::Span::{start,end,line,column}.) - #140086 (If creating a temporary directory fails with permission denied then retry with backoff) - #140216 (Document that "extern blocks must be unsafe" in Rust 2024) - #140253 (Add XtensaAsmPrinter) - #140272 (Improve error message for `||` (or) in let chains) - #140305 (Track per-obligation recursion depth only if there is inference in the new solver) - #140306 (handle specialization in the new trait solver) - #140308 (stall generator witness obligations: add regression test) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d3508a8 + c781c9a commit 5ae50d3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+526
-139
lines changed

Cargo.lock

+3-1
Original file line numberDiff line numberDiff line change
@@ -3700,6 +3700,9 @@ dependencies = [
37003700
[[package]]
37013701
name = "rustc_fs_util"
37023702
version = "0.0.0"
3703+
dependencies = [
3704+
"tempfile",
3705+
]
37033706

37043707
[[package]]
37053708
name = "rustc_graphviz"
@@ -4012,7 +4015,6 @@ dependencies = [
40124015
"rustc_session",
40134016
"rustc_span",
40144017
"rustc_target",
4015-
"tempfile",
40164018
"tracing",
40174019
]
40184020

compiler/rustc_codegen_ssa/src/back/archive.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use object::read::archive::ArchiveFile;
1313
use object::read::macho::FatArch;
1414
use rustc_data_structures::fx::FxIndexSet;
1515
use rustc_data_structures::memmap::Mmap;
16+
use rustc_fs_util::TempDirBuilder;
1617
use rustc_session::Session;
1718
use rustc_span::Symbol;
18-
use tempfile::Builder as TempFileBuilder;
1919
use tracing::trace;
2020

2121
use super::metadata::search_for_section;
@@ -501,7 +501,7 @@ impl<'a> ArArchiveBuilder<'a> {
501501
// it creates. We need it to be the default mode for back compat reasons however. (See
502502
// #107495) To handle this we are telling tempfile to create a temporary directory instead
503503
// and then inside this directory create a file using File::create.
504-
let archive_tmpdir = TempFileBuilder::new()
504+
let archive_tmpdir = TempDirBuilder::new()
505505
.suffix(".temp-archive")
506506
.tempdir_in(output.parent().unwrap_or_else(|| Path::new("")))
507507
.map_err(|err| {

compiler/rustc_codegen_ssa/src/back/link.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxIndexSet;
1818
use rustc_data_structures::memmap::Mmap;
1919
use rustc_data_structures::temp_dir::MaybeTempDir;
2020
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
21-
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
21+
use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize};
2222
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
2323
use rustc_macros::LintDiagnostic;
2424
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
@@ -48,7 +48,6 @@ use rustc_target::spec::{
4848
LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel,
4949
SanitizerSet, SplitDebuginfo,
5050
};
51-
use tempfile::Builder as TempFileBuilder;
5251
use tracing::{debug, info, warn};
5352

5453
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
@@ -100,7 +99,7 @@ pub fn link_binary(
10099
});
101100

102101
if outputs.outputs.should_link() {
103-
let tmpdir = TempFileBuilder::new()
102+
let tmpdir = TempDirBuilder::new()
104103
.prefix("rustc")
105104
.tempdir()
106105
.unwrap_or_else(|error| sess.dcx().emit_fatal(errors::CreateTempDir { error }));

compiler/rustc_fs_util/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ edition = "2024"
55

66
[dependencies]
77
# tidy-alphabetical-start
8+
tempfile = "3.7.1"
89
# tidy-alphabetical-end

compiler/rustc_fs_util/src/lib.rs

+44-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use std::ffi::CString;
1+
use std::ffi::{CString, OsStr};
22
use std::path::{Path, PathBuf, absolute};
3-
use std::{fs, io};
3+
use std::{env, fs, io};
4+
5+
use tempfile::TempDir;
46

57
// Unfortunately, on windows, it looks like msvcrt.dll is silently translating
68
// verbatim paths under the hood to non-verbatim paths! This manifests itself as
@@ -102,3 +104,43 @@ pub fn path_to_c_string(p: &Path) -> CString {
102104
pub fn try_canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
103105
fs::canonicalize(&path).or_else(|_| absolute(&path))
104106
}
107+
108+
pub struct TempDirBuilder<'a, 'b> {
109+
builder: tempfile::Builder<'a, 'b>,
110+
}
111+
112+
impl<'a, 'b> TempDirBuilder<'a, 'b> {
113+
pub fn new() -> Self {
114+
Self { builder: tempfile::Builder::new() }
115+
}
116+
117+
pub fn prefix<S: AsRef<OsStr> + ?Sized>(&mut self, prefix: &'a S) -> &mut Self {
118+
self.builder.prefix(prefix);
119+
self
120+
}
121+
122+
pub fn suffix<S: AsRef<OsStr> + ?Sized>(&mut self, suffix: &'b S) -> &mut Self {
123+
self.builder.suffix(suffix);
124+
self
125+
}
126+
127+
pub fn tempdir_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<TempDir> {
128+
let dir = dir.as_ref();
129+
// On Windows in CI, we had been getting fairly frequent "Access is denied"
130+
// errors when creating temporary directories.
131+
// So this implements a simple retry with backoff loop.
132+
#[cfg(windows)]
133+
for wait in 1..11 {
134+
match self.builder.tempdir_in(dir) {
135+
Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {}
136+
t => return t,
137+
}
138+
std::thread::sleep(std::time::Duration::from_millis(1 << wait));
139+
}
140+
self.builder.tempdir_in(dir)
141+
}
142+
143+
pub fn tempdir(&self) -> io::Result<TempDir> {
144+
self.tempdir_in(env::temp_dir())
145+
}
146+
}

compiler/rustc_llvm/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ pub fn initialize_available_targets() {
229229
LLVMInitializeXtensaTargetInfo,
230230
LLVMInitializeXtensaTarget,
231231
LLVMInitializeXtensaTargetMC,
232+
LLVMInitializeXtensaAsmPrinter,
232233
LLVMInitializeXtensaAsmParser
233234
);
234235
init_target!(

compiler/rustc_metadata/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ rustc_serialize = { path = "../rustc_serialize" }
2626
rustc_session = { path = "../rustc_session" }
2727
rustc_span = { path = "../rustc_span" }
2828
rustc_target = { path = "../rustc_target" }
29-
tempfile = "3.2"
3029
tracing = "0.1"
3130
# tidy-alphabetical-end
3231

compiler/rustc_metadata/src/fs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ use std::path::{Path, PathBuf};
22
use std::{fs, io};
33

44
use rustc_data_structures::temp_dir::MaybeTempDir;
5+
use rustc_fs_util::TempDirBuilder;
56
use rustc_middle::ty::TyCtxt;
67
use rustc_session::config::{CrateType, OutFileName, OutputType};
78
use rustc_session::output::filename_for_metadata;
89
use rustc_session::{MetadataKind, Session};
9-
use tempfile::Builder as TempFileBuilder;
1010

1111
use crate::errors::{
1212
BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile,
@@ -45,7 +45,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
4545
// final destination, with an `fs::rename` call. In order for the rename to
4646
// always succeed, the temporary file needs to be on the same filesystem,
4747
// which is why we create it inside the output directory specifically.
48-
let metadata_tmpdir = TempFileBuilder::new()
48+
let metadata_tmpdir = TempDirBuilder::new()
4949
.prefix("rmeta")
5050
.tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
5151
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailedCreateTempdir { err }));

compiler/rustc_middle/src/ty/context.rs

+4
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
590590
self.defaultness(def_id).has_value()
591591
}
592592

593+
fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool {
594+
self.specializes((impl_def_id, victim_def_id))
595+
}
596+
593597
fn impl_is_default(self, impl_def_id: DefId) -> bool {
594598
self.defaultness(impl_def_id).is_default()
595599
}

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

+72-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_type_ir::{
1010
};
1111
use tracing::{debug, instrument};
1212

13+
use super::has_only_region_constraints;
1314
use super::trait_goals::TraitGoalProvenVia;
1415
use crate::delegate::SolverDelegate;
1516
use crate::solve::inspect::ProbeKind;
@@ -771,6 +772,69 @@ where
771772
}
772773
})
773774
}
775+
}
776+
777+
pub(super) enum AllowInferenceConstraints {
778+
Yes,
779+
No,
780+
}
781+
782+
impl<D, I> EvalCtxt<'_, D>
783+
where
784+
D: SolverDelegate<Interner = I>,
785+
I: Interner,
786+
{
787+
/// Check whether we can ignore impl candidates due to specialization.
788+
///
789+
/// This is only necessary for `feature(specialization)` and seems quite ugly.
790+
pub(super) fn filter_specialized_impls(
791+
&mut self,
792+
allow_inference_constraints: AllowInferenceConstraints,
793+
candidates: &mut Vec<Candidate<I>>,
794+
) {
795+
match self.typing_mode() {
796+
TypingMode::Coherence => return,
797+
TypingMode::Analysis { .. }
798+
| TypingMode::Borrowck { .. }
799+
| TypingMode::PostBorrowckAnalysis { .. }
800+
| TypingMode::PostAnalysis => {}
801+
}
802+
803+
let mut i = 0;
804+
'outer: while i < candidates.len() {
805+
let CandidateSource::Impl(victim_def_id) = candidates[i].source else {
806+
i += 1;
807+
continue;
808+
};
809+
810+
for (j, c) in candidates.iter().enumerate() {
811+
if i == j {
812+
continue;
813+
}
814+
815+
let CandidateSource::Impl(other_def_id) = c.source else {
816+
continue;
817+
};
818+
819+
// See if we can toss out `victim` based on specialization.
820+
//
821+
// While this requires us to know *for sure* that the `lhs` impl applies
822+
// we still use modulo regions here. This is fine as specialization currently
823+
// assumes that specializing impls have to be always applicable, meaning that
824+
// the only allowed region constraints may be constraints also present on the default impl.
825+
if matches!(allow_inference_constraints, AllowInferenceConstraints::Yes)
826+
|| has_only_region_constraints(c.result)
827+
{
828+
if self.cx().impl_specializes(other_def_id, victim_def_id) {
829+
candidates.remove(i);
830+
continue 'outer;
831+
}
832+
}
833+
}
834+
835+
i += 1;
836+
}
837+
}
774838

775839
/// Assemble and merge candidates for goals which are related to an underlying trait
776840
/// goal. Right now, this is normalizes-to and host effect goals.
@@ -857,7 +921,7 @@ where
857921
}
858922
}
859923
TraitGoalProvenVia::Misc => {
860-
let candidates =
924+
let mut candidates =
861925
self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
862926

863927
// Prefer "orphaned" param-env normalization predicates, which are used
@@ -871,6 +935,13 @@ where
871935
return Ok(response);
872936
}
873937

938+
// We drop specialized impls to allow normalization via a final impl here. In case
939+
// the specializing impl has different inference constraints from the specialized
940+
// impl, proving the trait goal is already ambiguous, so we never get here. This
941+
// means we can just ignore inference constraints and don't have to special-case
942+
// constraining the normalized-to `term`.
943+
self.filter_specialized_impls(AllowInferenceConstraints::Yes, &mut candidates);
944+
874945
let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
875946
if let Some(response) = self.try_merge_responses(&responses) {
876947
Ok(response)

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_type_ir::{
1616
};
1717
use tracing::{instrument, trace};
1818

19+
use super::has_only_region_constraints;
1920
use crate::coherence;
2021
use crate::delegate::SolverDelegate;
2122
use crate::solve::inspect::{self, ProofTreeBuilder};
@@ -476,13 +477,8 @@ where
476477
Ok(response) => response,
477478
};
478479

479-
let has_changed = if !response.value.var_values.is_identity_modulo_regions()
480-
|| !response.value.external_constraints.opaque_types.is_empty()
481-
{
482-
HasChanged::Yes
483-
} else {
484-
HasChanged::No
485-
};
480+
let has_changed =
481+
if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
486482

487483
let (normalization_nested_goals, certainty) =
488484
self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);

compiler/rustc_next_trait_solver/src/solve/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ fn has_no_inference_or_external_constraints<I: Interner>(
7070
&& normalization_nested_goals.is_empty()
7171
}
7272

73+
fn has_only_region_constraints<I: Interner>(response: ty::Canonical<I, Response<I>>) -> bool {
74+
let ExternalConstraintsData {
75+
region_constraints: _,
76+
ref opaque_types,
77+
ref normalization_nested_goals,
78+
} = *response.value.external_constraints;
79+
response.value.var_values.is_identity_modulo_regions()
80+
&& opaque_types.is_empty()
81+
&& normalization_nested_goals.is_empty()
82+
}
83+
7384
impl<'a, D, I> EvalCtxt<'a, D>
7485
where
7586
D: SolverDelegate<Interner = I>,

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -213,18 +213,35 @@ where
213213
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
214214
};
215215

216-
// In case the associated item is hidden due to specialization, we have to
217-
// return ambiguity this would otherwise be incomplete, resulting in
218-
// unsoundness during coherence (#105782).
219216
let target_item_def_id = match ecx.fetch_eligible_assoc_item(
220217
goal_trait_ref,
221218
goal.predicate.def_id(),
222219
impl_def_id,
223220
) {
224221
Ok(Some(target_item_def_id)) => target_item_def_id,
225222
Ok(None) => {
226-
return ecx
227-
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
223+
match ecx.typing_mode() {
224+
// In case the associated item is hidden due to specialization, we have to
225+
// return ambiguity this would otherwise be incomplete, resulting in
226+
// unsoundness during coherence (#105782).
227+
ty::TypingMode::Coherence => {
228+
return ecx.evaluate_added_goals_and_make_canonical_response(
229+
Certainty::AMBIGUOUS,
230+
);
231+
}
232+
// Outside of coherence, we treat the associated item as rigid instead.
233+
ty::TypingMode::Analysis { .. }
234+
| ty::TypingMode::Borrowck { .. }
235+
| ty::TypingMode::PostBorrowckAnalysis { .. }
236+
| ty::TypingMode::PostAnalysis => {
237+
ecx.structurally_instantiate_normalizes_to_term(
238+
goal,
239+
goal.predicate.alias,
240+
);
241+
return ecx
242+
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
243+
}
244+
};
228245
}
229246
Err(guar) => return error_response(ecx, guar),
230247
};

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use tracing::{instrument, trace};
1313

1414
use crate::delegate::SolverDelegate;
1515
use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
16-
use crate::solve::assembly::{self, AssembleCandidatesFrom, Candidate};
16+
use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate};
1717
use crate::solve::inspect::ProbeKind;
1818
use crate::solve::{
1919
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
@@ -1338,6 +1338,8 @@ where
13381338
};
13391339
}
13401340

1341+
self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1342+
13411343
// If there are *only* global where bounds, then make sure to return that this
13421344
// is still reported as being proven-via the param-env so that rigid projections
13431345
// operate correctly. Otherwise, drop all global where-bounds before merging the

compiler/rustc_parse/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,8 @@ parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns ar
675675
676676
parse_nul_in_c_str = null characters in C string literals are not supported
677677
678+
parse_or_in_let_chain = `||` operators are not supported in let chain conditions
679+
678680
parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
679681
parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
680682
parse_out_of_range_hex_escape = out of range hex escape

compiler/rustc_parse/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,13 @@ pub(crate) struct ExpectedExpressionFoundLet {
478478
pub comparison: Option<MaybeComparison>,
479479
}
480480

481+
#[derive(Diagnostic)]
482+
#[diag(parse_or_in_let_chain)]
483+
pub(crate) struct OrInLetChain {
484+
#[primary_span]
485+
pub span: Span,
486+
}
487+
481488
#[derive(Subdiagnostic, Clone, Copy)]
482489
#[multipart_suggestion(
483490
parse_maybe_missing_let,

0 commit comments

Comments
 (0)