diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/mod.rs | 35 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 66 |
2 files changed, 88 insertions, 13 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 9fef31acef8..24aeb024461 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -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); + } } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7b8a03def86..7d1ab232c71 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1087,7 +1087,7 @@ 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() @@ -1095,12 +1095,66 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .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( |
