Skip to content

Commit b794652

Browse files
committed
Auto merge of #163157 - JonathanBrouwer:rollup-E6PKhEB, r=JonathanBrouwer
Rollup of 7 pull requests Successful merges: - #147876 (Check tainted_by_error in LateLint) - #162998 (Avoid generating overlapping assignments in DSE) - #163136 (library: prune allowed lints) - #163102 (remove unnecessary restriction with next-solver) - #163106 (emit the constant pattern note for raw identifier bindings) - #163118 (add `feature(field_projections)` fixme) - #163148 (Clean up diagnostic hashing)
2 parents e67cfe8 + cecc101 commit b794652

37 files changed

Lines changed: 271 additions & 152 deletions

‎compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs‎

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -362,44 +362,43 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
362362
DefinitionSiteHiddenType::new_error(tcx, guar)
363363
});
364364

365-
// Sometimes, when the hidden type is an inference variable, it can happen that
366-
// the hidden type becomes the opaque type itself. In this case, this was an opaque
367-
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
368-
// writeback.
369365
if !rcx.infcx.tcx.use_typing_mode_post_typeck_until_borrowck() {
366+
// Sometimes, when the hidden type is an inference variable, it can happen that
367+
// the hidden type becomes the opaque type itself. In this case, this was an opaque
368+
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
369+
// writeback.
370370
if let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) =
371371
hidden_type.ty.skip_binder().kind()
372372
&& def_id == opaque_type_key.def_id.to_def_id()
373373
&& args == opaque_type_key.args
374374
{
375375
continue;
376376
}
377-
}
378377

379-
// Check that all opaque types have the same region parameters if they have the same
380-
// non-region parameters. This is necessary because within the new solver we perform
381-
// various query operations modulo regions, and thus could unsoundly select some impls
382-
// that don't hold.
383-
//
384-
// FIXME(-Znext-solver): This isn't necessary after all. We can remove this check again.
385-
if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
386-
rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key),
387-
(opaque_type_key, hidden_type.span),
388-
) && let Some((arg1, arg2)) = std::iter::zip(
389-
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
390-
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
391-
)
392-
.find(|(arg1, arg2)| arg1 != arg2)
393-
{
394-
errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(
395-
LifetimeMismatchOpaqueParam {
396-
arg: arg1,
397-
prev: arg2,
398-
span: prev_span,
399-
prev_span: hidden_type.span,
400-
},
401-
));
378+
// Check that all opaque types have the same region parameters if they have the same
379+
// non-region parameters. This is necessary because within the new solver we perform
380+
// various query operations modulo regions, and thus could unsoundly select some impls
381+
// that don't hold.
382+
if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
383+
rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key),
384+
(opaque_type_key, hidden_type.span),
385+
) && let Some((arg1, arg2)) = std::iter::zip(
386+
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
387+
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
388+
)
389+
.find(|(arg1, arg2)| arg1 != arg2)
390+
{
391+
errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(
392+
LifetimeMismatchOpaqueParam {
393+
arg: arg1,
394+
prev: arg2,
395+
span: prev_span,
396+
prev_span: hidden_type.span,
397+
},
398+
));
399+
}
402400
}
401+
403402
add_hidden_type(tcx, hidden_types, opaque_type_key.def_id, hidden_type);
404403
}
405404
}

‎compiler/rustc_errors/src/diagnostic.rs‎

Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use std::borrow::Cow;
22
use std::fmt::{self, Debug};
3-
use std::hash::{Hash, Hasher};
3+
use std::hash::Hash;
44
use std::ops::{Deref, DerefMut};
55
use std::panic;
66
use std::path::PathBuf;
77
use std::thread::panicking;
88

99
use rustc_ast::attr::version::RustcVersion;
10-
use rustc_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg};
10+
use rustc_data_structures::stable_hash::StableHasher;
11+
use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg};
12+
use rustc_hashes::Hash128;
1113
use rustc_lint_defs::{Applicability, LintExpectationId};
1214
use rustc_macros::{Decodable, Encodable};
1315
use rustc_span::{DUMMY_SP, Span, Spanned, Symbol};
@@ -305,46 +307,31 @@ impl DiagInner {
305307
}
306308
}
307309

308-
/// Fields used for Hash, and PartialEq trait.
309-
fn keys(
310-
&self,
311-
) -> (
312-
&Level,
313-
&[(DiagMessage, Style)],
314-
&Option<ErrCode>,
315-
&MultiSpan,
316-
&[Subdiag],
317-
&Suggestions,
318-
Vec<(&DiagArgName, &DiagArgValue)>,
319-
&Option<IsLint>,
320-
) {
321-
(
322-
&self.level,
323-
&self.messages,
324-
&self.code,
325-
&self.span,
326-
&self.children,
327-
&self.suggestions,
328-
self.args.iter().collect(),
329-
// omit self.sort_span
330-
&self.is_lint,
331-
// omit self.emitted_at
332-
)
333-
}
334-
}
335-
336-
impl Hash for DiagInner {
337-
fn hash<H>(&self, state: &mut H)
338-
where
339-
H: Hasher,
340-
{
341-
self.keys().hash(state);
342-
}
343-
}
344-
345-
impl PartialEq for DiagInner {
346-
fn eq(&self, other: &Self) -> bool {
347-
self.keys() == other.keys()
310+
/// Hash used to determine if two diagnostics are the same. Used by
311+
/// `DiagCtxtInner::emitted_diagnostics`. Some fields are ignored for the hash.
312+
pub(crate) fn dedup_hash(&self) -> Hash128 {
313+
// Deconstruct to ensure all fields are considered.
314+
let DiagInner {
315+
level,
316+
messages,
317+
code,
318+
lint_id: _, // ignore
319+
span,
320+
children,
321+
suggestions,
322+
args,
323+
sort_span: _, // ignore
324+
is_lint,
325+
long_ty_path: _, // ignore
326+
emitted_at: _, // ignore
327+
} = self;
328+
329+
let hashed_parts =
330+
(level, messages, code, span, children, suggestions, args.as_slice(), is_lint);
331+
332+
let mut hasher = StableHasher::new();
333+
hashed_parts.hash(&mut hasher);
334+
hasher.finish()
348335
}
349336
}
350337

‎compiler/rustc_errors/src/lib.rs‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,10 @@ struct DiagCtxtInner {
325325
emitted_diagnostic_codes: FxIndexSet<ErrCode>,
326326

327327
/// This set contains a hash of every diagnostic that has been emitted by
328-
/// this `DiagCtxt`. These hashes is used to avoid emitting the same error
329-
/// twice.
328+
/// this `DiagCtxt`. These hashes are used to avoid emitting the same error
329+
/// twice. (Because we don't store the diagnostics themselves, two
330+
/// different diagnostics with the same hash value will be considered
331+
/// equivalent. Such collisions should be vanishingly rare...)
330332
emitted_diagnostics: FxHashSet<Hash128>,
331333

332334
/// We only want to emit `recursion_depth_exceeding_limit` once per
@@ -1301,12 +1303,7 @@ impl DiagCtxtInner {
13011303
self.emitted_diagnostic_codes.insert(code);
13021304
}
13031305

1304-
let already_emitted = {
1305-
let mut hasher = StableHasher::new();
1306-
diagnostic.hash(&mut hasher);
1307-
let diagnostic_hash = hasher.finish();
1308-
!self.emitted_diagnostics.insert(diagnostic_hash)
1309-
};
1306+
let already_emitted = !self.emitted_diagnostics.insert(diagnostic.dedup_hash());
13101307

13111308
let is_error = diagnostic.is_error();
13121309
let is_lint = diagnostic.is_lint.is_some();

‎compiler/rustc_lint/src/builtin.rs‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,7 @@ declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]);
148148

149149
impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
150150
fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) {
151-
// The result shouldn't be tainted, otherwise it will cause ICE.
152-
if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind
153-
&& cx.typeck_results().tainted_by_errors.is_none()
154-
{
151+
if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind {
155152
let variant = cx
156153
.typeck_results()
157154
.pat_ty(pat)

‎compiler/rustc_lint/src/late.rs‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,15 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
9999
// The body and typeck results are also set in `visit_fn`.
100100
// Only fetch the results if this is for a new body.
101101
if old_enclosing_body != Some(body_id) && !self.actually_rustdoc {
102-
self.context.typeck_results = Some(self.context.tcx.typeck_body(body_id));
102+
let typeck_results = self.context.tcx.typeck_body(body_id);
103+
104+
// To avoid ICE, skip visiting the body if the typeck_results is tainted.
105+
if typeck_results.tainted_by_errors.is_some() {
106+
self.context.enclosing_body = old_enclosing_body;
107+
self.context.typeck_results = old_typeck_results;
108+
return;
109+
}
110+
self.context.typeck_results = Some(typeck_results);
103111
}
104112

105113
let body = self.context.tcx.hir_body(body_id);
@@ -189,7 +197,16 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
189197
let old_enclosing_body = self.context.enclosing_body.replace(body_id);
190198
let old_typeck_results = self.context.typeck_results;
191199
if !self.actually_rustdoc {
192-
self.context.typeck_results = Some(self.context.tcx.typeck_body(body_id));
200+
let typeck_results = self.context.tcx.typeck_body(body_id);
201+
202+
// To avoid ICE, skip visiting the body if the typeck_results is tainted.
203+
if typeck_results.tainted_by_errors.is_some() {
204+
self.context.enclosing_body = old_enclosing_body;
205+
self.context.typeck_results = old_typeck_results;
206+
return;
207+
}
208+
209+
self.context.typeck_results = Some(typeck_results);
193210
}
194211
let body = self.context.tcx.hir_body(body_id);
195212
lint_callback!(self, check_fn, fk, decl, body, span, id);

‎compiler/rustc_mir_build/src/thir/pattern/check_match.rs‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -678,10 +678,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
678678

679679
if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, pat) {
680680
let span = self.tcx.def_span(def_id);
681-
let variable = self.tcx.item_name(def_id).to_string();
681+
let name = self.tcx.item_name(def_id);
682682
// When we encounter a constant as the binding name, point at the `const` definition.
683-
interpreted_as_const = Some(InterpretedAsConst { span, variable: variable.clone() });
684-
interpreted_as_const_sugg = Some(InterpretedAsConstSugg { span: pat.span, variable });
683+
interpreted_as_const =
684+
Some(InterpretedAsConst { span, variable: name.to_ident_string() });
685+
// The suggested name is suffixed, so it is never a keyword and never needs `r#`.
686+
interpreted_as_const_sugg =
687+
Some(InterpretedAsConstSugg { span: pat.span, variable: name.to_string() });
685688
} else if let PatKind::Constant { .. } = pat.kind
686689
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
687690
{
@@ -1231,7 +1234,11 @@ fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx>
12311234
// `::` namespace separators or other non-identifier characters.
12321235
if let ty::AliasConstKind::Free { def_id } = pat.extra.as_deref()?.expanded_const?
12331236
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span)
1234-
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
1237+
&& snippet
1238+
.strip_prefix("r#")
1239+
.unwrap_or(&snippet)
1240+
.chars()
1241+
.all(|c| c.is_alphanumeric() || c == '_')
12351242
{
12361243
Some(def_id)
12371244
} else {

‎compiler/rustc_mir_transform/src/dead_store_elimination.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
6363
loc,
6464
);
6565

66+
// The logic in LivenessTransferFunction isn't quite what we need; it ignores call
67+
// destinations that are just locals because they are killed by the call, which makes
68+
// it eligible to be moved-from in the argument list. That's backwards.
69+
if !destination.is_indirect() {
70+
state.insert(destination.local);
71+
}
72+
6673
for (index, arg) in args.iter().map(|a| &a.node).enumerate().rev() {
6774
if let Operand::Copy(place) = *arg
6875
&& !place.is_indirect()

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14941494
obligation: &PolyTraitObligation<'tcx>,
14951495
candidates: &mut SelectionCandidateSet<'tcx>,
14961496
) {
1497+
// FIXME(field_projections): We should not use `evaluate_obligation` in
1498+
// the trait solver. Doing so means we don't track overflow and cycles properly
1499+
// encountering query cycles instead.
14971500
if let ty::Adt(def, args) = obligation.predicate.self_ty().skip_binder().kind()
14981501
&& let Some(FieldInfo { base, ty, .. }) =
14991502
def.field_representing_type_info(self.tcx(), args)

‎library/alloc/src/alloc.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,6 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
663663

664664
#[cfg(not(no_global_oom_handling))]
665665
#[doc(hidden)]
666-
#[allow(unused_attributes)]
667666
#[unstable(feature = "alloc_internals", issue = "none")]
668667
pub mod __alloc_error_handler {
669668
// called via generated `__rust_alloc_error_handler` if there is no

‎library/alloc/src/lib.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
5959
#![allow(unused_features)]
6060
#![allow(incomplete_features)]
61-
#![allow(unused_attributes)]
6261
#![expect(clippy::partialeq_ne_impl, reason = "we need to implement ne for a lot of alloc types")]
6362
#![stable(feature = "alloc", since = "1.36.0")]
6463
#![doc(

0 commit comments

Comments
 (0)