Skip to content

Commit 11e5724

Browse files
committed
Auto merge of rust-lang#127956 - tgross35:rollup-8ten7pk, r=tgross35
Rollup of 7 pull requests Successful merges: - rust-lang#121533 (Handle .init_array link_section specially on wasm) - rust-lang#127825 (Migrate `macos-fat-archive`, `manual-link` and `archive-duplicate-names` `run-make` tests to rmake) - rust-lang#127891 (Tweak suggestions when using incorrect type of enum literal) - rust-lang#127902 (`collect_tokens_trailing_token` cleanups) - rust-lang#127928 (Migrate `lto-smoke-c` and `link-path-order` `run-make` tests to rmake) - rust-lang#127935 (Change `binary_asm_labels` to only fire on x86 and x86_64) - rust-lang#127953 ([compiletest] Search *.a when getting dynamic libraries on AIX) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8c3a94a + 314cf1f commit 11e5724

Some content is hidden

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

47 files changed

+1904
-281
lines changed

compiler/rustc_codegen_llvm/src/consts.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,14 @@ impl<'ll> CodegenCx<'ll, '_> {
495495
}
496496

497497
// Wasm statics with custom link sections get special treatment as they
498-
// go into custom sections of the wasm executable.
499-
if self.tcx.sess.target.is_like_wasm {
498+
// go into custom sections of the wasm executable. The exception to this
499+
// is the `.init_array` section which are treated specially by the wasm linker.
500+
if self.tcx.sess.target.is_like_wasm
501+
&& attrs
502+
.link_section
503+
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
504+
.unwrap_or(true)
505+
{
500506
if let Some(section) = attrs.link_section {
501507
let section = llvm::LLVMMDStringInContext2(
502508
self.llcx,

compiler/rustc_hir_analysis/src/check/mod.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -166,21 +166,42 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
166166
return;
167167
}
168168

169-
// For the wasm32 target statics with `#[link_section]` are placed into custom
170-
// sections of the final output file, but this isn't link custom sections of
171-
// other executable formats. Namely we can only embed a list of bytes,
172-
// nothing with provenance (pointers to anything else). If any provenance
173-
// show up, reject it here.
169+
// For the wasm32 target statics with `#[link_section]` other than `.init_array`
170+
// are placed into custom sections of the final output file, but this isn't like
171+
// custom sections of other executable formats. Namely we can only embed a list
172+
// of bytes, nothing with provenance (pointers to anything else). If any
173+
// provenance show up, reject it here.
174174
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
175175
// the consumer's responsibility to ensure all bytes that have been read
176176
// have defined values.
177+
//
178+
// The `.init_array` section is left to go through the normal custom section code path.
179+
// When dealing with `.init_array` wasm-ld currently has several limitations. This manifests
180+
// in workarounds in user-code.
181+
//
182+
// * The linker fails to merge multiple items in a crate into the .init_array section.
183+
// To work around this, a single array can be used placing multiple items in the array.
184+
// #[link_section = ".init_array"]
185+
// static FOO: [unsafe extern "C" fn(); 2] = [ctor, ctor];
186+
// * Even symbols marked used get gc'd from dependant crates unless at least one symbol
187+
// in the crate is marked with an `#[export_name]`
188+
//
189+
// Once `.init_array` support in wasm-ld is complete, the user code workarounds should
190+
// continue to work, but would no longer be necessary.
191+
177192
if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
178193
&& alloc.inner().provenance().ptrs().len() != 0
179194
{
180-
let msg = "statics with a custom `#[link_section]` must be a \
195+
if attrs
196+
.link_section
197+
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
198+
.unwrap()
199+
{
200+
let msg = "statics with a custom `#[link_section]` must be a \
181201
simple list of bytes on the wasm target with no \
182202
extra levels of indirection such as references";
183-
tcx.dcx().span_err(tcx.def_span(id), msg);
203+
tcx.dcx().span_err(tcx.def_span(id), msg);
204+
}
184205
}
185206
}
186207

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+60-6
Original file line numberDiff line numberDiff line change
@@ -1087,20 +1087,74 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10871087
);
10881088

10891089
let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
1090-
if let Some(suggested_name) = find_best_match_for_name(
1090+
if let Some(variant_name) = find_best_match_for_name(
10911091
&adt_def
10921092
.variants()
10931093
.iter()
10941094
.map(|variant| variant.name)
10951095
.collect::<Vec<Symbol>>(),
10961096
assoc_ident.name,
10971097
None,
1098-
) {
1099-
err.span_suggestion(
1100-
assoc_ident.span,
1098+
) && let Some(variant) =
1099+
adt_def.variants().iter().find(|s| s.name == variant_name)
1100+
{
1101+
let mut suggestion = vec![(assoc_ident.span, variant_name.to_string())];
1102+
if let hir::Node::Stmt(hir::Stmt {
1103+
kind: hir::StmtKind::Semi(ref expr),
1104+
..
1105+
})
1106+
| hir::Node::Expr(ref expr) = tcx.parent_hir_node(hir_ref_id)
1107+
&& let hir::ExprKind::Struct(..) = expr.kind
1108+
{
1109+
match variant.ctor {
1110+
None => {
1111+
// struct
1112+
suggestion = vec![(
1113+
assoc_ident.span.with_hi(expr.span.hi()),
1114+
if variant.fields.is_empty() {
1115+
format!("{variant_name} {{}}")
1116+
} else {
1117+
format!(
1118+
"{variant_name} {{ {} }}",
1119+
variant
1120+
.fields
1121+
.iter()
1122+
.map(|f| format!("{}: /* value */", f.name))
1123+
.collect::<Vec<_>>()
1124+
.join(", ")
1125+
)
1126+
},
1127+
)];
1128+
}
1129+
Some((hir::def::CtorKind::Fn, def_id)) => {
1130+
// tuple
1131+
let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
1132+
let inputs = fn_sig.inputs().skip_binder();
1133+
suggestion = vec![(
1134+
assoc_ident.span.with_hi(expr.span.hi()),
1135+
format!(
1136+
"{variant_name}({})",
1137+
inputs
1138+
.iter()
1139+
.map(|i| format!("/* {i} */"))
1140+
.collect::<Vec<_>>()
1141+
.join(", ")
1142+
),
1143+
)];
1144+
}
1145+
Some((hir::def::CtorKind::Const, _)) => {
1146+
// unit
1147+
suggestion = vec![(
1148+
assoc_ident.span.with_hi(expr.span.hi()),
1149+
variant_name.to_string(),
1150+
)];
1151+
}
1152+
}
1153+
}
1154+
err.multipart_suggestion_verbose(
11011155
"there is a variant with a similar name",
1102-
suggested_name,
1103-
Applicability::MaybeIncorrect,
1156+
suggestion,
1157+
Applicability::HasPlaceholders,
11041158
);
11051159
} else {
11061160
err.span_label(

compiler/rustc_hir_typeck/src/expr.rs

+34-10
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
519519
Ty::new_error(tcx, e)
520520
}
521521
Res::Def(DefKind::Variant, _) => {
522-
let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value");
522+
let e = report_unexpected_variant_res(
523+
tcx,
524+
res,
525+
Some(expr),
526+
qpath,
527+
expr.span,
528+
E0533,
529+
"value",
530+
);
523531
Ty::new_error(tcx, e)
524532
}
525533
_ => {
@@ -2210,8 +2218,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22102218
);
22112219

22122220
let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap();
2213-
match variant.ctor_kind() {
2214-
Some(CtorKind::Fn) => match ty.kind() {
2221+
match variant.ctor {
2222+
Some((CtorKind::Fn, def_id)) => match ty.kind() {
22152223
ty::Adt(adt, ..) if adt.is_enum() => {
22162224
err.span_label(
22172225
variant_ident_span,
@@ -2222,28 +2230,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22222230
),
22232231
);
22242232
err.span_label(field.ident.span, "field does not exist");
2233+
let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
2234+
let inputs = fn_sig.inputs().skip_binder();
2235+
let fields = format!(
2236+
"({})",
2237+
inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
2238+
);
2239+
let (replace_span, sugg) = match expr.kind {
2240+
hir::ExprKind::Struct(qpath, ..) => {
2241+
(qpath.span().shrink_to_hi().with_hi(expr.span.hi()), fields)
2242+
}
2243+
_ => {
2244+
(expr.span, format!("{ty}::{variant}{fields}", variant = variant.name))
2245+
}
2246+
};
22252247
err.span_suggestion_verbose(
2226-
expr.span,
2248+
replace_span,
22272249
format!(
22282250
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
22292251
adt = ty,
22302252
variant = variant.name,
22312253
),
2232-
format!(
2233-
"{adt}::{variant}(/* fields */)",
2234-
adt = ty,
2235-
variant = variant.name,
2236-
),
2254+
sugg,
22372255
Applicability::HasPlaceholders,
22382256
);
22392257
}
22402258
_ => {
22412259
err.span_label(variant_ident_span, format!("`{ty}` defined here"));
22422260
err.span_label(field.ident.span, "field does not exist");
2261+
let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
2262+
let inputs = fn_sig.inputs().skip_binder();
2263+
let fields = format!(
2264+
"({})",
2265+
inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
2266+
);
22432267
err.span_suggestion_verbose(
22442268
expr.span,
22452269
format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
2246-
format!("{ty}(/* fields */)"),
2270+
format!("{ty}{fields}"),
22472271
Applicability::HasPlaceholders,
22482272
);
22492273
}

compiler/rustc_hir_typeck/src/lib.rs

+58-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use crate::expectation::Expectation;
5353
use crate::fn_ctxt::LoweredTy;
5454
use crate::gather_locals::GatherLocalsVisitor;
5555
use rustc_data_structures::unord::UnordSet;
56-
use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
56+
use rustc_errors::{codes::*, struct_span_code_err, Applicability, ErrorGuaranteed};
5757
use rustc_hir as hir;
5858
use rustc_hir::def::{DefKind, Res};
5959
use rustc_hir::intravisit::Visitor;
@@ -346,6 +346,7 @@ impl<'tcx> EnclosingBreakables<'tcx> {
346346
fn report_unexpected_variant_res(
347347
tcx: TyCtxt<'_>,
348348
res: Res,
349+
expr: Option<&hir::Expr<'_>>,
349350
qpath: &hir::QPath<'_>,
350351
span: Span,
351352
err_code: ErrCode,
@@ -356,7 +357,7 @@ fn report_unexpected_variant_res(
356357
_ => res.descr(),
357358
};
358359
let path_str = rustc_hir_pretty::qpath_to_string(&tcx, qpath);
359-
let err = tcx
360+
let mut err = tcx
360361
.dcx()
361362
.struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
362363
.with_code(err_code);
@@ -366,6 +367,61 @@ fn report_unexpected_variant_res(
366367
err.with_span_label(span, "`fn` calls are not allowed in patterns")
367368
.with_help(format!("for more information, visit {patterns_url}"))
368369
}
370+
Res::Def(DefKind::Variant, _) if let Some(expr) = expr => {
371+
err.span_label(span, format!("not a {expected}"));
372+
let variant = tcx.expect_variant_res(res);
373+
let sugg = if variant.fields.is_empty() {
374+
" {}".to_string()
375+
} else {
376+
format!(
377+
" {{ {} }}",
378+
variant
379+
.fields
380+
.iter()
381+
.map(|f| format!("{}: /* value */", f.name))
382+
.collect::<Vec<_>>()
383+
.join(", ")
384+
)
385+
};
386+
let descr = "you might have meant to create a new value of the struct";
387+
let mut suggestion = vec![];
388+
match tcx.parent_hir_node(expr.hir_id) {
389+
hir::Node::Expr(hir::Expr {
390+
kind: hir::ExprKind::Call(..),
391+
span: call_span,
392+
..
393+
}) => {
394+
suggestion.push((span.shrink_to_hi().with_hi(call_span.hi()), sugg));
395+
}
396+
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(..), hir_id, .. }) => {
397+
suggestion.push((expr.span.shrink_to_lo(), "(".to_string()));
398+
if let hir::Node::Expr(drop_temps) = tcx.parent_hir_node(*hir_id)
399+
&& let hir::ExprKind::DropTemps(_) = drop_temps.kind
400+
&& let hir::Node::Expr(parent) = tcx.parent_hir_node(drop_temps.hir_id)
401+
&& let hir::ExprKind::If(condition, block, None) = parent.kind
402+
&& condition.hir_id == drop_temps.hir_id
403+
&& let hir::ExprKind::Block(block, _) = block.kind
404+
&& block.stmts.is_empty()
405+
&& let Some(expr) = block.expr
406+
&& let hir::ExprKind::Path(..) = expr.kind
407+
{
408+
// Special case: you can incorrectly write an equality condition:
409+
// if foo == Struct { field } { /* if body */ }
410+
// which should have been written
411+
// if foo == (Struct { field }) { /* if body */ }
412+
suggestion.push((block.span.shrink_to_hi(), ")".to_string()));
413+
} else {
414+
suggestion.push((span.shrink_to_hi().with_hi(expr.span.hi()), sugg));
415+
}
416+
}
417+
_ => {
418+
suggestion.push((span.shrink_to_hi(), sugg));
419+
}
420+
}
421+
422+
err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect);
423+
err
424+
}
369425
_ => err.with_span_label(span, format!("not a {expected}")),
370426
}
371427
.emit()

0 commit comments

Comments
 (0)