Skip to content

Commit d5b4c2e

Browse files
committed
Auto merge of #139269 - matthiaskrgr:rollup-pk78gig, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #138992 (literal pattern lowering: use the pattern's type instead of the literal's in `const_to_pat`) - #139211 (interpret: add a version of run_for_validation for &self) - #139235 (`AstValidator` tweaks) - #139237 (Add a dep kind for use of the anon node with zero dependencies) - #139260 (Add dianqk to codegen reviewers) - #139264 (Fix two incorrect turbofish suggestions) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 4f0de4c + 278bc67 commit d5b4c2e

File tree

22 files changed

+475
-262
lines changed

22 files changed

+475
-262
lines changed

Diff for: compiler/rustc_ast_passes/src/ast_validation.rs

+157-156
Large diffs are not rendered by default.

Diff for: compiler/rustc_const_eval/src/interpret/memory.rs

+32-11
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
99
use std::assert_matches::assert_matches;
1010
use std::borrow::{Borrow, Cow};
11+
use std::cell::Cell;
1112
use std::collections::VecDeque;
12-
use std::{fmt, mem, ptr};
13+
use std::{fmt, ptr};
1314

1415
use rustc_abi::{Align, HasDataLayout, Size};
1516
use rustc_ast::Mutability;
@@ -131,7 +132,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> {
131132
/// This stores whether we are currently doing reads purely for the purpose of validation.
132133
/// Those reads do not trigger the machine's hooks for memory reads.
133134
/// Needless to say, this must only be set with great care!
134-
validation_in_progress: bool,
135+
validation_in_progress: Cell<bool>,
135136
}
136137

137138
/// A reference to some allocation that was already bounds-checked for the given region
@@ -158,7 +159,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
158159
alloc_map: M::MemoryMap::default(),
159160
extra_fn_ptr_map: FxIndexMap::default(),
160161
dead_alloc_map: FxIndexMap::default(),
161-
validation_in_progress: false,
162+
validation_in_progress: Cell::new(false),
162163
}
163164
}
164165

@@ -715,15 +716,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
715716
// We want to call the hook on *all* accesses that involve an AllocId, including zero-sized
716717
// accesses. That means we cannot rely on the closure above or the `Some` branch below. We
717718
// do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
718-
if !self.memory.validation_in_progress {
719+
if !self.memory.validation_in_progress.get() {
719720
if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) {
720721
M::before_alloc_read(self, alloc_id)?;
721722
}
722723
}
723724

724725
if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
725726
let range = alloc_range(offset, size);
726-
if !self.memory.validation_in_progress {
727+
if !self.memory.validation_in_progress.get() {
727728
M::before_memory_read(
728729
self.tcx,
729730
&self.machine,
@@ -801,7 +802,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
801802
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
802803
{
803804
let tcx = self.tcx;
804-
let validation_in_progress = self.memory.validation_in_progress;
805+
let validation_in_progress = self.memory.validation_in_progress.get();
805806

806807
let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
807808
let ptr_and_alloc = Self::check_and_deref_ptr(
@@ -1087,23 +1088,43 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10871088
///
10881089
/// We do this so Miri's allocation access tracking does not show the validation
10891090
/// reads as spurious accesses.
1090-
pub fn run_for_validation<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
1091+
pub fn run_for_validation_mut<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
10911092
// This deliberately uses `==` on `bool` to follow the pattern
10921093
// `assert!(val.replace(new) == old)`.
10931094
assert!(
1094-
mem::replace(&mut self.memory.validation_in_progress, true) == false,
1095+
self.memory.validation_in_progress.replace(true) == false,
10951096
"`validation_in_progress` was already set"
10961097
);
10971098
let res = f(self);
10981099
assert!(
1099-
mem::replace(&mut self.memory.validation_in_progress, false) == true,
1100+
self.memory.validation_in_progress.replace(false) == true,
1101+
"`validation_in_progress` was unset by someone else"
1102+
);
1103+
res
1104+
}
1105+
1106+
/// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
1107+
/// suppressed. Needless to say, this must only be set with great care! Cannot be nested.
1108+
///
1109+
/// We do this so Miri's allocation access tracking does not show the validation
1110+
/// reads as spurious accesses.
1111+
pub fn run_for_validation_ref<R>(&self, f: impl FnOnce(&Self) -> R) -> R {
1112+
// This deliberately uses `==` on `bool` to follow the pattern
1113+
// `assert!(val.replace(new) == old)`.
1114+
assert!(
1115+
self.memory.validation_in_progress.replace(true) == false,
1116+
"`validation_in_progress` was already set"
1117+
);
1118+
let res = f(self);
1119+
assert!(
1120+
self.memory.validation_in_progress.replace(false) == true,
11001121
"`validation_in_progress` was unset by someone else"
11011122
);
11021123
res
11031124
}
11041125

11051126
pub(super) fn validation_in_progress(&self) -> bool {
1106-
self.memory.validation_in_progress
1127+
self.memory.validation_in_progress.get()
11071128
}
11081129
}
11091130

@@ -1375,7 +1396,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
13751396
};
13761397
let src_alloc = self.get_alloc_raw(src_alloc_id)?;
13771398
let src_range = alloc_range(src_offset, size);
1378-
assert!(!self.memory.validation_in_progress, "we can't be copying during validation");
1399+
assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation");
13791400
// For the overlapping case, it is crucial that we trigger the read hook
13801401
// before the write hook -- the aliasing model cares about the order.
13811402
M::before_memory_read(

Diff for: compiler/rustc_const_eval/src/interpret/validity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
13221322
trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty);
13231323

13241324
// Run the visitor.
1325-
self.run_for_validation(|ecx| {
1325+
self.run_for_validation_mut(|ecx| {
13261326
let reset_padding = reset_provenance_and_padding && {
13271327
// Check if `val` is actually stored in memory. If not, padding is not even
13281328
// represented and we need not reset it.

Diff for: compiler/rustc_hir_typeck/src/pat.rs

-4
Original file line numberDiff line numberDiff line change
@@ -632,10 +632,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
632632
{
633633
let tcx = self.tcx;
634634
trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
635-
self.typeck_results
636-
.borrow_mut()
637-
.treat_byte_string_as_slice
638-
.insert(lt.hir_id.local_id);
639635
pat_ty =
640636
Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
641637
}

Diff for: compiler/rustc_hir_typeck/src/writeback.rs

-3
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8181
debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
8282
wbcx.typeck_results.used_trait_imports = used_trait_imports;
8383

84-
wbcx.typeck_results.treat_byte_string_as_slice =
85-
mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
86-
8784
debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
8885

8986
self.tcx.arena.alloc(wbcx.typeck_results)

Diff for: compiler/rustc_middle/src/dep_graph/dep_node.rs

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ rustc_query_append!(define_dep_nodes![
8989
/// We use this to create a forever-red node.
9090
[] fn Red() -> (),
9191
[] fn SideEffect() -> (),
92+
[] fn AnonZeroDeps() -> (),
9293
[] fn TraitSelect() -> (),
9394
[] fn CompileCodegenUnit() -> (),
9495
[] fn CompileMonoItem() -> (),

Diff for: compiler/rustc_middle/src/dep_graph/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ impl Deps for DepsType {
5353
const DEP_KIND_NULL: DepKind = dep_kinds::Null;
5454
const DEP_KIND_RED: DepKind = dep_kinds::Red;
5555
const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect;
56+
const DEP_KIND_ANON_ZERO_DEPS: DepKind = dep_kinds::AnonZeroDeps;
5657
const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1;
5758
}
5859

Diff for: compiler/rustc_middle/src/ty/typeck_results.rs

-7
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,6 @@ pub struct TypeckResults<'tcx> {
197197
/// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
198198
pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
199199

200-
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
201-
/// as `&[u8]`, depending on the pattern in which they are used.
202-
/// This hashset records all instances where we behave
203-
/// like this to allow `const_to_pat` to reliably handle this situation.
204-
pub treat_byte_string_as_slice: ItemLocalSet,
205-
206200
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
207201
/// on closure size.
208202
pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
@@ -237,7 +231,6 @@ impl<'tcx> TypeckResults<'tcx> {
237231
closure_fake_reads: Default::default(),
238232
rvalue_scopes: Default::default(),
239233
coroutine_stalled_predicates: Default::default(),
240-
treat_byte_string_as_slice: Default::default(),
241234
closure_size_eval: Default::default(),
242235
offset_of_data: Default::default(),
243236
}

Diff for: compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+2-29
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,13 @@ struct ConstToPat<'tcx> {
5858
span: Span,
5959
id: hir::HirId,
6060

61-
treat_byte_string_as_slice: bool,
62-
6361
c: ty::Const<'tcx>,
6462
}
6563

6664
impl<'tcx> ConstToPat<'tcx> {
6765
fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
6866
trace!(?pat_ctxt.typeck_results.hir_owner);
69-
ConstToPat {
70-
tcx: pat_ctxt.tcx,
71-
typing_env: pat_ctxt.typing_env,
72-
span,
73-
id,
74-
treat_byte_string_as_slice: pat_ctxt
75-
.typeck_results
76-
.treat_byte_string_as_slice
77-
.contains(&id.local_id),
78-
c,
79-
}
67+
ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c }
8068
}
8169

8270
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
@@ -108,8 +96,6 @@ impl<'tcx> ConstToPat<'tcx> {
10896
uv: ty::UnevaluatedConst<'tcx>,
10997
ty: Ty<'tcx>,
11098
) -> Box<Pat<'tcx>> {
111-
trace!(self.treat_byte_string_as_slice);
112-
11399
// It's not *technically* correct to be revealing opaque types here as borrowcheck has
114100
// not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
115101
// during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
@@ -307,21 +293,8 @@ impl<'tcx> ConstToPat<'tcx> {
307293
ty,
308294
);
309295
} else {
310-
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
311-
// matching against references, you can only use byte string literals.
312-
// The typechecker has a special case for byte string literals, by treating them
313-
// as slices. This means we turn `&[T; N]` constants into slice patterns, which
314-
// has no negative effects on pattern matching, even if we're actually matching on
315-
// arrays.
316-
let pointee_ty = match *pointee_ty.kind() {
317-
ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => {
318-
Ty::new_slice(tcx, elem_ty)
319-
}
320-
_ => *pointee_ty,
321-
};
322296
// References have the same valtree representation as their pointee.
323-
let subpattern = self.valtree_to_pat(cv, pointee_ty);
324-
PatKind::Deref { subpattern }
297+
PatKind::Deref { subpattern: self.valtree_to_pat(cv, *pointee_ty) }
325298
}
326299
}
327300
},

Diff for: compiler/rustc_mir_build/src/thir/pattern/mod.rs

+33-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer};
1111
use rustc_errors::codes::*;
1212
use rustc_hir::def::{CtorOf, DefKind, Res};
1313
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
14-
use rustc_hir::{self as hir, RangeEnd};
14+
use rustc_hir::{self as hir, LangItem, RangeEnd};
1515
use rustc_index::Idx;
1616
use rustc_middle::mir::interpret::LitToConstInput;
1717
use rustc_middle::thir::{
@@ -130,7 +130,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
130130

131131
// Lower the endpoint into a temporary `PatKind` that will then be
132132
// deconstructed to obtain the constant value and other data.
133-
let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr);
133+
let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr, None);
134134

135135
// Unpeel any ascription or inline-const wrapper nodes.
136136
loop {
@@ -294,7 +294,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
294294

295295
hir::PatKind::Never => PatKind::Never,
296296

297-
hir::PatKind::Expr(value) => self.lower_pat_expr(value),
297+
hir::PatKind::Expr(value) => self.lower_pat_expr(value, Some(ty)),
298298

299299
hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
300300
let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
@@ -630,7 +630,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
630630
/// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
631631
/// - Inline const blocks (e.g. `const { 1 + 1 }`)
632632
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
633-
fn lower_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
633+
fn lower_pat_expr(
634+
&mut self,
635+
expr: &'tcx hir::PatExpr<'tcx>,
636+
pat_ty: Option<Ty<'tcx>>,
637+
) -> PatKind<'tcx> {
634638
let (lit, neg) = match &expr.kind {
635639
hir::PatExprKind::Path(qpath) => {
636640
return self.lower_path(qpath, expr.hir_id, expr.span).kind;
@@ -641,7 +645,31 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
641645
hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
642646
};
643647

644-
let ct_ty = self.typeck_results.node_type(expr.hir_id);
648+
// We handle byte string literal patterns by using the pattern's type instead of the
649+
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
650+
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
651+
// pattern's type means we'll properly translate it to a slice reference pattern. This works
652+
// because slices and arrays have the same valtree representation.
653+
// HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
654+
// `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
655+
// FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
656+
// superseded by a more general implementation of deref patterns.
657+
let ct_ty = match pat_ty {
658+
Some(pat_ty)
659+
if let ty::Adt(def, _) = *pat_ty.kind()
660+
&& self.tcx.is_lang_item(def.did(), LangItem::String) =>
661+
{
662+
if !self.tcx.features().string_deref_patterns() {
663+
span_bug!(
664+
expr.span,
665+
"matching on `String` went through without enabling string_deref_patterns"
666+
);
667+
}
668+
self.typeck_results.node_type(expr.hir_id)
669+
}
670+
Some(pat_ty) => pat_ty,
671+
None => self.typeck_results.node_type(expr.hir_id),
672+
};
645673
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
646674
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
647675
self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind

Diff for: compiler/rustc_parse/src/parser/item.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -2960,13 +2960,30 @@ impl<'a> Parser<'a> {
29602960
let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
29612961
this.eat_incorrect_doc_comment_for_param_type();
29622962
let mut ty = this.parse_ty_for_param();
2963-
if ty.is_ok()
2964-
&& this.token != token::Comma
2965-
&& this.token != token::CloseDelim(Delimiter::Parenthesis)
2966-
{
2967-
// This wasn't actually a type, but a pattern looking like a type,
2968-
// so we are going to rollback and re-parse for recovery.
2969-
ty = this.unexpected_any();
2963+
2964+
if let Ok(t) = &ty {
2965+
// Check for trailing angle brackets
2966+
if let TyKind::Path(_, Path { segments, .. }) = &t.kind {
2967+
if let Some(segment) = segments.last() {
2968+
if let Some(guar) =
2969+
this.check_trailing_angle_brackets(segment, &[exp!(CloseParen)])
2970+
{
2971+
return Ok((
2972+
dummy_arg(segment.ident, guar),
2973+
Trailing::No,
2974+
UsePreAttrPos::No,
2975+
));
2976+
}
2977+
}
2978+
}
2979+
2980+
if this.token != token::Comma
2981+
&& this.token != token::CloseDelim(Delimiter::Parenthesis)
2982+
{
2983+
// This wasn't actually a type, but a pattern looking like a type,
2984+
// so we are going to rollback and re-parse for recovery.
2985+
ty = this.unexpected_any();
2986+
}
29702987
}
29712988
match ty {
29722989
Ok(ty) => {
@@ -2977,6 +2994,7 @@ impl<'a> Parser<'a> {
29772994
}
29782995
// If this is a C-variadic argument and we hit an error, return the error.
29792996
Err(err) if this.token == token::DotDotDot => return Err(err),
2997+
Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
29802998
// Recover from attempting to parse the argument as a type without pattern.
29812999
Err(err) => {
29823000
err.cancel();

Diff for: compiler/rustc_query_impl/src/plumbing.rs

+11
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,17 @@ macro_rules! define_queries {
870870
}
871871
}
872872

873+
pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindStruct<'tcx> {
874+
DepKindStruct {
875+
is_anon: true,
876+
is_eval_always: false,
877+
fingerprint_style: FingerprintStyle::Opaque,
878+
force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")),
879+
try_load_from_on_disk_cache: None,
880+
name: &"AnonZeroDeps",
881+
}
882+
}
883+
873884
pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
874885
DepKindStruct {
875886
is_anon: true,

0 commit comments

Comments
 (0)