Skip to content

Commit 940d00f

Browse files
committed
Auto merge of rust-lang#107185 - compiler-errors:rollup-wkomjma, r=compiler-errors
Rollup of 8 pull requests Successful merges: - rust-lang#103418 (Add `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` to future-incompat report) - rust-lang#106113 (llvm-wrapper: adapt for LLVM API change) - rust-lang#106144 (Improve the documentation of `black_box`) - rust-lang#106578 (Label closure captures/generator locals that make opaque types recursive) - rust-lang#106749 (Update cc to 1.0.77) - rust-lang#106935 (Fix `SingleUseLifetime` ICE) - rust-lang#107015 (Re-enable building rust-analyzer on riscv64) - rust-lang#107029 (Add new bootstrap members to triagebot.toml) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 85da15c + 31f9f21 commit 940d00f

21 files changed

+577
-51
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -551,9 +551,9 @@ version = "0.1.0"
551551

552552
[[package]]
553553
name = "cc"
554-
version = "1.0.76"
554+
version = "1.0.77"
555555
source = "registry+https://github.com/rust-lang/crates.io-index"
556-
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
556+
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
557557
dependencies = [
558558
"jobserver",
559559
]

compiler/rustc_hir_analysis/src/check/check.rs

+53-6
Original file line numberDiff line numberDiff line change
@@ -1391,11 +1391,15 @@ fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed
13911391
///
13921392
/// If all the return expressions evaluate to `!`, then we explain that the error will go away
13931393
/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
1394-
fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> ErrorGuaranteed {
1394+
fn opaque_type_cycle_error(
1395+
tcx: TyCtxt<'_>,
1396+
opaque_def_id: LocalDefId,
1397+
span: Span,
1398+
) -> ErrorGuaranteed {
13951399
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
13961400

13971401
let mut label = false;
1398-
if let Some((def_id, visitor)) = get_owner_return_paths(tcx, def_id) {
1402+
if let Some((def_id, visitor)) = get_owner_return_paths(tcx, opaque_def_id) {
13991403
let typeck_results = tcx.typeck(def_id);
14001404
if visitor
14011405
.returns
@@ -1431,28 +1435,71 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
14311435
.filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
14321436
.filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
14331437
{
1434-
struct OpaqueTypeCollector(Vec<DefId>);
1438+
#[derive(Default)]
1439+
struct OpaqueTypeCollector {
1440+
opaques: Vec<DefId>,
1441+
closures: Vec<DefId>,
1442+
}
14351443
impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector {
14361444
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
14371445
match *t.kind() {
14381446
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
1439-
self.0.push(def);
1447+
self.opaques.push(def);
14401448
ControlFlow::Continue(())
14411449
}
1450+
ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => {
1451+
self.closures.push(def_id);
1452+
t.super_visit_with(self)
1453+
}
14421454
_ => t.super_visit_with(self),
14431455
}
14441456
}
14451457
}
1446-
let mut visitor = OpaqueTypeCollector(vec![]);
1458+
1459+
let mut visitor = OpaqueTypeCollector::default();
14471460
ty.visit_with(&mut visitor);
1448-
for def_id in visitor.0 {
1461+
for def_id in visitor.opaques {
14491462
let ty_span = tcx.def_span(def_id);
14501463
if !seen.contains(&ty_span) {
14511464
err.span_label(ty_span, &format!("returning this opaque type `{ty}`"));
14521465
seen.insert(ty_span);
14531466
}
14541467
err.span_label(sp, &format!("returning here with type `{ty}`"));
14551468
}
1469+
1470+
for closure_def_id in visitor.closures {
1471+
let Some(closure_local_did) = closure_def_id.as_local() else { continue; };
1472+
let typeck_results = tcx.typeck(closure_local_did);
1473+
1474+
let mut label_match = |ty: Ty<'_>, span| {
1475+
for arg in ty.walk() {
1476+
if let ty::GenericArgKind::Type(ty) = arg.unpack()
1477+
&& let ty::Alias(ty::Opaque, ty::AliasTy { def_id: captured_def_id, .. }) = *ty.kind()
1478+
&& captured_def_id == opaque_def_id.to_def_id()
1479+
{
1480+
err.span_label(
1481+
span,
1482+
format!(
1483+
"{} captures itself here",
1484+
tcx.def_kind(closure_def_id).descr(closure_def_id)
1485+
),
1486+
);
1487+
}
1488+
}
1489+
};
1490+
1491+
// Label any closure upvars that capture the opaque
1492+
for capture in typeck_results.closure_min_captures_flattened(closure_local_did)
1493+
{
1494+
label_match(capture.place.ty(), capture.get_path_span(tcx));
1495+
}
1496+
// Label any generator locals that capture the opaque
1497+
for interior_ty in
1498+
typeck_results.generator_interior_types.as_ref().skip_binder()
1499+
{
1500+
label_match(interior_ty.ty, interior_ty.span);
1501+
}
1502+
}
14561503
}
14571504
}
14581505
}

compiler/rustc_lint/src/context.rs

+26-21
Original file line numberDiff line numberDiff line change
@@ -825,34 +825,39 @@ pub trait LintContext: Sized {
825825
debug!(?param_span, ?use_span, ?deletion_span);
826826
db.span_label(param_span, "this lifetime...");
827827
db.span_label(use_span, "...is used only here");
828-
let msg = "elide the single-use lifetime";
829-
let (use_span, replace_lt) = if elide {
830-
let use_span = sess.source_map().span_extend_while(
831-
use_span,
832-
char::is_whitespace,
833-
).unwrap_or(use_span);
834-
(use_span, String::new())
835-
} else {
836-
(use_span, "'_".to_owned())
837-
};
838-
db.multipart_suggestion(
839-
msg,
840-
vec![(deletion_span, String::new()), (use_span, replace_lt)],
841-
Applicability::MachineApplicable,
842-
);
828+
if let Some(deletion_span) = deletion_span {
829+
let msg = "elide the single-use lifetime";
830+
let (use_span, replace_lt) = if elide {
831+
let use_span = sess.source_map().span_extend_while(
832+
use_span,
833+
char::is_whitespace,
834+
).unwrap_or(use_span);
835+
(use_span, String::new())
836+
} else {
837+
(use_span, "'_".to_owned())
838+
};
839+
debug!(?deletion_span, ?use_span);
840+
db.multipart_suggestion(
841+
msg,
842+
vec![(deletion_span, String::new()), (use_span, replace_lt)],
843+
Applicability::MachineApplicable,
844+
);
845+
}
843846
},
844847
BuiltinLintDiagnostics::SingleUseLifetime {
845848
param_span: _,
846849
use_span: None,
847850
deletion_span,
848851
} => {
849852
debug!(?deletion_span);
850-
db.span_suggestion(
851-
deletion_span,
852-
"elide the unused lifetime",
853-
"",
854-
Applicability::MachineApplicable,
855-
);
853+
if let Some(deletion_span) = deletion_span {
854+
db.span_suggestion(
855+
deletion_span,
856+
"elide the unused lifetime",
857+
"",
858+
Applicability::MachineApplicable,
859+
);
860+
}
856861
},
857862
BuiltinLintDiagnostics::NamedArgumentUsedPositionally{ position_sp_to_replace, position_sp_for_msg, named_arg_sp, named_arg_name, is_formatting_arg} => {
858863
db.span_label(named_arg_sp, "this named argument is referred to by position in formatting string");

compiler/rustc_lint_defs/src/builtin.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3015,6 +3015,7 @@ declare_lint! {
30153015
"trailing semicolon in macro body used as expression",
30163016
@future_incompatible = FutureIncompatibleInfo {
30173017
reference: "issue #79813 <https://github.com/rust-lang/rust/issues/79813>",
3018+
reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
30183019
};
30193020
}
30203021

compiler/rustc_lint_defs/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ pub enum BuiltinLintDiagnostics {
503503
param_span: Span,
504504
/// Span of the code that should be removed when eliding this lifetime.
505505
/// This span should include leading or trailing comma.
506-
deletion_span: Span,
506+
deletion_span: Option<Span>,
507507
/// Span of the single use, or None if the lifetime is never used.
508508
/// If true, the lifetime will be fully elided.
509509
use_span: Option<(Span, bool)>,

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+9-11
Original file line numberDiff line numberDiff line change
@@ -1349,18 +1349,16 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
13491349
return LLVMBFloatTypeKind;
13501350
case Type::X86_AMXTyID:
13511351
return LLVMX86_AMXTypeKind;
1352-
#if LLVM_VERSION_GE(15, 0) && LLVM_VERSION_LT(16, 0)
1353-
case Type::DXILPointerTyID:
1354-
report_fatal_error("Rust does not support DirectX typed pointers.");
1355-
break;
1356-
#endif
1357-
#if LLVM_VERSION_GE(16, 0)
1358-
case Type::TypedPointerTyID:
1359-
report_fatal_error("Rust does not support typed pointers.");
1360-
break;
1361-
#endif
1352+
default:
1353+
{
1354+
std::string error;
1355+
llvm::raw_string_ostream stream(error);
1356+
stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID()
1357+
<< " for the type: " << *unwrap(Ty);
1358+
stream.flush();
1359+
report_fatal_error(error.c_str());
1360+
}
13621361
}
1363-
report_fatal_error("Unhandled TypeID.");
13641362
}
13651363

13661364
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)

compiler/rustc_resolve/src/late/diagnostics.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -2188,15 +2188,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
21882188
let deletion_span = || {
21892189
if params.len() == 1 {
21902190
// if sole lifetime, remove the entire `<>` brackets
2191-
generics_span
2191+
Some(generics_span)
21922192
} else if param_index == 0 {
21932193
// if removing within `<>` brackets, we also want to
21942194
// delete a leading or trailing comma as appropriate
2195-
param.span().to(params[param_index + 1].span().shrink_to_lo())
2195+
match (
2196+
param.span().find_ancestor_inside(generics_span),
2197+
params[param_index + 1].span().find_ancestor_inside(generics_span),
2198+
) {
2199+
(Some(param_span), Some(next_param_span)) => {
2200+
Some(param_span.to(next_param_span.shrink_to_lo()))
2201+
}
2202+
_ => None,
2203+
}
21962204
} else {
21972205
// if removing within `<>` brackets, we also want to
21982206
// delete a leading or trailing comma as appropriate
2199-
params[param_index - 1].span().shrink_to_hi().to(param.span())
2207+
match (
2208+
param.span().find_ancestor_inside(generics_span),
2209+
params[param_index - 1].span().find_ancestor_inside(generics_span),
2210+
) {
2211+
(Some(param_span), Some(prev_param_span)) => {
2212+
Some(prev_param_span.shrink_to_hi().to(param_span))
2213+
}
2214+
_ => None,
2215+
}
22002216
}
22012217
};
22022218
match use_set {

library/core/src/hint.rs

+69
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,75 @@ pub fn spin_loop() {
219219
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
220220
///
221221
/// [`std::convert::identity`]: crate::convert::identity
222+
///
223+
/// # When is this useful?
224+
///
225+
/// First and foremost: `black_box` does _not_ guarantee any exact behavior and, in some cases, may
226+
/// do nothing at all. As such, it **must not be relied upon to control critical program behavior.**
227+
/// This _immediately_ precludes any direct use of this function for cryptographic or security
228+
/// purposes.
229+
///
230+
/// While not suitable in those mission-critical cases, `back_box`'s functionality can generally be
231+
/// relied upon for benchmarking, and should be used there. It will try to ensure that the
232+
/// compiler doesn't optimize away part of the intended test code based on context. For
233+
/// example:
234+
///
235+
/// ```
236+
/// fn contains(haystack: &[&str], needle: &str) -> bool {
237+
/// haystack.iter().any(|x| x == &needle)
238+
/// }
239+
///
240+
/// pub fn benchmark() {
241+
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
242+
/// let needle = "ghi";
243+
/// for _ in 0..10 {
244+
/// contains(&haystack, needle);
245+
/// }
246+
/// }
247+
/// ```
248+
///
249+
/// The compiler could theoretically make optimizations like the following:
250+
///
251+
/// - `needle` and `haystack` are always the same, move the call to `contains` outside the loop and
252+
/// delete the loop
253+
/// - Inline `contains`
254+
/// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove
255+
/// the call and replace with `true`
256+
/// - Nothing is done with the result of `contains`: delete this function call entirely
257+
/// - `benchmark` now has no purpose: delete this function
258+
///
259+
/// It is not likely that all of the above happens, but the compiler is definitely able to make some
260+
/// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes
261+
/// in:
262+
///
263+
/// ```
264+
/// use std::hint::black_box;
265+
///
266+
/// // Same `contains` function
267+
/// fn contains(haystack: &[&str], needle: &str) -> bool {
268+
/// haystack.iter().any(|x| x == &needle)
269+
/// }
270+
///
271+
/// pub fn benchmark() {
272+
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
273+
/// let needle = "ghi";
274+
/// for _ in 0..10 {
275+
/// // Adjust our benchmark loop contents
276+
/// black_box(contains(black_box(&haystack), black_box(needle)));
277+
/// }
278+
/// }
279+
/// ```
280+
///
281+
/// This essentially tells the compiler to block optimizations across any calls to `black_box`. So,
282+
/// it now:
283+
///
284+
/// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be
285+
/// optimized based on argument values
286+
/// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot
287+
/// optimize this away
288+
///
289+
/// This makes our benchmark much more realistic to how the function would be used in situ, where
290+
/// arguments are usually not known at compile time and the result is used in some way.
222291
#[inline]
223292
#[stable(feature = "bench_black_box", since = "1.66.0")]
224293
#[rustc_const_unstable(feature = "const_black_box", issue = "none")]

src/bootstrap/dist.rs

-6
Original file line numberDiff line numberDiff line change
@@ -1130,12 +1130,6 @@ impl Step for RustAnalyzer {
11301130
let compiler = self.compiler;
11311131
let target = self.target;
11321132

1133-
if target.contains("riscv64") {
1134-
// riscv64 currently has an LLVM bug that makes rust-analyzer unable
1135-
// to build. See #74813 for details.
1136-
return None;
1137-
}
1138-
11391133
let rust_analyzer = builder
11401134
.ensure(tool::RustAnalyzer { compiler, target })
11411135
.expect("rust-analyzer always builds");
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![feature(generators, generator_trait)]
2+
3+
use std::ops::{Generator, GeneratorState};
4+
5+
fn foo() -> impl Generator<Yield = (), Return = ()> {
6+
//~^ ERROR cannot resolve opaque type
7+
//~| NOTE recursive opaque type
8+
//~| NOTE in this expansion of desugaring of
9+
|| {
10+
//~^ NOTE returning here
11+
let mut gen = Box::pin(foo());
12+
//~^ NOTE generator captures itself here
13+
let mut r = gen.as_mut().resume(());
14+
while let GeneratorState::Yielded(v) = r {
15+
yield v;
16+
r = gen.as_mut().resume(());
17+
}
18+
}
19+
}
20+
21+
fn main() {
22+
foo();
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0720]: cannot resolve opaque type
2+
--> $DIR/recursive-generator.rs:5:13
3+
|
4+
LL | fn foo() -> impl Generator<Yield = (), Return = ()> {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type
6+
...
7+
LL | / || {
8+
LL | |
9+
LL | | let mut gen = Box::pin(foo());
10+
| | ------- generator captures itself here
11+
LL | |
12+
... |
13+
LL | | }
14+
LL | | }
15+
| |_____- returning here with type `[generator@$DIR/recursive-generator.rs:9:5: 9:7]`
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0720`.

0 commit comments

Comments
 (0)