Auto merge of #102482 - notriddle:rollup-fjm618g, r=notriddle

Rollup of 7 pull requests

Successful merges:

 - #102214 (Fix span of byte-escaped left format args brace)
 - #102426 (Don't export `__wasm_init_memory` on WebAssembly.)
 - #102437 (rustdoc: cut margin-top from first header in docblock)
 - #102442 (rustdoc: remove bad CSS font-weight on `.impl`, `.method`, etc)
 - #102447 (rustdoc: add method spacing to trait methods)
 - #102468 (tidy: make rustc dependency error less confusing)
 - #102476 (Split out the error reporting logic into a separate function)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-09-29 19:52:48 +00:00
commit 9c56d9d6fe
12 changed files with 243 additions and 175 deletions

View File

@ -1180,18 +1180,12 @@ impl<'a> WasmLd<'a> {
// sharing memory and instantiating the module multiple times. As a
// result if it were exported then we'd just have no sharing.
//
// * `--export=__wasm_init_memory` - when using `--passive-segments` the
// linker will synthesize this function, and so we need to make sure
// that our usage of `--export` below won't accidentally cause this
// function to get deleted.
//
// * `--export=*tls*` - when `#[thread_local]` symbols are used these
// symbols are how the TLS segments are initialized and configured.
if sess.target_features.contains(&sym::atomics) {
cmd.arg("--shared-memory");
cmd.arg("--max-memory=1073741824");
cmd.arg("--import-memory");
cmd.arg("--export=__wasm_init_memory");
cmd.arg("--export=__wasm_init_tls");
cmd.arg("--export=__tls_size");
cmd.arg("--export=__tls_align");

View File

@ -394,140 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ty::FnPtr(sig) => (sig, None),
_ => {
let mut unit_variant = None;
if let hir::ExprKind::Path(qpath) = &callee_expr.kind
&& let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
= self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
// Only suggest removing parens if there are no arguments
&& arg_exprs.is_empty()
{
let descr = match kind {
def::CtorOf::Struct => "struct",
def::CtorOf::Variant => "enum variant",
};
let removal_span =
callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
unit_variant =
Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
}
let callee_ty = self.resolve_vars_if_possible(callee_ty);
let mut err = type_error_struct!(
self.tcx.sess,
callee_expr.span,
callee_ty,
E0618,
"expected function, found {}",
match &unit_variant {
Some((_, kind, path)) => format!("{kind} `{path}`"),
None => format!("`{callee_ty}`"),
}
);
self.identify_bad_closure_def_and_call(
&mut err,
call_expr.hir_id,
&callee_expr.kind,
callee_expr.span,
);
if let Some((removal_span, kind, path)) = &unit_variant {
err.span_suggestion_verbose(
*removal_span,
&format!(
"`{path}` is a unit {kind}, and does not take parentheses to be constructed",
),
"",
Applicability::MachineApplicable,
);
}
let mut inner_callee_path = None;
let def = match callee_expr.kind {
hir::ExprKind::Path(ref qpath) => {
self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
}
hir::ExprKind::Call(ref inner_callee, _) => {
// If the call spans more than one line and the callee kind is
// itself another `ExprCall`, that's a clue that we might just be
// missing a semicolon (Issue #51055)
let call_is_multiline =
self.tcx.sess.source_map().is_multiline(call_expr.span);
if call_is_multiline {
err.span_suggestion(
callee_expr.span.shrink_to_hi(),
"consider using a semicolon here",
";",
Applicability::MaybeIncorrect,
);
}
if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
inner_callee_path = Some(inner_qpath);
self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
} else {
Res::Err
}
}
_ => Res::Err,
};
if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_expr, callee_ty)
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
{
let descr = match maybe_def {
DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
DefIdOrName::Name(name) => name,
};
err.span_label(
callee_expr.span,
format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
);
if let DefIdOrName::DefId(def_id) = maybe_def
&& let Some(def_span) = self.tcx.hir().span_if_local(def_id)
{
err.span_label(def_span, "the callable type is defined here");
}
} else {
err.span_label(call_expr.span, "call expression requires function");
}
}
if let Some(span) = self.tcx.hir().res_span(def) {
let callee_ty = callee_ty.to_string();
let label = match (unit_variant, inner_callee_path) {
(Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
(_, Some(hir::QPath::Resolved(_, path))) => self
.tcx
.sess
.source_map()
.span_to_snippet(path.span)
.ok()
.map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
_ => {
match def {
// Emit a different diagnostic for local variables, as they are not
// type definitions themselves, but rather variables *of* that type.
Res::Local(hir_id) => Some(format!(
"`{}` has type `{}`",
self.tcx.hir().name(hir_id),
callee_ty
)),
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
Some(format!(
"`{}` defined here",
self.tcx.def_path_str(def_id),
))
}
_ => Some(format!("`{callee_ty}` defined here")),
}
}
};
if let Some(label) = label {
err.span_label(span, label);
}
}
err.emit();
self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
// This is the "default" function signature, used in case of error.
// In that case, we check each argument against "error" in order to
@ -574,6 +441,145 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn_sig.output()
}
fn report_invalid_callee(
&self,
call_expr: &'tcx hir::Expr<'tcx>,
callee_expr: &'tcx hir::Expr<'tcx>,
callee_ty: Ty<'tcx>,
arg_exprs: &'tcx [hir::Expr<'tcx>],
) {
let mut unit_variant = None;
if let hir::ExprKind::Path(qpath) = &callee_expr.kind
&& let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
= self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
// Only suggest removing parens if there are no arguments
&& arg_exprs.is_empty()
{
let descr = match kind {
def::CtorOf::Struct => "struct",
def::CtorOf::Variant => "enum variant",
};
let removal_span =
callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
unit_variant =
Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
}
let callee_ty = self.resolve_vars_if_possible(callee_ty);
let mut err = type_error_struct!(
self.tcx.sess,
callee_expr.span,
callee_ty,
E0618,
"expected function, found {}",
match &unit_variant {
Some((_, kind, path)) => format!("{kind} `{path}`"),
None => format!("`{callee_ty}`"),
}
);
self.identify_bad_closure_def_and_call(
&mut err,
call_expr.hir_id,
&callee_expr.kind,
callee_expr.span,
);
if let Some((removal_span, kind, path)) = &unit_variant {
err.span_suggestion_verbose(
*removal_span,
&format!(
"`{path}` is a unit {kind}, and does not take parentheses to be constructed",
),
"",
Applicability::MachineApplicable,
);
}
let mut inner_callee_path = None;
let def = match callee_expr.kind {
hir::ExprKind::Path(ref qpath) => {
self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
}
hir::ExprKind::Call(ref inner_callee, _) => {
// If the call spans more than one line and the callee kind is
// itself another `ExprCall`, that's a clue that we might just be
// missing a semicolon (Issue #51055)
let call_is_multiline = self.tcx.sess.source_map().is_multiline(call_expr.span);
if call_is_multiline {
err.span_suggestion(
callee_expr.span.shrink_to_hi(),
"consider using a semicolon here",
";",
Applicability::MaybeIncorrect,
);
}
if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
inner_callee_path = Some(inner_qpath);
self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
} else {
Res::Err
}
}
_ => Res::Err,
};
if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_expr, callee_ty)
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
{
let descr = match maybe_def {
DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
DefIdOrName::Name(name) => name,
};
err.span_label(
callee_expr.span,
format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
);
if let DefIdOrName::DefId(def_id) = maybe_def
&& let Some(def_span) = self.tcx.hir().span_if_local(def_id)
{
err.span_label(def_span, "the callable type is defined here");
}
} else {
err.span_label(call_expr.span, "call expression requires function");
}
}
if let Some(span) = self.tcx.hir().res_span(def) {
let callee_ty = callee_ty.to_string();
let label = match (unit_variant, inner_callee_path) {
(Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
(_, Some(hir::QPath::Resolved(_, path))) => self
.tcx
.sess
.source_map()
.span_to_snippet(path.span)
.ok()
.map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
_ => {
match def {
// Emit a different diagnostic for local variables, as they are not
// type definitions themselves, but rather variables *of* that type.
Res::Local(hir_id) => Some(format!(
"`{}` has type `{}`",
self.tcx.hir().name(hir_id),
callee_ty
)),
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
Some(format!("`{}` defined here", self.tcx.def_path_str(def_id),))
}
_ => Some(format!("`{callee_ty}` defined here")),
}
}
};
if let Some(label) = label {
err.span_label(span, label);
}
}
err.emit();
}
fn confirm_deferred_closure_call(
&self,
call_expr: &'tcx hir::Expr<'tcx>,

View File

@ -224,7 +224,7 @@ impl<'a> Iterator for Parser<'a> {
'{' => {
let curr_last_brace = self.last_opening_brace;
let byte_pos = self.to_span_index(pos);
let lbrace_end = InnerOffset(byte_pos.0 + 1);
let lbrace_end = self.to_span_index(pos + 1);
self.last_opening_brace = Some(byte_pos.to(lbrace_end));
self.cur.next();
if self.consume('{') {

View File

@ -716,7 +716,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
document(&mut content, cx, m, Some(t), HeadingOffset::H5);
let toggled = !content.is_empty();
if toggled {
write!(w, "<details class=\"rustdoc-toggle\" open><summary>");
write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
}
write!(w, "<div id=\"{}\" class=\"method has-srclink\">", id);
render_rightside(w, cx, m, t, RenderMode::Normal);

View File

@ -138,6 +138,13 @@ h1, h2, h3, h4 {
.docblock h3, .docblock h4, h5, h6 {
margin: 15px 0 5px 0;
}
.docblock > h2:first-child,
.docblock > h3:first-child,
.docblock > h4:first-child,
.docblock > h5:first-child,
.docblock > h6:first-child {
margin-top: 0;
}
h1.fqn {
margin: 0;
padding: 0;
@ -187,7 +194,6 @@ h4.code-header {
.impl-items .associatedtype,
.methods .associatedtype {
flex-basis: 100%;
font-weight: 600;
position: relative;
}
@ -2008,7 +2014,8 @@ in storage.js plus the media query with (min-width: 701px)
.method-toggle summary,
.implementors-toggle summary,
.impl {
.impl,
#implementors-list > .docblock {
margin-bottom: 0.75em;
}

View File

@ -7,5 +7,5 @@
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
// We check that ".item-info" is bigger than its content.
move-cursor-to: ".impl"
assert-property: (".impl > a.anchor", {"offsetWidth": "9"})
assert-property: (".impl > a.anchor", {"offsetWidth": "8"})
assert-css: (".impl > a.anchor", {"left": "-8px"})

View File

@ -13,7 +13,7 @@ goto: file://|DOC_PATH|/test_docs/type.SomeType.html
assert-css: (".top-doc .docblock p", {"font-weight": "400"}, ALL)
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
assert-css: (".impl-items .method", {"font-weight": "600"}, ALL)
assert-css: (".impl-items .method > .code-header", {"font-weight": "600"}, ALL)
goto: file://|DOC_PATH|/lib2/trait.Trait.html
@ -41,4 +41,4 @@ assert-count: (".methods .associatedtype", 1)
assert-css: (".methods .associatedtype", {"font-weight": "600"})
assert-count: (".methods .constant", 1)
assert-css: (".methods .constant", {"font-weight": "600"})
assert-css: (".methods .method", {"font-weight": "600"})
assert-css: (".methods .method > .code-header", {"font-weight": "600"})

View File

@ -4,8 +4,8 @@
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
show-text: true
// Check the impl headers.
assert-css: (".impl.has-srclink .srclink", {"font-size": "16px"}, ALL)
assert-css: (".impl.has-srclink .code-header", {"font-size": "18px"}, ALL)
assert-css: (".impl.has-srclink .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
assert-css: (".impl.has-srclink .code-header", {"font-size": "18px", "font-weight": 600}, ALL)
// Check the impl items.
assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px"}, ALL)
assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px"}, ALL)
assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px", "font-weight": 600}, ALL)

View File

@ -4,12 +4,12 @@
// summary. Trait methods with no documentation should not be wrapped.
//
// @has foo/trait.Foo.html
// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
// @has - '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented is documented'
// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
// @has - '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
pub trait Foo {
fn not_documented();

View File

@ -0,0 +1,19 @@
fn main() {
format!("\x7Ba}");
//~^ ERROR cannot find value `a` in this scope
format!("\x7Ba\x7D");
//~^ ERROR cannot find value `a` in this scope
let a = 0;
format!("\x7Ba} {b}");
//~^ ERROR cannot find value `b` in this scope
format!("\x7Ba\x7D {b}");
//~^ ERROR cannot find value `b` in this scope
format!("\x7Ba} \x7Bb}");
//~^ ERROR cannot find value `b` in this scope
format!("\x7Ba\x7D \x7Bb}");
//~^ ERROR cannot find value `b` in this scope
format!("\x7Ba\x7D \x7Bb\x7D");
//~^ ERROR cannot find value `b` in this scope
}

View File

@ -0,0 +1,45 @@
error[E0425]: cannot find value `a` in this scope
--> $DIR/format-args-capture-issue-102057.rs:2:18
|
LL | format!("\x7Ba}");
| ^ not found in this scope
error[E0425]: cannot find value `a` in this scope
--> $DIR/format-args-capture-issue-102057.rs:4:18
|
LL | format!("\x7Ba\x7D");
| ^ not found in this scope
error[E0425]: cannot find value `b` in this scope
--> $DIR/format-args-capture-issue-102057.rs:9:22
|
LL | format!("\x7Ba} {b}");
| ^ help: a local variable with a similar name exists: `a`
error[E0425]: cannot find value `b` in this scope
--> $DIR/format-args-capture-issue-102057.rs:11:25
|
LL | format!("\x7Ba\x7D {b}");
| ^ help: a local variable with a similar name exists: `a`
error[E0425]: cannot find value `b` in this scope
--> $DIR/format-args-capture-issue-102057.rs:13:25
|
LL | format!("\x7Ba} \x7Bb}");
| ^ help: a local variable with a similar name exists: `a`
error[E0425]: cannot find value `b` in this scope
--> $DIR/format-args-capture-issue-102057.rs:15:28
|
LL | format!("\x7Ba\x7D \x7Bb}");
| ^ help: a local variable with a similar name exists: `a`
error[E0425]: cannot find value `b` in this scope
--> $DIR/format-args-capture-issue-102057.rs:17:28
|
LL | format!("\x7Ba\x7D \x7Bb\x7D");
| ^ help: a local variable with a similar name exists: `a`
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0425`.

View File

@ -73,14 +73,11 @@ const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
/// these and all their dependencies *must not* be in the exception list.
const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
/// Crates whose dependencies must be explicitly permitted.
const RESTRICTED_DEPENDENCY_CRATES: &[&str] = &["rustc_driver", "rustc_codegen_llvm"];
/// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
///
/// This list is here to provide a speed-bump to adding a new dependency to
/// rustc. Please check with the compiler team before adding an entry.
const PERMITTED_DEPENDENCIES: &[&str] = &[
const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"addr2line",
"adler",
"ahash",
@ -307,7 +304,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
];
const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
// These two crates take quite a long time to build, so don't allow two versions of them
// This crate takes quite a long time to build, so don't allow two versions of them
// to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
// under control.
"cargo",
@ -324,12 +321,12 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
.features(cargo_metadata::CargoOpt::AllFeatures);
let metadata = t!(cmd.exec());
let runtime_ids = compute_runtime_crates(&metadata);
check_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
check_dependencies(
check_license_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
check_permitted_dependencies(
&metadata,
"main workspace",
PERMITTED_DEPENDENCIES,
RESTRICTED_DEPENDENCY_CRATES,
"rustc",
PERMITTED_RUSTC_DEPENDENCIES,
&["rustc_driver", "rustc_codegen_llvm"],
bad,
);
check_crate_duplicate(&metadata, FORBIDDEN_TO_HAVE_DUPLICATES, bad);
@ -342,8 +339,8 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
.features(cargo_metadata::CargoOpt::AllFeatures);
let metadata = t!(cmd.exec());
let runtime_ids = HashSet::new();
check_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad);
check_dependencies(
check_license_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad);
check_permitted_dependencies(
&metadata,
"cranelift",
PERMITTED_CRANELIFT_DEPENDENCIES,
@ -358,13 +355,13 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
.features(cargo_metadata::CargoOpt::AllFeatures);
let metadata = t!(cmd.exec());
let runtime_ids = HashSet::new();
check_exceptions(&metadata, EXCEPTIONS_BOOTSTRAP, runtime_ids, bad);
check_license_exceptions(&metadata, EXCEPTIONS_BOOTSTRAP, runtime_ids, bad);
}
/// Check that all licenses are in the valid list in `LICENSES`.
///
/// Packages listed in `EXCEPTIONS` are allowed for tools.
fn check_exceptions(
/// Packages listed in `exceptions` are allowed for tools.
fn check_license_exceptions(
metadata: &Metadata,
exceptions: &[(&str, &str)],
runtime_ids: HashSet<&PackageId>,
@ -434,11 +431,11 @@ fn check_exceptions(
}
}
/// Checks the dependency of `RESTRICTED_DEPENDENCY_CRATES` at the given path. Changes `bad` to
/// Checks the dependency of `restricted_dependency_crates` at the given path. Changes `bad` to
/// `true` if a check failed.
///
/// Specifically, this checks that the dependencies are on the `PERMITTED_DEPENDENCIES`.
fn check_dependencies(
/// Specifically, this checks that the dependencies are on the `permitted_dependencies`.
fn check_permitted_dependencies(
metadata: &Metadata,
descr: &str,
permitted_dependencies: &[&'static str],