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 7 pull requests #100330

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
27b9b16
Error on broken pipe but do not ICE
ChrisDenton 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
18a21e1
Remove duplicated temporaries creating during box derefs elaboration
tmiasko Aug 6, 2022
7d2131a
./x.py test --bless
tmiasko Aug 6, 2022
db7ddc5
Do not manually craft a span pointing inside a multibyte character.
cjgillot Aug 7, 2022
ac75863
Add more `// unit-test`s to MIR opt tests
JakobDegen Aug 3, 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
507b299
Rollup merge of #100040 - ChrisDenton:broken-pipe, r=davidtwco
Dylan-DPC Aug 9, 2022
5ca5f02
Rollup merge of #100086 - JakobDegen:better-tests, r=wesleywiser
Dylan-DPC Aug 9, 2022
2adcb4c
Rollup merge of #100098 - compiler-errors:field-suggestion-fixups, r=…
Dylan-DPC Aug 9, 2022
0888432
Rollup merge of #100192 - tmiasko:rm-duplicated-locals, r=nagisa
Dylan-DPC Aug 9, 2022
be071ec
Rollup merge of #100226 - cjgillot:noice-multibyte, r=davidtwco
Dylan-DPC Aug 9, 2022
e606861
Rollup merge of #100261 - luqmana:suggestions-overflow, r=lcnr
Dylan-DPC Aug 9, 2022
6109582
Rollup merge of #100319 - GuillaumeGomez:rm-clean-impls-2, r=Dylan-DPC
Dylan-DPC 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
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
8 changes: 0 additions & 8 deletions compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> {
build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did);

let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
self.local_decls.push(LocalDecl::new(ptr_ty, source_info.span));

self.patch.add_statement(location, StatementKind::StorageLive(ptr_local));

Expand Down Expand Up @@ -125,13 +124,6 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
index += 1;
}

if let Some(terminator) = terminator
&& !matches!(terminator.kind, TerminatorKind::Yield{..})
{
let location = Location { block, statement_index: index };
visitor.visit_terminator(terminator, location);
}

let location = Location { block, statement_index: index };
match terminator {
// yielding into a box is handled when lowering generators
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
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
8 changes: 4 additions & 4 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};

use crate::clean::{
self, clean_fn_decl_from_did_and_sig, clean_middle_field, clean_middle_ty,
clean_trait_ref_with_bindings, clean_ty, clean_ty_generics, clean_variant_def,
self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_field,
clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, clean_ty_generics, clean_variant_def,
clean_visibility, utils, Attributes, AttributesExt, Clean, ImplKind, ItemId, Type, Visibility,
};
use crate::core::DocContext;
Expand Down Expand Up @@ -426,9 +426,9 @@ pub(crate) fn build_impl(
true
}
})
.map(|item| item.clean(cx))
.map(|item| clean_impl_item(item, cx))
.collect::<Vec<_>>(),
impl_.generics.clean(cx),
clean_generics(impl_.generics, cx),
),
None => (
tcx.associated_items(did)
Expand Down
Loading