Skip to content

Commit e324cf0

Browse files
committedOct 30, 2023
Auto merge of #117387 - fmease:rollup-5958nsf, r=fmease
Rollup of 8 pull requests Successful merges: - #117147 (Print variadic argument pattern in HIR pretty printer) - #117177 (Use ImageDataType for allocation type) - #117205 (Allows `#[diagnostic::on_unimplemented]` attributes to have multiple) - #117350 (coverage: Replace manual debug indents with nested tracing spans in `counters`) - #117365 (Stabilize inline asm usage with rustc_codegen_cranelift) - #117371 (Ignore RPIT duplicated lifetimes in `opaque_types_defined_by`) - #117382 (Fail typeck for illegal break-with-value) - #117385 (deduce_param_attrs: explain a read-only case) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 91bbdd9 + 288ab16 commit e324cf0

File tree

32 files changed

+386
-459
lines changed

32 files changed

+386
-459
lines changed
 

‎compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,14 +1742,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17421742
}
17431743

17441744
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
1745-
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
1746-
// as they are not explicit in HIR/Ty function signatures.
1747-
// (instead, the `c_variadic` flag is set to `true`)
1748-
let mut inputs = &decl.inputs[..];
1749-
if decl.c_variadic() {
1750-
inputs = &inputs[..inputs.len() - 1];
1751-
}
1752-
self.arena.alloc_from_iter(inputs.iter().map(|param| match param.pat.kind {
1745+
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
17531746
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
17541747
_ => Ident::new(kw::Empty, self.lower_span(param.pat.span)),
17551748
}))

‎compiler/rustc_codegen_cranelift/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ smallvec = "1.8.1"
3535

3636
[features]
3737
# Enable features not ready to be enabled when compiling as part of rustc
38-
unstable-features = ["jit", "inline_asm"]
38+
unstable-features = ["jit", "inline_asm_sym"]
3939
jit = ["cranelift-jit", "libloading"]
40-
inline_asm = []
40+
inline_asm_sym = []
4141

4242
[package.metadata.rust-analyzer]
4343
rustc_private = true

‎compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,6 @@ version = "0.2.15"
4040
source = "registry+https://github.com/rust-lang/crates.io-index"
4141
checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9"
4242

43-
[[package]]
44-
name = "auxv"
45-
version = "0.3.3"
46-
source = "registry+https://github.com/rust-lang/crates.io-index"
47-
checksum = "e50430f9beb8effb02399fa81c76eeaa26b05e4f03b09285cad8d079c1af5a3d"
48-
dependencies = [
49-
"byteorder",
50-
"gcc",
51-
]
52-
53-
[[package]]
54-
name = "byteorder"
55-
version = "1.4.3"
56-
source = "registry+https://github.com/rust-lang/crates.io-index"
57-
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
58-
5943
[[package]]
6044
name = "cc"
6145
version = "1.0.79"
@@ -388,7 +372,6 @@ dependencies = [
388372
name = "std_detect"
389373
version = "0.1.5"
390374
dependencies = [
391-
"auxv",
392375
"cfg-if",
393376
"compiler_builtins",
394377
"cupid",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[toolchain]
2-
channel = "nightly-2023-10-21"
2+
channel = "nightly-2023-10-29"
33
components = ["rust-src", "rustc-dev", "llvm-tools"]

‎compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ set -e
44
# Compiletest expects all standard library paths to start with /rustc/FAKE_PREFIX.
55
# CG_CLIF_STDLIB_REMAP_PATH_PREFIX will cause cg_clif's build system to pass
66
# --remap-path-prefix to handle this.
7-
CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build
7+
# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we
8+
# the LLVM backend isn't compiled in here.
9+
CG_CLIF_FORCE_GNU_AS=1 CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build
810

911
echo "[SETUP] Rust fork"
1012
git clone https://github.com/rust-lang/rust.git || true

‎compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src}
1111
cp ../Cargo.* compiler/rustc_codegen_cranelift/
1212
cp -r ../src compiler/rustc_codegen_cranelift/src
1313

14-
./x.py build --stage 1 library/std
14+
# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we
15+
# the LLVM backend isn't compiled in here.
16+
CG_CLIF_FORCE_GNU_AS=1 ./x.py build --stage 1 library/std
1517
popd

‎compiler/rustc_codegen_cranelift/src/global_asm.rs

Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
4646
global_asm.push_str(&string);
4747
}
4848
InlineAsmOperand::SymFn { anon_const } => {
49+
if cfg!(not(feature = "inline_asm_sym")) {
50+
tcx.sess.span_err(
51+
item.span,
52+
"asm! and global_asm! sym operands are not yet supported",
53+
);
54+
}
55+
4956
let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
5057
let instance = match ty.kind() {
5158
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
@@ -57,6 +64,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
5764
global_asm.push_str(symbol.name);
5865
}
5966
InlineAsmOperand::SymStatic { path: _, def_id } => {
67+
if cfg!(not(feature = "inline_asm_sym")) {
68+
tcx.sess.span_err(
69+
item.span,
70+
"asm! and global_asm! sym operands are not yet supported",
71+
);
72+
}
73+
6074
let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
6175
let symbol = tcx.symbol_name(instance);
6276
global_asm.push_str(symbol.name);
@@ -81,22 +95,23 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
8195
}
8296
}
8397

84-
pub(crate) fn asm_supported(tcx: TyCtxt<'_>) -> bool {
85-
cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows
86-
}
87-
8898
#[derive(Debug)]
8999
pub(crate) struct GlobalAsmConfig {
90-
asm_enabled: bool,
91100
assembler: PathBuf,
101+
target: String,
92102
pub(crate) output_filenames: Arc<OutputFilenames>,
93103
}
94104

95105
impl GlobalAsmConfig {
96106
pub(crate) fn new(tcx: TyCtxt<'_>) -> Self {
97107
GlobalAsmConfig {
98-
asm_enabled: asm_supported(tcx),
99108
assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"),
109+
target: match &tcx.sess.opts.target_triple {
110+
rustc_target::spec::TargetTriple::TargetTriple(triple) => triple.clone(),
111+
rustc_target::spec::TargetTriple::TargetJson { path_for_rustdoc, .. } => {
112+
path_for_rustdoc.to_str().unwrap().to_owned()
113+
}
114+
},
100115
output_filenames: tcx.output_filenames(()).clone(),
101116
}
102117
}
@@ -111,21 +126,6 @@ pub(crate) fn compile_global_asm(
111126
return Ok(None);
112127
}
113128

114-
if !config.asm_enabled {
115-
if global_asm.contains("__rust_probestack") {
116-
return Ok(None);
117-
}
118-
119-
if cfg!(not(feature = "inline_asm")) {
120-
return Err(
121-
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift"
122-
.to_owned(),
123-
);
124-
} else {
125-
return Err("asm! and global_asm! are not yet supported on Windows".to_owned());
126-
}
127-
}
128-
129129
// Remove all LLVM style comments
130130
let mut global_asm = global_asm
131131
.lines()
@@ -134,20 +134,67 @@ pub(crate) fn compile_global_asm(
134134
.join("\n");
135135
global_asm.push('\n');
136136

137-
let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
137+
let global_asm_object_file = add_file_stem_postfix(
138+
config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)),
139+
".asm",
140+
);
138141

139142
// Assemble `global_asm`
140-
let global_asm_object_file = add_file_stem_postfix(output_object_file, ".asm");
141-
let mut child = Command::new(&config.assembler)
142-
.arg("-o")
143-
.arg(&global_asm_object_file)
144-
.stdin(Stdio::piped())
145-
.spawn()
146-
.expect("Failed to spawn `as`.");
147-
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
148-
let status = child.wait().expect("Failed to wait for `as`.");
149-
if !status.success() {
150-
return Err(format!("Failed to assemble `{}`", global_asm));
143+
if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() {
144+
let mut child = Command::new(&config.assembler)
145+
.arg("-o")
146+
.arg(&global_asm_object_file)
147+
.stdin(Stdio::piped())
148+
.spawn()
149+
.expect("Failed to spawn `as`.");
150+
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
151+
let status = child.wait().expect("Failed to wait for `as`.");
152+
if !status.success() {
153+
return Err(format!("Failed to assemble `{}`", global_asm));
154+
}
155+
} else {
156+
let mut child = Command::new(std::env::current_exe().unwrap())
157+
.arg("--target")
158+
.arg(&config.target)
159+
.arg("--crate-type")
160+
.arg("staticlib")
161+
.arg("--emit")
162+
.arg("obj")
163+
.arg("-o")
164+
.arg(&global_asm_object_file)
165+
.arg("-")
166+
.arg("-Abad_asm_style")
167+
.arg("-Zcodegen-backend=llvm")
168+
.stdin(Stdio::piped())
169+
.spawn()
170+
.expect("Failed to spawn `as`.");
171+
let mut stdin = child.stdin.take().unwrap();
172+
stdin
173+
.write_all(
174+
br####"
175+
#![feature(decl_macro, no_core, rustc_attrs)]
176+
#![allow(internal_features)]
177+
#![no_core]
178+
#[rustc_builtin_macro]
179+
#[rustc_macro_transparency = "semitransparent"]
180+
macro global_asm() { /* compiler built-in */ }
181+
global_asm!(r###"
182+
"####,
183+
)
184+
.unwrap();
185+
stdin.write_all(global_asm.as_bytes()).unwrap();
186+
stdin
187+
.write_all(
188+
br####"
189+
"###);
190+
"####,
191+
)
192+
.unwrap();
193+
std::mem::drop(stdin);
194+
let status = child.wait().expect("Failed to wait for `as`.");
195+
if !status.success() {
196+
return Err(format!("Failed to assemble `{}`", global_asm));
197+
}
151198
}
152199

153200
Ok(Some(global_asm_object_file))

‎compiler/rustc_codegen_cranelift/src/inline_asm.rs

Lines changed: 11 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_span::sym;
88
use rustc_target::asm::*;
99
use target_lexicon::BinaryFormat;
1010

11-
use crate::global_asm::asm_supported;
1211
use crate::prelude::*;
1312

1413
enum CInlineAsmOperand<'tcx> {
@@ -45,208 +44,11 @@ pub(crate) fn codegen_inline_asm<'tcx>(
4544
) {
4645
// FIXME add .eh_frame unwind info directives
4746

48-
if !asm_supported(fx.tcx) {
49-
if template.is_empty() {
50-
let destination_block = fx.get_block(destination.unwrap());
51-
fx.bcx.ins().jump(destination_block, &[]);
52-
return;
53-
}
54-
55-
// Used by panic_abort
56-
if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) {
57-
fx.bcx.ins().trap(TrapCode::User(1));
58-
return;
59-
}
60-
61-
// Used by stdarch
62-
if template[0] == InlineAsmTemplatePiece::String("mov ".to_string())
63-
&& matches!(
64-
template[1],
65-
InlineAsmTemplatePiece::Placeholder {
66-
operand_idx: 0,
67-
modifier: Some('r'),
68-
span: _
69-
}
70-
)
71-
&& template[2] == InlineAsmTemplatePiece::String(", rbx".to_string())
72-
&& template[3] == InlineAsmTemplatePiece::String("\n".to_string())
73-
&& template[4] == InlineAsmTemplatePiece::String("cpuid".to_string())
74-
&& template[5] == InlineAsmTemplatePiece::String("\n".to_string())
75-
&& template[6] == InlineAsmTemplatePiece::String("xchg ".to_string())
76-
&& matches!(
77-
template[7],
78-
InlineAsmTemplatePiece::Placeholder {
79-
operand_idx: 0,
80-
modifier: Some('r'),
81-
span: _
82-
}
83-
)
84-
&& template[8] == InlineAsmTemplatePiece::String(", rbx".to_string())
85-
{
86-
assert_eq!(operands.len(), 4);
87-
let (leaf, eax_place) = match operands[1] {
88-
InlineAsmOperand::InOut {
89-
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
90-
late: _,
91-
ref in_value,
92-
out_place: Some(out_place),
93-
} => (
94-
crate::base::codegen_operand(fx, in_value).load_scalar(fx),
95-
crate::base::codegen_place(fx, out_place),
96-
),
97-
_ => unreachable!(),
98-
};
99-
let ebx_place = match operands[0] {
100-
InlineAsmOperand::Out {
101-
reg:
102-
InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86(
103-
X86InlineAsmRegClass::reg,
104-
)),
105-
late: _,
106-
place: Some(place),
107-
} => crate::base::codegen_place(fx, place),
108-
_ => unreachable!(),
109-
};
110-
let (sub_leaf, ecx_place) = match operands[2] {
111-
InlineAsmOperand::InOut {
112-
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
113-
late: _,
114-
ref in_value,
115-
out_place: Some(out_place),
116-
} => (
117-
crate::base::codegen_operand(fx, in_value).load_scalar(fx),
118-
crate::base::codegen_place(fx, out_place),
119-
),
120-
_ => unreachable!(),
121-
};
122-
let edx_place = match operands[3] {
123-
InlineAsmOperand::Out {
124-
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
125-
late: _,
126-
place: Some(place),
127-
} => crate::base::codegen_place(fx, place),
128-
_ => unreachable!(),
129-
};
130-
131-
let (eax, ebx, ecx, edx) = crate::intrinsics::codegen_cpuid_call(fx, leaf, sub_leaf);
132-
133-
eax_place.write_cvalue(fx, CValue::by_val(eax, fx.layout_of(fx.tcx.types.u32)));
134-
ebx_place.write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32)));
135-
ecx_place.write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32)));
136-
edx_place.write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32)));
137-
let destination_block = fx.get_block(destination.unwrap());
138-
fx.bcx.ins().jump(destination_block, &[]);
139-
return;
140-
}
141-
142-
// Used by compiler-builtins
143-
if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") {
144-
// ___chkstk, ___chkstk_ms and __alloca are only used on Windows
145-
crate::trap::trap_unimplemented(fx, "Stack probes are not supported");
146-
return;
147-
} else if fx.tcx.symbol_name(fx.instance).name == "__alloca" {
148-
crate::trap::trap_unimplemented(fx, "Alloca is not supported");
149-
return;
150-
}
151-
152-
// Used by core::hint::spin_loop()
153-
if template[0]
154-
== InlineAsmTemplatePiece::String(".insn i 0x0F, 0, x0, x0, 0x010".to_string())
155-
&& template.len() == 1
156-
{
157-
let destination_block = fx.get_block(destination.unwrap());
158-
fx.bcx.ins().jump(destination_block, &[]);
159-
return;
160-
}
161-
162-
// Used by measureme
163-
if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string())
164-
&& template[1] == InlineAsmTemplatePiece::String("\n".to_string())
165-
&& template[2] == InlineAsmTemplatePiece::String("mov %rbx, ".to_string())
166-
&& matches!(
167-
template[3],
168-
InlineAsmTemplatePiece::Placeholder {
169-
operand_idx: 0,
170-
modifier: Some('r'),
171-
span: _
172-
}
173-
)
174-
&& template[4] == InlineAsmTemplatePiece::String("\n".to_string())
175-
&& template[5] == InlineAsmTemplatePiece::String("cpuid".to_string())
176-
&& template[6] == InlineAsmTemplatePiece::String("\n".to_string())
177-
&& template[7] == InlineAsmTemplatePiece::String("mov ".to_string())
178-
&& matches!(
179-
template[8],
180-
InlineAsmTemplatePiece::Placeholder {
181-
operand_idx: 0,
182-
modifier: Some('r'),
183-
span: _
184-
}
185-
)
186-
&& template[9] == InlineAsmTemplatePiece::String(", %rbx".to_string())
187-
{
188-
let destination_block = fx.get_block(destination.unwrap());
189-
fx.bcx.ins().jump(destination_block, &[]);
190-
return;
191-
} else if template[0] == InlineAsmTemplatePiece::String("rdpmc".to_string()) {
192-
// Return zero dummy values for all performance counters
193-
match operands[0] {
194-
InlineAsmOperand::In {
195-
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
196-
value: _,
197-
} => {}
198-
_ => unreachable!(),
199-
};
200-
let lo = match operands[1] {
201-
InlineAsmOperand::Out {
202-
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
203-
late: true,
204-
place: Some(place),
205-
} => crate::base::codegen_place(fx, place),
206-
_ => unreachable!(),
207-
};
208-
let hi = match operands[2] {
209-
InlineAsmOperand::Out {
210-
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
211-
late: true,
212-
place: Some(place),
213-
} => crate::base::codegen_place(fx, place),
214-
_ => unreachable!(),
215-
};
216-
217-
let u32_layout = fx.layout_of(fx.tcx.types.u32);
218-
let zero = fx.bcx.ins().iconst(types::I32, 0);
219-
lo.write_cvalue(fx, CValue::by_val(zero, u32_layout));
220-
hi.write_cvalue(fx, CValue::by_val(zero, u32_layout));
221-
222-
let destination_block = fx.get_block(destination.unwrap());
223-
fx.bcx.ins().jump(destination_block, &[]);
224-
return;
225-
} else if template[0] == InlineAsmTemplatePiece::String("lock xadd ".to_string())
226-
&& matches!(
227-
template[1],
228-
InlineAsmTemplatePiece::Placeholder { operand_idx: 1, modifier: None, span: _ }
229-
)
230-
&& template[2] == InlineAsmTemplatePiece::String(", (".to_string())
231-
&& matches!(
232-
template[3],
233-
InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ }
234-
)
235-
&& template[4] == InlineAsmTemplatePiece::String(")".to_string())
236-
{
237-
let destination_block = fx.get_block(destination.unwrap());
238-
fx.bcx.ins().jump(destination_block, &[]);
239-
return;
240-
}
241-
242-
if cfg!(not(feature = "inline_asm")) {
243-
fx.tcx.sess.span_err(
244-
span,
245-
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift",
246-
);
247-
} else {
248-
fx.tcx.sess.span_err(span, "asm! and global_asm! are not yet supported on Windows");
249-
}
47+
// Used by panic_abort on Windows, but uses a syntax which only happens to work with
48+
// asm!() by accident and breaks with the GNU assembler as well as global_asm!() for
49+
// the LLVM backend.
50+
if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) {
51+
fx.bcx.ins().trap(TrapCode::User(1));
25052
return;
25153
}
25254

@@ -280,6 +82,12 @@ pub(crate) fn codegen_inline_asm<'tcx>(
28082
CInlineAsmOperand::Const { value }
28183
}
28284
InlineAsmOperand::SymFn { ref value } => {
85+
if cfg!(not(feature = "inline_asm_sym")) {
86+
fx.tcx
87+
.sess
88+
.span_err(span, "asm! and global_asm! sym operands are not yet supported");
89+
}
90+
28391
let const_ = fx.monomorphize(value.const_);
28492
if let ty::FnDef(def_id, args) = *const_.ty().kind() {
28593
let instance = ty::Instance::resolve_for_fn_ptr(

‎compiler/rustc_codegen_cranelift/src/intrinsics/cpuid.rs

Lines changed: 0 additions & 74 deletions
This file was deleted.

‎compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ macro_rules! intrinsic_args {
1212
}
1313
}
1414

15-
mod cpuid;
1615
mod llvm;
1716
mod llvm_aarch64;
1817
mod llvm_x86;
@@ -25,7 +24,6 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
2524
use rustc_middle::ty::GenericArgsRef;
2625
use rustc_span::symbol::{kw, sym, Symbol};
2726

28-
pub(crate) use self::cpuid::codegen_cpuid_call;
2927
pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
3028
use crate::prelude::*;
3129

‎compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -502,13 +502,13 @@ impl<'a> State<'a> {
502502
self.word(";");
503503
self.end(); // end the outer cbox
504504
}
505-
hir::ItemKind::Fn(ref sig, param_names, body) => {
505+
hir::ItemKind::Fn(ref sig, generics, body) => {
506506
self.head("");
507507
self.print_fn(
508508
sig.decl,
509509
sig.header,
510510
Some(item.ident.name),
511-
param_names,
511+
generics,
512512
&[],
513513
Some(body),
514514
);
@@ -1948,11 +1948,10 @@ impl<'a> State<'a> {
19481948
self.print_generic_params(generics.params);
19491949

19501950
self.popen();
1951-
let mut i = 0;
19521951
// Make sure we aren't supplied *both* `arg_names` and `body_id`.
19531952
assert!(arg_names.is_empty() || body_id.is_none());
1954-
self.commasep(Inconsistent, decl.inputs, |s, ty| {
1955-
s.ibox(INDENT_UNIT);
1953+
let mut i = 0;
1954+
let mut print_arg = |s: &mut Self| {
19561955
if let Some(arg_name) = arg_names.get(i) {
19571956
s.word(arg_name.to_string());
19581957
s.word(":");
@@ -1963,11 +1962,17 @@ impl<'a> State<'a> {
19631962
s.space();
19641963
}
19651964
i += 1;
1965+
};
1966+
self.commasep(Inconsistent, decl.inputs, |s, ty| {
1967+
s.ibox(INDENT_UNIT);
1968+
print_arg(s);
19661969
s.print_type(ty);
1967-
s.end()
1970+
s.end();
19681971
});
19691972
if decl.c_variadic {
1970-
self.word(", ...");
1973+
self.word(", ");
1974+
print_arg(self);
1975+
self.word("...");
19711976
}
19721977
self.pclose();
19731978

‎compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,10 +625,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
625625
}
626626
};
627627

628-
// If the loop context is not a `loop { }`, then break with
629-
// a value is illegal, and `opt_coerce_to` will be `None`.
630-
// Just set expectation to error in that case.
631-
let coerce_to = opt_coerce_to.unwrap_or_else(|| Ty::new_misc_error(tcx));
628+
let coerce_to = match opt_coerce_to {
629+
Some(c) => c,
630+
None => {
631+
// If the loop context is not a `loop { }`, then break with
632+
// a value is illegal, and `opt_coerce_to` will be `None`.
633+
// Return error in that case (#114529).
634+
return Ty::new_misc_error(tcx);
635+
}
636+
};
632637

633638
// Recurse without `enclosing_breakables` borrowed.
634639
e_ty = self.check_expr_with_hint(e, coerce_to);

‎compiler/rustc_middle/src/ty/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl<'tcx> TyCtxt<'tcx> {
460460
/// Checks whether each generic argument is simply a unique generic parameter.
461461
pub fn uses_unique_generic_params(
462462
self,
463-
args: GenericArgsRef<'tcx>,
463+
args: &[ty::GenericArg<'tcx>],
464464
ignore_regions: CheckRegions,
465465
) -> Result<(), NotUniqueParam<'tcx>> {
466466
let mut seen = GrowableBitSet::default();

‎compiler/rustc_mir_transform/src/coverage/counters.rs

Lines changed: 19 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ use rustc_middle::mir::coverage::*;
1212

1313
use std::fmt::{self, Debug};
1414

15-
const NESTED_INDENT: &str = " ";
16-
1715
/// The coverage counter or counter expression associated with a particular
1816
/// BCB node or BCB edge.
1917
#[derive(Clone)]
@@ -346,23 +344,11 @@ impl<'a> MakeBcbCounters<'a> {
346344
Ok(())
347345
}
348346

347+
#[instrument(level = "debug", skip(self))]
349348
fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result<CovTerm, Error> {
350-
self.recursive_get_or_make_counter_operand(bcb, 1)
351-
}
352-
353-
fn recursive_get_or_make_counter_operand(
354-
&mut self,
355-
bcb: BasicCoverageBlock,
356-
debug_indent_level: usize,
357-
) -> Result<CovTerm, Error> {
358349
// If the BCB already has a counter, return it.
359350
if let Some(counter_kind) = &self.coverage_counters.bcb_counters[bcb] {
360-
debug!(
361-
"{}{:?} already has a counter: {:?}",
362-
NESTED_INDENT.repeat(debug_indent_level),
363-
bcb,
364-
counter_kind,
365-
);
351+
debug!("{bcb:?} already has a counter: {counter_kind:?}");
366352
return Ok(counter_kind.as_term());
367353
}
368354

@@ -373,20 +359,12 @@ impl<'a> MakeBcbCounters<'a> {
373359
if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) {
374360
let counter_kind = self.coverage_counters.make_counter();
375361
if one_path_to_target {
376-
debug!(
377-
"{}{:?} gets a new counter: {:?}",
378-
NESTED_INDENT.repeat(debug_indent_level),
379-
bcb,
380-
counter_kind,
381-
);
362+
debug!("{bcb:?} gets a new counter: {counter_kind:?}");
382363
} else {
383364
debug!(
384-
"{}{:?} has itself as its own predecessor. It can't be part of its own \
385-
Expression sum, so it will get its own new counter: {:?}. (Note, the compiled \
386-
code will generate an infinite loop.)",
387-
NESTED_INDENT.repeat(debug_indent_level),
388-
bcb,
389-
counter_kind,
365+
"{bcb:?} has itself as its own predecessor. It can't be part of its own \
366+
Expression sum, so it will get its own new counter: {counter_kind:?}. \
367+
(Note, the compiled code will generate an infinite loop.)",
390368
);
391369
}
392370
return self.coverage_counters.set_bcb_counter(bcb, counter_kind);
@@ -396,24 +374,14 @@ impl<'a> MakeBcbCounters<'a> {
396374
// counters and/or expressions of its incoming edges. This will recursively get or create
397375
// counters for those incoming edges first, then call `make_expression()` to sum them up,
398376
// with additional intermediate expressions as needed.
377+
let _sumup_debug_span = debug_span!("(preparing sum-up expression)").entered();
378+
399379
let mut predecessors = self.bcb_predecessors(bcb).to_owned().into_iter();
400-
debug!(
401-
"{}{:?} has multiple incoming edges and will get an expression that sums them up...",
402-
NESTED_INDENT.repeat(debug_indent_level),
403-
bcb,
404-
);
405-
let first_edge_counter_operand = self.recursive_get_or_make_edge_counter_operand(
406-
predecessors.next().unwrap(),
407-
bcb,
408-
debug_indent_level + 1,
409-
)?;
380+
let first_edge_counter_operand =
381+
self.get_or_make_edge_counter_operand(predecessors.next().unwrap(), bcb)?;
410382
let mut some_sumup_edge_counter_operand = None;
411383
for predecessor in predecessors {
412-
let edge_counter_operand = self.recursive_get_or_make_edge_counter_operand(
413-
predecessor,
414-
bcb,
415-
debug_indent_level + 1,
416-
)?;
384+
let edge_counter_operand = self.get_or_make_edge_counter_operand(predecessor, bcb)?;
417385
if let Some(sumup_edge_counter_operand) =
418386
some_sumup_edge_counter_operand.replace(edge_counter_operand)
419387
{
@@ -422,11 +390,7 @@ impl<'a> MakeBcbCounters<'a> {
422390
Op::Add,
423391
edge_counter_operand,
424392
);
425-
debug!(
426-
"{}new intermediate expression: {:?}",
427-
NESTED_INDENT.repeat(debug_indent_level),
428-
intermediate_expression
429-
);
393+
debug!("new intermediate expression: {intermediate_expression:?}");
430394
let intermediate_expression_operand = intermediate_expression.as_term();
431395
some_sumup_edge_counter_operand.replace(intermediate_expression_operand);
432396
}
@@ -436,59 +400,36 @@ impl<'a> MakeBcbCounters<'a> {
436400
Op::Add,
437401
some_sumup_edge_counter_operand.unwrap(),
438402
);
439-
debug!(
440-
"{}{:?} gets a new counter (sum of predecessor counters): {:?}",
441-
NESTED_INDENT.repeat(debug_indent_level),
442-
bcb,
443-
counter_kind
444-
);
403+
drop(_sumup_debug_span);
404+
405+
debug!("{bcb:?} gets a new counter (sum of predecessor counters): {counter_kind:?}");
445406
self.coverage_counters.set_bcb_counter(bcb, counter_kind)
446407
}
447408

409+
#[instrument(level = "debug", skip(self))]
448410
fn get_or_make_edge_counter_operand(
449411
&mut self,
450412
from_bcb: BasicCoverageBlock,
451413
to_bcb: BasicCoverageBlock,
452-
) -> Result<CovTerm, Error> {
453-
self.recursive_get_or_make_edge_counter_operand(from_bcb, to_bcb, 1)
454-
}
455-
456-
fn recursive_get_or_make_edge_counter_operand(
457-
&mut self,
458-
from_bcb: BasicCoverageBlock,
459-
to_bcb: BasicCoverageBlock,
460-
debug_indent_level: usize,
461414
) -> Result<CovTerm, Error> {
462415
// If the source BCB has only one successor (assumed to be the given target), an edge
463416
// counter is unnecessary. Just get or make a counter for the source BCB.
464417
let successors = self.bcb_successors(from_bcb).iter();
465418
if successors.len() == 1 {
466-
return self.recursive_get_or_make_counter_operand(from_bcb, debug_indent_level + 1);
419+
return self.get_or_make_counter_operand(from_bcb);
467420
}
468421

469422
// If the edge already has a counter, return it.
470423
if let Some(counter_kind) =
471424
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
472425
{
473-
debug!(
474-
"{}Edge {:?}->{:?} already has a counter: {:?}",
475-
NESTED_INDENT.repeat(debug_indent_level),
476-
from_bcb,
477-
to_bcb,
478-
counter_kind
479-
);
426+
debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}");
480427
return Ok(counter_kind.as_term());
481428
}
482429

483430
// Make a new counter to count this edge.
484431
let counter_kind = self.coverage_counters.make_counter();
485-
debug!(
486-
"{}Edge {:?}->{:?} gets a new counter: {:?}",
487-
NESTED_INDENT.repeat(debug_indent_level),
488-
from_bcb,
489-
to_bcb,
490-
counter_kind
491-
);
432+
debug!("Edge {from_bcb:?}->{to_bcb:?} gets a new counter: {counter_kind:?}");
492433
self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind)
493434
}
494435

‎compiler/rustc_mir_transform/src/deduce_param_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
4444
// Whether mutating though a `&raw const` is allowed is still undecided, so we
4545
// disable any sketchy `readonly` optimizations for now.
4646
// But we only need to do this if the pointer would point into the argument.
47+
// IOW: for indirect places, like `&raw (*local).field`, this surely cannot mutate `local`.
4748
!place.is_indirect()
4849
}
4950
PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {

‎compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ pub struct OnUnimplementedDirective {
319319
pub subcommands: Vec<OnUnimplementedDirective>,
320320
pub message: Option<OnUnimplementedFormatString>,
321321
pub label: Option<OnUnimplementedFormatString>,
322-
pub note: Option<OnUnimplementedFormatString>,
322+
pub notes: Vec<OnUnimplementedFormatString>,
323323
pub parent_label: Option<OnUnimplementedFormatString>,
324324
pub append_const_msg: Option<AppendConstMessage>,
325325
}
@@ -329,7 +329,7 @@ pub struct OnUnimplementedDirective {
329329
pub struct OnUnimplementedNote {
330330
pub message: Option<String>,
331331
pub label: Option<String>,
332-
pub note: Option<String>,
332+
pub notes: Vec<String>,
333333
pub parent_label: Option<String>,
334334
// If none, should fall back to a generic message
335335
pub append_const_msg: Option<AppendConstMessage>,
@@ -399,7 +399,7 @@ impl<'tcx> OnUnimplementedDirective {
399399

400400
let mut message = None;
401401
let mut label = None;
402-
let mut note = None;
402+
let mut notes = Vec::new();
403403
let mut parent_label = None;
404404
let mut subcommands = vec![];
405405
let mut append_const_msg = None;
@@ -415,10 +415,12 @@ impl<'tcx> OnUnimplementedDirective {
415415
label = parse_value(label_)?;
416416
continue;
417417
}
418-
} else if item.has_name(sym::note) && note.is_none() {
418+
} else if item.has_name(sym::note) {
419419
if let Some(note_) = item.value_str() {
420-
note = parse_value(note_)?;
421-
continue;
420+
if let Some(note) = parse_value(note_)? {
421+
notes.push(note);
422+
continue;
423+
}
422424
}
423425
} else if item.has_name(sym::parent_label)
424426
&& parent_label.is_none()
@@ -432,7 +434,7 @@ impl<'tcx> OnUnimplementedDirective {
432434
&& is_root
433435
&& message.is_none()
434436
&& label.is_none()
435-
&& note.is_none()
437+
&& notes.is_empty()
436438
&& !is_diagnostic_namespace_variant
437439
// FIXME(diagnostic_namespace): disallow filters for now
438440
{
@@ -487,7 +489,7 @@ impl<'tcx> OnUnimplementedDirective {
487489
subcommands,
488490
message,
489491
label,
490-
note,
492+
notes,
491493
parent_label,
492494
append_const_msg,
493495
}))
@@ -505,12 +507,14 @@ impl<'tcx> OnUnimplementedDirective {
505507
if let Some(aggr) = aggr {
506508
let mut subcommands = aggr.subcommands;
507509
subcommands.extend(directive.subcommands);
510+
let mut notes = aggr.notes;
511+
notes.extend(directive.notes);
508512
Ok(Some(Self {
509513
condition: aggr.condition.or(directive.condition),
510514
subcommands,
511515
message: aggr.message.or(directive.message),
512516
label: aggr.label.or(directive.label),
513-
note: aggr.note.or(directive.note),
517+
notes,
514518
parent_label: aggr.parent_label.or(directive.parent_label),
515519
append_const_msg: aggr.append_const_msg.or(directive.append_const_msg),
516520
}))
@@ -543,7 +547,7 @@ impl<'tcx> OnUnimplementedDirective {
543547
value,
544548
attr.span,
545549
)?),
546-
note: None,
550+
notes: Vec::new(),
547551
parent_label: None,
548552
append_const_msg: None,
549553
}))
@@ -600,7 +604,7 @@ impl<'tcx> OnUnimplementedDirective {
600604
) -> OnUnimplementedNote {
601605
let mut message = None;
602606
let mut label = None;
603-
let mut note = None;
607+
let mut notes = Vec::new();
604608
let mut parent_label = None;
605609
let mut append_const_msg = None;
606610
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
@@ -637,9 +641,7 @@ impl<'tcx> OnUnimplementedDirective {
637641
label = Some(label_.clone());
638642
}
639643

640-
if let Some(ref note_) = command.note {
641-
note = Some(note_.clone());
642-
}
644+
notes.extend(command.notes.clone());
643645

644646
if let Some(ref parent_label_) = command.parent_label {
645647
parent_label = Some(parent_label_.clone());
@@ -651,7 +653,7 @@ impl<'tcx> OnUnimplementedDirective {
651653
OnUnimplementedNote {
652654
label: label.map(|l| l.format(tcx, trait_ref, &options_map)),
653655
message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
654-
note: note.map(|n| n.format(tcx, trait_ref, &options_map)),
656+
notes: notes.into_iter().map(|n| n.format(tcx, trait_ref, &options_map)).collect(),
655657
parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
656658
append_const_msg,
657659
}

‎compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -445,29 +445,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
445445
let OnUnimplementedNote {
446446
message,
447447
label,
448-
note,
448+
notes,
449449
parent_label,
450450
append_const_msg,
451451
} = self.on_unimplemented_note(trait_ref, &obligation);
452452
let have_alt_message = message.is_some() || label.is_some();
453453
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
454454
let is_unsize =
455455
Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait();
456-
let (message, note, append_const_msg) = if is_try_conversion {
456+
let (message, notes, append_const_msg) = if is_try_conversion {
457457
(
458458
Some(format!(
459459
"`?` couldn't convert the error to `{}`",
460460
trait_ref.skip_binder().self_ty(),
461461
)),
462-
Some(
462+
vec![
463463
"the question mark operation (`?`) implicitly performs a \
464464
conversion on the error value using the `From` trait"
465465
.to_owned(),
466-
),
466+
],
467467
Some(AppendConstMessage::Default),
468468
)
469469
} else {
470-
(message, note, append_const_msg)
470+
(message, notes, append_const_msg)
471471
};
472472

473473
let err_msg = self.get_standard_error_message(
@@ -588,9 +588,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
588588
if let Some((msg, span)) = type_def {
589589
err.span_label(span, msg);
590590
}
591-
if let Some(s) = note {
591+
for note in notes {
592592
// If it has a custom `#[rustc_on_unimplemented]` note, let's display it
593-
err.note(s);
593+
err.note(note);
594594
}
595595
if let Some(s) = parent_label {
596596
let body = obligation.cause.body_id;

‎compiler/rustc_ty_utils/src/opaque_types.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,14 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
154154

155155
self.opaques.push(alias_ty.def_id.expect_local());
156156

157-
match self.tcx.uses_unique_generic_params(alias_ty.args, CheckRegions::Bound) {
157+
let parent_count = self.tcx.generics_of(alias_ty.def_id).parent_count;
158+
// Only check that the parent generics of the TAIT/RPIT are unique.
159+
// the args owned by the opaque are going to always be duplicate
160+
// lifetime params for RPITs, and empty for TAITs.
161+
match self
162+
.tcx
163+
.uses_unique_generic_params(&alias_ty.args[..parent_count], CheckRegions::Bound)
164+
{
158165
Ok(()) => {
159166
// FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
160167
// supported at all, so this is sound to do, but once we want to support them, you'll

‎library/core/src/marker.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,20 @@ impl<T: ?Sized> Copy for &T {}
621621
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead",
622622
),
623623
on(
624-
_Self = "core::cell::Cell<T>",
624+
all(
625+
_Self = "core::cell::Cell<T>",
626+
not(_Self = "core::cell::Cell<u8>"),
627+
not(_Self = "core::cell::Cell<u16>"),
628+
not(_Self = "core::cell::Cell<u32>"),
629+
not(_Self = "core::cell::Cell<u64>"),
630+
not(_Self = "core::cell::Cell<usize>"),
631+
not(_Self = "core::cell::Cell<i8>"),
632+
not(_Self = "core::cell::Cell<i16>"),
633+
not(_Self = "core::cell::Cell<i32>"),
634+
not(_Self = "core::cell::Cell<i64>"),
635+
not(_Self = "core::cell::Cell<isize>"),
636+
not(_Self = "core::cell::Cell<bool>")
637+
),
625638
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`",
626639
),
627640
on(

‎library/std/src/sys/uefi/alloc.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,38 @@
11
//! Global Allocator for UEFI.
22
//! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc)
33
4-
use crate::alloc::{GlobalAlloc, Layout, System};
4+
use r_efi::protocols::loaded_image;
55

6-
const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA;
6+
use crate::alloc::{GlobalAlloc, Layout, System};
7+
use crate::sync::OnceLock;
8+
use crate::sys::uefi::helpers;
79

810
#[stable(feature = "alloc_system_type", since = "1.28.0")]
911
unsafe impl GlobalAlloc for System {
1012
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
13+
static EFI_MEMORY_TYPE: OnceLock<u32> = OnceLock::new();
14+
1115
// Return null pointer if boot services are not available
1216
if crate::os::uefi::env::boot_services().is_none() {
1317
return crate::ptr::null_mut();
1418
}
1519

1620
// If boot services is valid then SystemTable is not null.
1721
let system_table = crate::os::uefi::env::system_table().as_ptr().cast();
22+
23+
// Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this
24+
// will never fail.
25+
let mem_type = EFI_MEMORY_TYPE.get_or_init(|| {
26+
let protocol = helpers::image_handle_protocol::<loaded_image::Protocol>(
27+
loaded_image::PROTOCOL_GUID,
28+
)
29+
.unwrap();
30+
// Gives allocations the memory type that the data sections were loaded as.
31+
unsafe { (*protocol.as_ptr()).image_data_type }
32+
});
33+
1834
// The caller must ensure non-0 layout
19-
unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) }
35+
unsafe { r_efi_alloc::raw::alloc(system_table, layout, *mem_type) }
2036
}
2137

2238
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {

‎tests/pretty/hir-fn-variadic.pp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// pretty-compare-only
2+
// pretty-mode:hir
3+
// pp-exact:hir-fn-variadic.pp
4+
5+
#![feature(c_variadic)]
6+
#[prelude_import]
7+
use ::std::prelude::rust_2015::*;
8+
#[macro_use]
9+
extern crate std;
10+
11+
extern "C" {
12+
fn foo(x: i32, va1: ...);
13+
}
14+
15+
unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::<usize>() }

‎tests/pretty/hir-fn-variadic.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// pretty-compare-only
2+
// pretty-mode:hir
3+
// pp-exact:hir-fn-variadic.pp
4+
5+
#![feature(c_variadic)]
6+
7+
extern "C" {
8+
pub fn foo(x: i32, va1: ...);
9+
}
10+
11+
pub unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize {
12+
va2.arg::<usize>()
13+
}

‎tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ LL | takes_foo(());
2626
|
2727
= help: the trait `Foo` is not implemented for `()`
2828
= note: custom note
29+
= note: fallback note
2930
help: this trait has no implementations, consider adding one
3031
--> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1
3132
|
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(diagnostic_namespace)]
2+
3+
#[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz", note = "Boom")]
4+
trait Foo {}
5+
6+
#[diagnostic::on_unimplemented(message = "Bar", label = "Foo", note = "Baz")]
7+
#[diagnostic::on_unimplemented(note = "Baz2")]
8+
trait Bar {}
9+
10+
fn takes_foo(_: impl Foo) {}
11+
fn takes_bar(_: impl Bar) {}
12+
13+
fn main() {
14+
takes_foo(());
15+
//~^ERROR Foo
16+
takes_bar(());
17+
//~^ERROR Bar
18+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error[E0277]: Foo
2+
--> $DIR/multiple_notes.rs:14:15
3+
|
4+
LL | takes_foo(());
5+
| --------- ^^ Bar
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Foo` is not implemented for `()`
10+
= note: Baz
11+
= note: Boom
12+
help: this trait has no implementations, consider adding one
13+
--> $DIR/multiple_notes.rs:4:1
14+
|
15+
LL | trait Foo {}
16+
| ^^^^^^^^^
17+
note: required by a bound in `takes_foo`
18+
--> $DIR/multiple_notes.rs:10:22
19+
|
20+
LL | fn takes_foo(_: impl Foo) {}
21+
| ^^^ required by this bound in `takes_foo`
22+
23+
error[E0277]: Bar
24+
--> $DIR/multiple_notes.rs:16:15
25+
|
26+
LL | takes_bar(());
27+
| --------- ^^ Foo
28+
| |
29+
| required by a bound introduced by this call
30+
|
31+
= help: the trait `Bar` is not implemented for `()`
32+
= note: Baz
33+
= note: Baz2
34+
help: this trait has no implementations, consider adding one
35+
--> $DIR/multiple_notes.rs:8:1
36+
|
37+
LL | trait Bar {}
38+
| ^^^^^^^^^
39+
note: required by a bound in `takes_bar`
40+
--> $DIR/multiple_notes.rs:11:22
41+
|
42+
LL | fn takes_bar(_: impl Bar) {}
43+
| ^^^ required by this bound in `takes_bar`
44+
45+
error: aborting due to 2 previous errors
46+
47+
For more information about this error, try `rustc --explain E0277`.

‎tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ LL | call(foo_unsafe);
5858
| required by a bound introduced by this call
5959
|
6060
= help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
61+
= note: unsafe function cannot be called generically without an unsafe block
6162
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
6263
= note: `#[target_feature]` functions do not implement the `Fn` traits
6364
note: required by a bound in `call`
@@ -75,6 +76,7 @@ LL | call_mut(foo_unsafe);
7576
| required by a bound introduced by this call
7677
|
7778
= help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
79+
= note: unsafe function cannot be called generically without an unsafe block
7880
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
7981
= note: `#[target_feature]` functions do not implement the `Fn` traits
8082
note: required by a bound in `call_mut`
@@ -92,6 +94,7 @@ LL | call_once(foo_unsafe);
9294
| required by a bound introduced by this call
9395
|
9496
= help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
97+
= note: unsafe function cannot be called generically without an unsafe block
9598
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
9699
= note: `#[target_feature]` functions do not implement the `Fn` traits
97100
note: required by a bound in `call_once`

‎tests/ui/suggestions/path-display.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | println!("{}", path);
55
| ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it
66
|
77
= help: the trait `std::fmt::Display` is not implemented for `Path`
8+
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
89
= note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
910
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
1011

@@ -15,6 +16,7 @@ LL | println!("{}", path);
1516
| ^^^^ `PathBuf` cannot be formatted with the default formatter; call `.display()` on it
1617
|
1718
= help: the trait `std::fmt::Display` is not implemented for `PathBuf`
19+
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
1820
= note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
1921
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
2022

‎tests/ui/traits/new-solver/fn-trait.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ LL | require_fn(f as unsafe fn() -> i32);
77
| required by a bound introduced by this call
88
|
99
= help: the trait `Fn<()>` is not implemented for `unsafe fn() -> i32`
10+
= note: unsafe function cannot be called generically without an unsafe block
1011
= note: wrap the `unsafe fn() -> i32` in a closure with no arguments: `|| { /* code */ }`
1112
note: required by a bound in `require_fn`
1213
--> $DIR/fn-trait.rs:3:23
@@ -97,6 +98,7 @@ LL | require_fn(h);
9798
| required by a bound introduced by this call
9899
|
99100
= help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() -> i32 {h}`
101+
= note: unsafe function cannot be called generically without an unsafe block
100102
= note: wrap the `unsafe fn() -> i32 {h}` in a closure with no arguments: `|| { /* code */ }`
101103
note: required by a bound in `require_fn`
102104
--> $DIR/fn-trait.rs:3:23
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
type Opaque<'lt> = impl Sized + 'lt;
6+
7+
fn test<'a>(
8+
arg: impl Iterator<Item = &'a u8>,
9+
) -> impl Iterator<Item = Opaque<'a>> {
10+
arg
11+
}
12+
13+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
// edition: 2021
3+
4+
#![feature(type_alias_impl_trait)]
5+
6+
struct Foo<'a>(&'a ());
7+
8+
impl<'a> Foo<'a> {
9+
async fn new() -> () {
10+
type T = impl Sized;
11+
let _: T = ();
12+
}
13+
}
14+
15+
fn main() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Regression test for issue #114529
2+
// Tests that we do not ICE during const eval for a
3+
// break-with-value in contexts where it is illegal
4+
5+
#[allow(while_true)]
6+
fn main() {
7+
[(); {
8+
while true {
9+
break 9; //~ ERROR `break` with value from a `while` loop
10+
};
11+
51
12+
}];
13+
14+
[(); {
15+
while let Some(v) = Some(9) {
16+
break v; //~ ERROR `break` with value from a `while` loop
17+
};
18+
51
19+
}];
20+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0571]: `break` with value from a `while` loop
2+
--> $DIR/issue-114529-illegal-break-with-value.rs:9:13
3+
|
4+
LL | while true {
5+
| ---------- you can't `break` with a value in a `while` loop
6+
LL | break 9;
7+
| ^^^^^^^ can only break with a value inside `loop` or breakable block
8+
|
9+
help: use `break` on its own without a value inside this `while` loop
10+
|
11+
LL | break;
12+
| ~~~~~
13+
14+
error[E0571]: `break` with value from a `while` loop
15+
--> $DIR/issue-114529-illegal-break-with-value.rs:16:13
16+
|
17+
LL | while let Some(v) = Some(9) {
18+
| --------------------------- you can't `break` with a value in a `while` loop
19+
LL | break v;
20+
| ^^^^^^^ can only break with a value inside `loop` or breakable block
21+
|
22+
help: use `break` on its own without a value inside this `while` loop
23+
|
24+
LL | break;
25+
| ~~~~~
26+
27+
error: aborting due to 2 previous errors
28+
29+
For more information about this error, try `rustc --explain E0571`.

0 commit comments

Comments
 (0)
Please sign in to comment.