Skip to content

Commit 0164cc1

Browse files
committed
Auto merge of #156041 - JonathanBrouwer:rollup-yc0vOVk, r=JonathanBrouwer
Rollup of 9 pull requests Successful merges: - #149637 (Do not run jump-threading for GPUs) - #154971 (Verify that penultimate segment of enum variant path refers to enum if it has args) - #155186 (Avoid loop_match self-assignment in MIR lowering) - #155948 (Fix order-dependent visibility diagnostics) - #156001 (ssa-range-prop: fix ICE when encountering self-domiating bb) - #155600 (Adds a couple UI tests for polonius) - #155995 (-Zembed-source: also embed external source) - #156019 (Feed cleanups) - #156031 (Return a single diagnostic from `lex_token_trees`.)
2 parents 0469a92 + 47e6437 commit 0164cc1

43 files changed

Lines changed: 775 additions & 280 deletions

File tree

Some content is hidden

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

compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
4747

4848
fn make_file_info(source_file: &SourceFile, embed_source: bool) -> Option<FileInfo> {
4949
let has_md5 = source_file.src_hash.kind == SourceFileHashAlgorithm::Md5;
50-
let has_source = embed_source && source_file.src.is_some();
50+
let has_source = embed_source
51+
&& (source_file.src.is_some() || source_file.external_src.read().get_source().is_some());
5152

5253
if !has_md5 && !has_source {
5354
return None;
@@ -62,6 +63,8 @@ fn make_file_info(source_file: &SourceFile, embed_source: bool) -> Option<FileIn
6263
if embed_source {
6364
if let Some(src) = &source_file.src {
6465
info.source = Some(LineString::String(src.as_bytes().to_vec()));
66+
} else if let Some(src) = source_file.external_src.read().get_source() {
67+
info.source = Some(LineString::String(src.as_bytes().to_vec()));
6568
}
6669
}
6770

@@ -79,19 +82,22 @@ impl DebugContext {
7982
let span = hygiene::walk_chain_collapsed(span, function_span);
8083
match tcx.sess.source_map().lookup_line(span.lo()) {
8184
Ok(SourceFileAndLine { sf: file, line }) => {
82-
let file_id = self.add_source_file(&file);
85+
let file_id = self.add_source_file(tcx, &file);
8386
let line_pos = file.lines()[line];
8487
let col = file.relative_position(span.lo()) - line_pos;
8588

8689
(file_id, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
8790
}
88-
Err(file) => (self.add_source_file(&file), 0, 0),
91+
Err(file) => (self.add_source_file(tcx, &file), 0, 0),
8992
}
9093
}
9194

92-
pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId {
95+
pub(crate) fn add_source_file(&mut self, tcx: TyCtxt<'_>, source_file: &SourceFile) -> FileId {
9396
let cache_key = (source_file.stable_id, source_file.src_hash);
9497
*self.created_files.entry(cache_key).or_insert_with(|| {
98+
if self.embed_source && source_file.src.is_none() {
99+
tcx.sess.source_map().ensure_source_file_source_present(source_file);
100+
}
95101
let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
96102
let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
97103

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::borrow::Cow;
22
use std::fmt::{self, Write};
33
use std::hash::{Hash, Hasher};
44
use std::path::PathBuf;
5-
use std::sync::Arc;
65
use std::{assert_matches, iter, ptr};
76

87
use libc::{c_longlong, c_uint};
@@ -607,8 +606,16 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi
607606
};
608607
let hash_value = hex_encode(source_file.src_hash.hash_bytes());
609608

610-
let source =
611-
cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref());
609+
let mut source = None;
610+
let external_src;
611+
if cx.sess().opts.unstable_opts.embed_source {
612+
source = source_file.src.as_deref().map(String::as_str);
613+
if source.is_none() {
614+
cx.tcx.sess.source_map().ensure_source_file_source_present(source_file);
615+
external_src = source_file.external_src.read();
616+
source = external_src.get_source();
617+
}
618+
}
612619

613620
create_file(DIB(cx), &file_name, &directory, &hash_value, hash_kind, source)
614621
}
@@ -626,7 +633,7 @@ fn create_file<'ll>(
626633
directory: &str,
627634
hash_value: &str,
628635
hash_kind: llvm::ChecksumKind,
629-
source: Option<&Arc<String>>,
636+
source: Option<&str>,
630637
) -> &'ll DIFile {
631638
unsafe {
632639
llvm::LLVMRustDIBuilderCreateFile(

compiler/rustc_data_structures/src/graph/dominators/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,24 @@ impl<Node: Idx> Dominators<Node> {
386386
}
387387
}
388388
}
389+
390+
/// Returns true if `a` **strictly** dominates `b`
391+
///
392+
/// # Panics
393+
///
394+
/// Panics if `b` is unreachable
395+
#[inline]
396+
pub fn strictly_dominates(&self, a: Node, b: Node) -> bool {
397+
match &self.kind {
398+
Kind::Path => a.index() < b.index(),
399+
Kind::General(g) => {
400+
let a = g.time[a];
401+
let b = g.time[b];
402+
assert!(b.start != 0, "node {b:?} is not reachable");
403+
a.start < b.start && b.finish < a.finish
404+
}
405+
}
406+
}
389407
}
390408

391409
/// Describes the number of vertices discovered at the time when processing of a particular vertex

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,28 +2174,51 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21742174
// Case 2. Reference to a variant constructor.
21752175
DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
21762176
let (generics_def_id, index) = if let Some(self_ty) = self_ty {
2177+
// We have something like `<module::Enum>::Variant`.
2178+
21772179
let adt_def = self.probe_adt(span, self_ty).unwrap();
21782180
debug_assert!(adt_def.is_enum());
2181+
2182+
// FIXME: Stating that the last segment (here: `Variant`) is allowed to have
2183+
// generic args is a lie! We should set the index to `None` instead as it's
2184+
// the *self type* that's allowed to have args.
2185+
// HIR typeck's `instantiate_value_path` actually contains a special case to
2186+
// reject args on `DefKind::Ctor` segments (see `is_alias_variant_ctor`).
2187+
// Using `None` here for this should allow us to get rid of that workaround.
2188+
//
2189+
// (For additional context, `DefKind::Variant` segments never actually reach
2190+
// this branch as they're interpreted as `TypeRelative` paths whose lowering
2191+
// routines manually reject args on them).
2192+
21792193
(adt_def.did(), last)
2180-
} else if last >= 1 && segments[last - 1].args.is_some() {
2181-
// Everything but the penultimate segment should have no
2182-
// parameters at all.
2183-
let mut def_id = def_id;
2194+
} else if let [.., second_to_last, _] = segments
2195+
&& second_to_last.args.is_some()
2196+
&& let Res::Def(DefKind::Enum, _) = second_to_last.res
2197+
{
2198+
// We have something like `module::Enum::<…>::Variant`.
2199+
// No segment other than the penultimate one is allowed to have generic args.
2200+
2201+
// We had to check that the second to last segment actually referred to an enum
2202+
// since at this stage it could very well refer to a module in which case we
2203+
// certainly don't want to allow generic args on it!
21842204

21852205
// `DefKind::Ctor` -> `DefKind::Variant`
2186-
if let DefKind::Ctor(..) = kind {
2187-
def_id = tcx.parent(def_id);
2188-
}
2206+
let def_id = match kind {
2207+
DefKind::Ctor(..) => tcx.parent(def_id),
2208+
_ => def_id,
2209+
};
21892210

21902211
// `DefKind::Variant` -> `DefKind::Enum`
21912212
let enum_def_id = tcx.parent(def_id);
2213+
21922214
(enum_def_id, last - 1)
21932215
} else {
2216+
// We have something like `module::Enum::Variant` or `module::Variant`.
2217+
// No segment other than the final one is allowed to have generic args.
2218+
21942219
// FIXME: lint here recommending `Enum::<...>::Variant` form
21952220
// instead of `Enum::Variant::<...>` form.
21962221

2197-
// Everything but the final segment should have no
2198-
// parameters at all.
21992222
let generics = tcx.generics_of(def_id);
22002223
// Variant and struct constructors use the
22012224
// generics of their parent type definition.

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,11 @@ impl Location {
16091609
dominators.dominates(self.block, other.block)
16101610
}
16111611
}
1612+
1613+
#[inline]
1614+
pub fn strictly_dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
1615+
self.block != other.block && dominators.strictly_dominates(self.block, other.block)
1616+
}
16121617
}
16131618

16141619
/// `DefLocation` represents the location of a definition - either an argument or an assignment

compiler/rustc_middle/src/ty/context.rs

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::cmp::Ordering;
1010
use std::env::VarError;
1111
use std::ffi::OsStr;
1212
use std::hash::{Hash, Hasher};
13-
use std::marker::{PhantomData, PointeeSized};
13+
use std::marker::PointeeSized;
1414
use std::ops::{Bound, Deref};
1515
use std::sync::{Arc, OnceLock};
1616
use std::{fmt, iter, mem};
@@ -539,36 +539,14 @@ pub struct FreeRegionInfo {
539539

540540
/// This struct should only be created by `create_def`.
541541
#[derive(Copy, Clone)]
542-
pub struct TyCtxtFeed<'tcx, KEY: Copy> {
542+
pub struct TyCtxtFeed<'tcx, K: Copy> {
543543
pub tcx: TyCtxt<'tcx>,
544544
// Do not allow direct access, as downstream code must not mutate this field.
545-
key: KEY,
545+
key: K,
546546
}
547547

548-
/// Never return a `Feed` from a query. Only queries that create a `DefId` are
549-
/// allowed to feed queries for that `DefId`.
550-
impl<KEY: Copy> !HashStable for TyCtxtFeed<'_, KEY> {}
551-
552-
/// The same as `TyCtxtFeed`, but does not contain a `TyCtxt`.
553-
/// Use this to pass around when you have a `TyCtxt` elsewhere.
554-
/// Just an optimization to save space and not store hundreds of
555-
/// `TyCtxtFeed` in the resolver.
556-
#[derive(Copy, Clone)]
557-
pub struct Feed<'tcx, KEY: Copy> {
558-
_tcx: PhantomData<TyCtxt<'tcx>>,
559-
// Do not allow direct access, as downstream code must not mutate this field.
560-
key: KEY,
561-
}
562-
563-
/// Never return a `Feed` from a query. Only queries that create a `DefId` are
564-
/// allowed to feed queries for that `DefId`.
565-
impl<KEY: Copy> !HashStable for Feed<'_, KEY> {}
566-
567-
impl<T: fmt::Debug + Copy> fmt::Debug for Feed<'_, T> {
568-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569-
self.key.fmt(f)
570-
}
571-
}
548+
/// Only queries that create a `DefId` are allowed to feed queries for that `DefId`.
549+
impl<K: Copy> !HashStable for TyCtxtFeed<'_, K> {}
572550

573551
/// Some workarounds to use cases that cannot use `create_def`.
574552
/// Do not add new ways to create `TyCtxtFeed` without consulting
@@ -622,28 +600,11 @@ impl<'tcx> TyCtxt<'tcx> {
622600
}
623601
}
624602

625-
impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
603+
impl<'tcx, K: Copy> TyCtxtFeed<'tcx, K> {
626604
#[inline(always)]
627-
pub fn key(&self) -> KEY {
605+
pub fn key(&self) -> K {
628606
self.key
629607
}
630-
631-
#[inline(always)]
632-
pub fn downgrade(self) -> Feed<'tcx, KEY> {
633-
Feed { _tcx: PhantomData, key: self.key }
634-
}
635-
}
636-
637-
impl<'tcx, KEY: Copy> Feed<'tcx, KEY> {
638-
#[inline(always)]
639-
pub fn key(&self) -> KEY {
640-
self.key
641-
}
642-
643-
#[inline(always)]
644-
pub fn upgrade(self, tcx: TyCtxt<'tcx>) -> TyCtxtFeed<'tcx, KEY> {
645-
TyCtxtFeed { tcx, key: self.key }
646-
}
647608
}
648609

649610
impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub use self::consts::{
8383
const_lit_matches_ty,
8484
};
8585
pub use self::context::{
86-
CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls,
86+
CtxtInterners, CurrentGcx, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls,
8787
};
8888
pub use self::fold::*;
8989
pub use self::instance::{Instance, InstanceKind, ReifyReason};

compiler/rustc_mir_build/src/builder/expr/into.rs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -326,36 +326,61 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
326326
);
327327

328328
let state_place = scrutinee_place_builder.to_place(this);
329+
let state_result = this.temp(state_ty, expr_span);
330+
let state_result_place = Place::from(state_result);
329331

330332
// This is logic for the labeled block: a block is a drop scope, hence
331333
// `in_scope`, and a labeled block can be broken out of with a `break 'label`,
332334
// hence the `in_breakable_scope`.
333335
//
336+
// The state update is still modeled like `state = 'blk: { ... }`: normal
337+
// match arm results and ordinary breaks to the block are first written to
338+
// `state_result_place`, then written back to `state_place`. This avoids
339+
// building an overlapping assignment like `state = state`.
340+
//
334341
// Then `in_const_continuable_scope` stores information for the lowering of
335-
// `#[const_continue]`, and finally the match is lowered in the standard way.
342+
// `#[const_continue]`, which still updates the actual `state_place` directly
343+
// so it can jump to the statically known next match branch.
336344
unpack!(
337345
body_block = this.in_scope(
338346
(region_scope, source_info),
339347
LintLevel::Inherited,
340348
move |this| {
341-
this.in_breakable_scope(None, state_place, expr_span, |this| {
342-
Some(this.in_const_continuable_scope(
343-
Box::from(arms),
344-
built_tree.clone(),
345-
state_place,
346-
expr_span,
347-
|this| {
348-
this.lower_match_arms(
349-
state_place,
350-
scrutinee_place_builder,
351-
scrutinee_span,
352-
arms,
353-
built_tree,
354-
this.source_info(match_span),
349+
this.in_const_continuable_scope(
350+
Box::from(arms),
351+
built_tree.clone(),
352+
state_place,
353+
expr_span,
354+
|this| {
355+
let block = this
356+
.in_breakable_scope(
357+
None,
358+
state_result_place,
359+
expr_span,
360+
|this| {
361+
Some(this.lower_match_arms(
362+
state_result_place,
363+
scrutinee_place_builder,
364+
scrutinee_span,
365+
arms,
366+
built_tree,
367+
this.source_info(match_span),
368+
))
369+
},
355370
)
356-
},
357-
))
358-
})
371+
.into_block();
372+
373+
this.cfg.push_assign(
374+
block,
375+
source_info,
376+
state_place,
377+
Rvalue::Use(
378+
this.consume_by_copy_or_move(state_result_place),
379+
),
380+
);
381+
block.unit()
382+
},
383+
)
359384
}
360385
)
361386
);

compiler/rustc_mir_transform/src/jump_threading.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ const MAX_COST: u8 = 100;
7676

7777
impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
7878
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
79+
if sess.target.is_like_gpu {
80+
// Jump threading can duplicate calls in control-flow.
81+
// This leads to incorrect code when done for so called "convergent" operations on GPU
82+
// targets, similar to how inline assembly cannot be duplicated on all targets.
83+
// Conservatively prevent this by disabling the pass.
84+
// See also issue #137086.
85+
return false;
86+
}
7987
sess.mir_opt_level() >= 2
8088
}
8189

compiler/rustc_mir_transform/src/lint.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ impl<'a, 'tcx> Lint<'a, 'tcx> {
6666
}
6767
}
6868

69+
/// Checks whether reading `src` while assigning to `dest` would violate MIR's
70+
/// non-overlap requirement for assignments.
71+
fn places_conflict_for_assignment<'tcx>(dest: Place<'tcx>, src: Place<'tcx>) -> bool {
72+
dest == src || (dest.local == src.local && !dest.is_indirect() && !src.is_indirect())
73+
}
74+
6975
impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
7076
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
7177
if context.is_use() {
@@ -96,11 +102,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
96102
// The sides of an assignment must not alias.
97103
if forbid_aliasing {
98104
VisitPlacesWith(|src: Place<'tcx>, _| {
99-
if *dest == src
100-
|| (dest.local == src.local
101-
&& !dest.is_indirect()
102-
&& !src.is_indirect())
103-
{
105+
if places_conflict_for_assignment(*dest, src) {
104106
self.fail(
105107
location,
106108
format!(

0 commit comments

Comments
 (0)