Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 14 pull requests #100346

Merged
merged 37 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6b60bc6
rustdoc: improve scroll locking in the rustdoc mobile sidebars
notriddle Jul 1, 2022
4e73d90
rustdoc-json: De-duplicate `FromWithTcx<clean::Import>`
Enselic Jul 19, 2022
3dfd268
rustdoc-json: Add tests for re-exports of primitives
Enselic Jul 19, 2022
1b6f629
rustdoc-json: Remove doc FIXME for Import::id and explain
Enselic Jul 19, 2022
27b9b16
Error on broken pipe but do not ICE
ChrisDenton Aug 2, 2022
e1eab53
linker-plugin-lto.md: Correct the name of example c file
oToToT Aug 2, 2022
9cf5709
Suggest expressions' fields even if they're not ADTs
compiler-errors Aug 3, 2022
4df6cbe
Consider privacy more carefully when suggesting accessing fields
compiler-errors Aug 3, 2022
2a3fd50
Don't suggest field method if it's just missing some bounds
compiler-errors Aug 3, 2022
603ffeb
Skip over structs with no private fields that impl Deref
compiler-errors Aug 3, 2022
db7ddc5
Do not manually craft a span pointing inside a multibyte character.
cjgillot Aug 7, 2022
aa031f9
Fail gracefully when const pattern is not structural match.
cjgillot Aug 7, 2022
1f75142
Add some high-level docs to `FnCtxt` and `ItemCtxt`
camelid Aug 8, 2022
92ce2c1
also update anyhow in codegen_cranelift
RalfJung Aug 8, 2022
bed8e93
remove Clean trait implementation for hir::ImplItem
GuillaumeGomez Aug 8, 2022
daa0e8f
remove Clean trait implementation for hir::Generics
GuillaumeGomez Aug 8, 2022
fb8636f
Set tainted errors bit before emitting coerce suggestions.
luqmana Aug 8, 2022
75cc9cd
Add test for #100246.
luqmana Aug 8, 2022
5ed55f7
remove Clean trait implementation for ast::Module
GuillaumeGomez Aug 8, 2022
dd816a9
Prevent impl blocks containing only private items to be documented by…
GuillaumeGomez Aug 9, 2022
c634852
Add test for impl blocks containing only private items
GuillaumeGomez Aug 9, 2022
6ae1c03
Mention `unit-test` in MIR opt test README
JakobDegen Aug 9, 2022
31a0518
Address review comments
camelid Aug 8, 2022
02fc0fa
Rollup merge of #98775 - notriddle:notriddle/mobile-sidebar-scroll-lo…
matthiaskrgr Aug 9, 2022
0dc39c7
Rollup merge of #99479 - Enselic:import-can-be-without-id, r=camelid
matthiaskrgr Aug 9, 2022
cf7a9ae
Rollup merge of #100040 - ChrisDenton:broken-pipe, r=davidtwco
matthiaskrgr Aug 9, 2022
2059391
Rollup merge of #100072 - oToToT:patch-1, r=michaelwoerister
matthiaskrgr Aug 9, 2022
867453e
Rollup merge of #100098 - compiler-errors:field-suggestion-fixups, r=…
matthiaskrgr Aug 9, 2022
e6c9594
Rollup merge of #100226 - cjgillot:noice-multibyte, r=davidtwco
matthiaskrgr Aug 9, 2022
b11b8d6
Rollup merge of #100240 - cjgillot:noice-structural-match, r=davidtwco
matthiaskrgr Aug 9, 2022
4add514
Rollup merge of #100256 - camelid:typeck-ctxt-doc, r=compiler-errors
matthiaskrgr Aug 9, 2022
2be32e8
Rollup merge of #100261 - luqmana:suggestions-overflow, r=lcnr
matthiaskrgr Aug 9, 2022
45c9dde
Rollup merge of #100275 - RalfJung:anyhow, r=bjorn3
matthiaskrgr Aug 9, 2022
790b19f
Rollup merge of #100281 - GuillaumeGomez:rm-clean-impls-3, r=notriddle
matthiaskrgr Aug 9, 2022
e8d8599
Rollup merge of #100314 - JakobDegen:test-docs, r=RalfJung
matthiaskrgr Aug 9, 2022
a431ef4
Rollup merge of #100319 - GuillaumeGomez:rm-clean-impls-2, r=Dylan-DPC
matthiaskrgr Aug 9, 2022
752b9a8
Rollup merge of #100323 - GuillaumeGomez:impl-blocks-only-private, r=…
matthiaskrgr Aug 9, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ dependencies = [

[[package]]
name = "anyhow"
version = "1.0.56"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"

[[package]]
name = "ar"
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,17 @@ static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send +
LazyLock::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| {
// If the error was caused by a broken pipe then this is not a bug.
// Write the error and return immediately. See #98700.
#[cfg(windows)]
if let Some(msg) = info.payload().downcast_ref::<String>() {
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
{
early_error_no_abort(ErrorOutputType::default(), &msg);
return;
}
};

// Invoke the default handler, which prints the actual panic message and optionally a backtrace
(*DEFAULT_HOOK)(info);

Expand Down
88 changes: 42 additions & 46 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_middle::ty::adjustment;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::Symbol;
use rustc_span::symbol::{kw, sym};
use rustc_span::{BytePos, Span, DUMMY_SP};
use rustc_span::{BytePos, Span};

declare_lint! {
/// The `unused_must_use` lint detects unused result of a type flagged as
Expand Down Expand Up @@ -504,23 +504,23 @@ trait UnusedDelimLint {
ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
let start = block.stmts[0].span;
let end = block.stmts[block.stmts.len() - 1].span;
if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
(
value.span.with_hi(value.span.lo() + BytePos(1)),
value.span.with_lo(value.span.hi() - BytePos(1)),
)
if let Some(start) = start.find_ancestor_inside(value.span)
&& let Some(end) = end.find_ancestor_inside(value.span)
{
Some((
value.span.with_hi(start.lo()),
value.span.with_lo(end.hi()),
))
} else {
(value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
None
}
}
ast::ExprKind::Paren(ref expr) => {
if value.span.from_expansion() || expr.span.from_expansion() {
(
value.span.with_hi(value.span.lo() + BytePos(1)),
value.span.with_lo(value.span.hi() - BytePos(1)),
)
let expr_span = expr.span.find_ancestor_inside(value.span);
if let Some(expr_span) = expr_span {
Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
} else {
(value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
None
}
}
_ => return,
Expand All @@ -529,36 +529,38 @@ trait UnusedDelimLint {
left_pos.map_or(false, |s| s >= value.span.lo()),
right_pos.map_or(false, |s| s <= value.span.hi()),
);
self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
}

fn emit_unused_delims(
&self,
cx: &EarlyContext<'_>,
spans: (Span, Span),
value_span: Span,
spans: Option<(Span, Span)>,
msg: &str,
keep_space: (bool, bool),
) {
// FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
// properly.
if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
return;
}

cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
let replacement = vec![
(spans.0, if keep_space.0 { " ".into() } else { "".into() }),
(spans.1, if keep_space.1 { " ".into() } else { "".into() }),
];
lint.build(fluent::lint::unused_delim)
.set_arg("delim", Self::DELIM_STR)
.set_arg("item", msg)
.multipart_suggestion(
let primary_span = if let Some((lo, hi)) = spans {
MultiSpan::from(vec![lo, hi])
} else {
MultiSpan::from(value_span)
};
cx.struct_span_lint(self.lint(), primary_span, |lint| {
let mut db = lint.build(fluent::lint::unused_delim);
db.set_arg("delim", Self::DELIM_STR);
db.set_arg("item", msg);
if let Some((lo, hi)) = spans {
let replacement = vec![
(lo, if keep_space.0 { " ".into() } else { "".into() }),
(hi, if keep_space.1 { " ".into() } else { "".into() }),
];
db.multipart_suggestion(
fluent::lint::suggestion,
replacement,
Applicability::MachineApplicable,
)
.emit();
);
}
db.emit();
});
}

Expand Down Expand Up @@ -766,15 +768,12 @@ impl UnusedParens {
// Otherwise proceed with linting.
_ => {}
}
let spans = if value.span.from_expansion() || inner.span.from_expansion() {
(
value.span.with_hi(value.span.lo() + BytePos(1)),
value.span.with_lo(value.span.hi() - BytePos(1)),
)
let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
} else {
(value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
None
};
self.emit_unused_delims(cx, spans, "pattern", (false, false));
self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
}
}
}
Expand Down Expand Up @@ -879,15 +878,12 @@ impl EarlyLintPass for UnusedParens {
);
}
_ => {
let spans = if ty.span.from_expansion() || r.span.from_expansion() {
(
ty.span.with_hi(ty.span.lo() + BytePos(1)),
ty.span.with_lo(ty.span.hi() - BytePos(1)),
)
let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
} else {
(ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
None
};
self.emit_unused_delims(cx, spans, "type", (false, false));
self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,12 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
// once indirect_structural_match is a full fledged error, this
// level of indirection can be eliminated

let inlined_const_as_pat = self.recur(cv, mir_structural_match_violation).unwrap();
let inlined_const_as_pat =
self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| Pat {
span: self.span,
ty: cv.ty(),
kind: Box::new(PatKind::Constant { value: cv }),
});

if self.include_lint_checks && !self.saw_const_match_error.get() {
// If we were able to successfully convert the const to some pat,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_typeck/src/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}
}
Err(coercion_error) => {
// Mark that we've failed to coerce the types here to suppress
// any superfluous errors we might encounter while trying to
// emit or provide suggestions on how to fix the initial error.
fcx.set_tainted_by_errors();
let (expected, found) = if label_expression_as_expected {
// In the case where this is a "forced unit", like
// `break`, we want to call the `()` "expected"
Expand Down
72 changes: 43 additions & 29 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2526,15 +2526,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);

// try to add a suggestion in case the field is a nested field of a field of the Adt
if let Some((fields, substs)) = self.get_field_candidates(span, expr_t) {
for candidate_field in fields.iter() {
let mod_id = self.tcx.parent_module(id).to_def_id();
if let Some((fields, substs)) =
self.get_field_candidates_considering_privacy(span, expr_t, mod_id)
{
for candidate_field in fields {
if let Some(mut field_path) = self.check_for_nested_field_satisfying(
span,
&|candidate_field, _| candidate_field.ident(self.tcx()) == field,
candidate_field,
substs,
vec![],
self.tcx.parent_module(id).to_def_id(),
mod_id,
) {
// field_path includes `field` that we're looking for, so pop it.
field_path.pop();
Expand All @@ -2558,22 +2561,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err
}

pub(crate) fn get_field_candidates(
pub(crate) fn get_field_candidates_considering_privacy(
&self,
span: Span,
base_t: Ty<'tcx>,
) -> Option<(&[ty::FieldDef], SubstsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_t);
base_ty: Ty<'tcx>,
mod_id: DefId,
) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, SubstsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);

for (base_t, _) in self.autoderef(span, base_t) {
for (base_t, _) in self.autoderef(span, base_ty) {
match base_t.kind() {
ty::Adt(base_def, substs) if !base_def.is_enum() => {
let tcx = self.tcx;
let fields = &base_def.non_enum_variant().fields;
// For compile-time reasons put a limit on number of fields we search
if fields.len() > 100 {
return None;
// Some struct, e.g. some that impl `Deref`, have all private fields
// because you're expected to deref them to access the _real_ fields.
// This, for example, will help us suggest accessing a field through a `Box<T>`.
if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
continue;
}
return Some((fields, substs));
return Some((
fields
.iter()
.filter(move |field| field.vis.is_accessible_from(mod_id, tcx))
// For compile-time reasons put a limit on number of fields we search
.take(100),
substs,
));
}
_ => {}
}
Expand All @@ -2590,7 +2604,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
candidate_field: &ty::FieldDef,
subst: SubstsRef<'tcx>,
mut field_path: Vec<Ident>,
id: DefId,
mod_id: DefId,
) -> Option<Vec<Ident>> {
debug!(
"check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
Expand All @@ -2602,24 +2616,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// up to a depth of three
None
} else {
// recursively search fields of `candidate_field` if it's a ty::Adt
field_path.push(candidate_field.ident(self.tcx).normalize_to_macros_2_0());
let field_ty = candidate_field.ty(self.tcx, subst);
if let Some((nested_fields, subst)) = self.get_field_candidates(span, field_ty) {
for field in nested_fields.iter() {
if field.vis.is_accessible_from(id, self.tcx) {
if matches(candidate_field, field_ty) {
return Some(field_path);
} else if let Some(field_path) = self.check_for_nested_field_satisfying(
span,
matches,
field,
subst,
field_path.clone(),
id,
) {
return Some(field_path);
}
if matches(candidate_field, field_ty) {
return Some(field_path);
} else if let Some((nested_fields, subst)) =
self.get_field_candidates_considering_privacy(span, field_ty, mod_id)
{
// recursively search fields of `candidate_field` if it's a ty::Adt
for field in nested_fields {
if let Some(field_path) = self.check_for_nested_field_satisfying(
span,
matches,
field,
subst,
field_path.clone(),
mod_id,
) {
return Some(field_path);
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
use std::cell::{Cell, RefCell};
use std::ops::Deref;

/// The `FnCtxt` stores type-checking context needed to type-check bodies of
/// functions, closures, and `const`s, including performing type inference
/// with [`InferCtxt`].
///
/// This is in contrast to [`ItemCtxt`], which is used to type-check item *signatures*
/// and thus does not perform type inference.
///
/// See [`ItemCtxt`]'s docs for more.
///
/// [`ItemCtxt`]: crate::collect::ItemCtxt
/// [`InferCtxt`]: infer::InferCtxt
pub struct FnCtxt<'a, 'tcx> {
pub(super) body_id: hir::HirId,

Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
label_span_not_found(&mut err);
}

self.check_for_field_method(&mut err, source, span, actual, item_name);
// Don't suggest (for example) `expr.field.method()` if `expr.method()`
// doesn't exist due to unsatisfied predicates.
if unsatisfied_predicates.is_empty() {
self.check_for_field_method(&mut err, source, span, actual, item_name);
}

self.check_for_unwrap_self(&mut err, source, span, actual, item_name);

Expand Down Expand Up @@ -1334,10 +1338,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: Ident,
) {
if let SelfSource::MethodCall(expr) = source
&& let Some((fields, substs)) = self.get_field_candidates(span, actual)
&& let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
&& let Some((fields, substs)) = self.get_field_candidates_considering_privacy(span, actual, mod_id)
{
let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
for candidate_field in fields.iter() {
for candidate_field in fields {
if let Some(field_path) = self.check_for_nested_field_satisfying(
span,
&|_, field_ty| {
Expand All @@ -1353,7 +1358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
candidate_field,
substs,
vec![],
self.tcx.parent_module(expr.hir_id).to_def_id(),
mod_id,
) {
let field_path_str = field_path
.iter()
Expand Down
22 changes: 21 additions & 1 deletion compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,27 @@ pub fn provide(providers: &mut Providers) {
///////////////////////////////////////////////////////////////////////////

/// Context specific to some particular item. This is what implements
/// `AstConv`. It has information about the predicates that are defined
/// [`AstConv`].
///
/// # `ItemCtxt` vs `FnCtxt`
///
/// `ItemCtxt` is primarily used to type-check item signatures and lower them
/// from HIR to their [`ty::Ty`] representation, which is exposed using [`AstConv`].
/// It's also used for the bodies of items like structs where the body (the fields)
/// are just signatures.
///
/// This is in contrast to [`FnCtxt`], which is used to type-check bodies of
/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
///
/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
/// while `FnCtxt` does do inference.
///
/// [`FnCtxt`]: crate::check::FnCtxt
/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
///
/// # Trait predicates
///
/// `ItemCtxt` has information about the predicates that are defined
/// on the trait. Unfortunately, this predicate information is
/// available in various different forms at various points in the
/// process. So we can't just store a pointer to e.g., the AST or the
Expand Down
Loading