Skip to content

Commit

Permalink
Auto merge of rust-lang#127956 - tgross35:rollup-8ten7pk, r=tgross35
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Jul 19, 2024
2 parents 8c3a94a + 314cf1f commit 11e5724
Show file tree
Hide file tree
Showing 47 changed files with 1,904 additions and 281 deletions.
10 changes: 8 additions & 2 deletions compiler/rustc_codegen_llvm/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,14 @@ impl<'ll> CodegenCx<'ll, '_> {
}

// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable.
if self.tcx.sess.target.is_like_wasm {
// go into custom sections of the wasm executable. The exception to this
// is the `.init_array` section which are treated specially by the wasm linker.
if self.tcx.sess.target.is_like_wasm
&& attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap_or(true)
{
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext2(
self.llcx,
Expand Down
35 changes: 28 additions & 7 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,21 +166,42 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
return;
}

// For the wasm32 target statics with `#[link_section]` are placed into custom
// sections of the final output file, but this isn't link custom sections of
// other executable formats. Namely we can only embed a list of bytes,
// nothing with provenance (pointers to anything else). If any provenance
// show up, reject it here.
// For the wasm32 target statics with `#[link_section]` other than `.init_array`
// are placed into custom sections of the final output file, but this isn't like
// custom sections of other executable formats. Namely we can only embed a list
// of bytes, nothing with provenance (pointers to anything else). If any
// provenance show up, reject it here.
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
// the consumer's responsibility to ensure all bytes that have been read
// have defined values.
//
// The `.init_array` section is left to go through the normal custom section code path.
// When dealing with `.init_array` wasm-ld currently has several limitations. This manifests
// in workarounds in user-code.
//
// * The linker fails to merge multiple items in a crate into the .init_array section.
// To work around this, a single array can be used placing multiple items in the array.
// #[link_section = ".init_array"]
// static FOO: [unsafe extern "C" fn(); 2] = [ctor, ctor];
// * Even symbols marked used get gc'd from dependant crates unless at least one symbol
// in the crate is marked with an `#[export_name]`
//
// Once `.init_array` support in wasm-ld is complete, the user code workarounds should
// continue to work, but would no longer be necessary.

if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
&& alloc.inner().provenance().ptrs().len() != 0
{
let msg = "statics with a custom `#[link_section]` must be a \
if attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap()
{
let msg = "statics with a custom `#[link_section]` must be a \
simple list of bytes on the wasm target with no \
extra levels of indirection such as references";
tcx.dcx().span_err(tcx.def_span(id), msg);
tcx.dcx().span_err(tcx.def_span(id), msg);
}
}
}

Expand Down
66 changes: 60 additions & 6 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,20 +1087,74 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);

let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
if let Some(suggested_name) = find_best_match_for_name(
if let Some(variant_name) = find_best_match_for_name(
&adt_def
.variants()
.iter()
.map(|variant| variant.name)
.collect::<Vec<Symbol>>(),
assoc_ident.name,
None,
) {
err.span_suggestion(
assoc_ident.span,
) && let Some(variant) =
adt_def.variants().iter().find(|s| s.name == variant_name)
{
let mut suggestion = vec![(assoc_ident.span, variant_name.to_string())];
if let hir::Node::Stmt(hir::Stmt {
kind: hir::StmtKind::Semi(ref expr),
..
})
| hir::Node::Expr(ref expr) = tcx.parent_hir_node(hir_ref_id)
&& let hir::ExprKind::Struct(..) = expr.kind
{
match variant.ctor {
None => {
// struct
suggestion = vec![(
assoc_ident.span.with_hi(expr.span.hi()),
if variant.fields.is_empty() {
format!("{variant_name} {{}}")
} else {
format!(
"{variant_name} {{ {} }}",
variant
.fields
.iter()
.map(|f| format!("{}: /* value */", f.name))
.collect::<Vec<_>>()
.join(", ")
)
},
)];
}
Some((hir::def::CtorKind::Fn, def_id)) => {
// tuple
let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
let inputs = fn_sig.inputs().skip_binder();
suggestion = vec![(
assoc_ident.span.with_hi(expr.span.hi()),
format!(
"{variant_name}({})",
inputs
.iter()
.map(|i| format!("/* {i} */"))
.collect::<Vec<_>>()
.join(", ")
),
)];
}
Some((hir::def::CtorKind::Const, _)) => {
// unit
suggestion = vec![(
assoc_ident.span.with_hi(expr.span.hi()),
variant_name.to_string(),
)];
}
}
}
err.multipart_suggestion_verbose(
"there is a variant with a similar name",
suggested_name,
Applicability::MaybeIncorrect,
suggestion,
Applicability::HasPlaceholders,
);
} else {
err.span_label(
Expand Down
44 changes: 34 additions & 10 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_error(tcx, e)
}
Res::Def(DefKind::Variant, _) => {
let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value");
let e = report_unexpected_variant_res(
tcx,
res,
Some(expr),
qpath,
expr.span,
E0533,
"value",
);
Ty::new_error(tcx, e)
}
_ => {
Expand Down Expand Up @@ -2210,8 +2218,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);

let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap();
match variant.ctor_kind() {
Some(CtorKind::Fn) => match ty.kind() {
match variant.ctor {
Some((CtorKind::Fn, def_id)) => match ty.kind() {
ty::Adt(adt, ..) if adt.is_enum() => {
err.span_label(
variant_ident_span,
Expand All @@ -2222,28 +2230,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
);
err.span_label(field.ident.span, "field does not exist");
let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
let inputs = fn_sig.inputs().skip_binder();
let fields = format!(
"({})",
inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
);
let (replace_span, sugg) = match expr.kind {
hir::ExprKind::Struct(qpath, ..) => {
(qpath.span().shrink_to_hi().with_hi(expr.span.hi()), fields)
}
_ => {
(expr.span, format!("{ty}::{variant}{fields}", variant = variant.name))
}
};
err.span_suggestion_verbose(
expr.span,
replace_span,
format!(
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
adt = ty,
variant = variant.name,
),
format!(
"{adt}::{variant}(/* fields */)",
adt = ty,
variant = variant.name,
),
sugg,
Applicability::HasPlaceholders,
);
}
_ => {
err.span_label(variant_ident_span, format!("`{ty}` defined here"));
err.span_label(field.ident.span, "field does not exist");
let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
let inputs = fn_sig.inputs().skip_binder();
let fields = format!(
"({})",
inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
);
err.span_suggestion_verbose(
expr.span,
format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
format!("{ty}(/* fields */)"),
format!("{ty}{fields}"),
Applicability::HasPlaceholders,
);
}
Expand Down
60 changes: 58 additions & 2 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use crate::expectation::Expectation;
use crate::fn_ctxt::LoweredTy;
use crate::gather_locals::GatherLocalsVisitor;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
use rustc_errors::{codes::*, struct_span_code_err, Applicability, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor;
Expand Down Expand Up @@ -346,6 +346,7 @@ impl<'tcx> EnclosingBreakables<'tcx> {
fn report_unexpected_variant_res(
tcx: TyCtxt<'_>,
res: Res,
expr: Option<&hir::Expr<'_>>,
qpath: &hir::QPath<'_>,
span: Span,
err_code: ErrCode,
Expand All @@ -356,7 +357,7 @@ fn report_unexpected_variant_res(
_ => res.descr(),
};
let path_str = rustc_hir_pretty::qpath_to_string(&tcx, qpath);
let err = tcx
let mut err = tcx
.dcx()
.struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
.with_code(err_code);
Expand All @@ -366,6 +367,61 @@ fn report_unexpected_variant_res(
err.with_span_label(span, "`fn` calls are not allowed in patterns")
.with_help(format!("for more information, visit {patterns_url}"))
}
Res::Def(DefKind::Variant, _) if let Some(expr) = expr => {
err.span_label(span, format!("not a {expected}"));
let variant = tcx.expect_variant_res(res);
let sugg = if variant.fields.is_empty() {
" {}".to_string()
} else {
format!(
" {{ {} }}",
variant
.fields
.iter()
.map(|f| format!("{}: /* value */", f.name))
.collect::<Vec<_>>()
.join(", ")
)
};
let descr = "you might have meant to create a new value of the struct";
let mut suggestion = vec![];
match tcx.parent_hir_node(expr.hir_id) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Call(..),
span: call_span,
..
}) => {
suggestion.push((span.shrink_to_hi().with_hi(call_span.hi()), sugg));
}
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(..), hir_id, .. }) => {
suggestion.push((expr.span.shrink_to_lo(), "(".to_string()));
if let hir::Node::Expr(drop_temps) = tcx.parent_hir_node(*hir_id)
&& let hir::ExprKind::DropTemps(_) = drop_temps.kind
&& let hir::Node::Expr(parent) = tcx.parent_hir_node(drop_temps.hir_id)
&& let hir::ExprKind::If(condition, block, None) = parent.kind
&& condition.hir_id == drop_temps.hir_id
&& let hir::ExprKind::Block(block, _) = block.kind
&& block.stmts.is_empty()
&& let Some(expr) = block.expr
&& let hir::ExprKind::Path(..) = expr.kind
{
// Special case: you can incorrectly write an equality condition:
// if foo == Struct { field } { /* if body */ }
// which should have been written
// if foo == (Struct { field }) { /* if body */ }
suggestion.push((block.span.shrink_to_hi(), ")".to_string()));
} else {
suggestion.push((span.shrink_to_hi().with_hi(expr.span.hi()), sugg));
}
}
_ => {
suggestion.push((span.shrink_to_hi(), sugg));
}
}

err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect);
err
}
_ => err.with_span_label(span, format!("not a {expected}")),
}
.emit()
Expand Down
Loading

0 comments on commit 11e5724

Please sign in to comment.