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 6 pull requests #125344

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cfb0479
Fix `read_exact` and `read_buf_exact` for `&[u8]` and `io:Cursor`
a1phyr May 14, 2024
4b7466c
Add codegen test for array comparision opt
tesuji May 20, 2024
b092b5d
Note for E0599 if shadowed bindings has the method.
surechen Apr 23, 2024
a197ff3
Address review comments
a1phyr May 20, 2024
8d3bc55
Fix up a few more tests
saethlin Apr 17, 2024
e0632d7
Add only-unix to sigpipe tests
saethlin Apr 18, 2024
18b0a07
Handle a few more simple tests
saethlin Apr 18, 2024
281178d
Add a Windows version of foreign2.rs
saethlin Apr 18, 2024
70147cd
Patch up foreign-fn-linkname.rs
saethlin Apr 18, 2024
7a906e1
Port stdout-during-shutdown
saethlin Apr 18, 2024
f45a7a2
Fix feature-gates/rustc-private.rs
saethlin Apr 18, 2024
30379f9
Update tests/incremental/foreign.rs
saethlin Apr 19, 2024
aa31281
Remove Windows dependency on libc
saethlin Apr 18, 2024
39ef149
Undo accidental change to tests/ui/sanitizer/thread.rs
saethlin May 14, 2024
422de35
make it into an IR test
tesuji May 20, 2024
ba8fba9
Update books
rustbot May 20, 2024
7b1527f
hir pretty: fix block indent
Noratrieb May 15, 2024
59a4f7c
Rollup merge of #124050 - saethlin:less-sysroot-libc, r=ChrisDenton
matthiaskrgr May 20, 2024
98bec6e
Rollup merge of #124283 - surechen:fix_123558, r=estebank
matthiaskrgr May 20, 2024
6586ed7
Rollup merge of #125123 - a1phyr:fix-read_exact, r=workingjubilee
matthiaskrgr May 20, 2024
885b456
Rollup merge of #125158 - Nilstrieb:block-indent, r=compiler-errors
matthiaskrgr May 20, 2024
65dff32
Rollup merge of #125298 - tesuji:arrcmp, r=nikic
matthiaskrgr May 20, 2024
ee8ea3a
Rollup merge of #125332 - rustbot:docs-update, r=ehuss
matthiaskrgr May 20, 2024
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
2 changes: 1 addition & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ impl<'a> State<'a> {
self.word_space(":");
}
// containing cbox, will be closed by print-block at `}`
self.cbox(INDENT_UNIT);
self.cbox(0);
// head-box, will be closed by print-block after `{`
self.ibox(0);
self.print_block(blk);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if segment.ident.name != kw::Empty {
if let Some(err) = self.report_method_error(
span,
Some(rcvr),
rcvr_t,
segment.ident,
SelfSource::MethodCall(rcvr),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if item_name.name != kw::Empty {
if let Some(e) = self.report_method_error(
span,
None,
ty.normalized,
item_name,
SelfSource::QPath(qself),
Expand Down
213 changes: 207 additions & 6 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
use crate::Expectation;
use crate::FnCtxt;
use core::ops::ControlFlow;
use hir::Expr;
use rustc_ast::ast::Mutability;
use rustc_attr::parse_confusables;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
Expand All @@ -19,7 +20,6 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::PatKind::Binding;
use rustc_hir::PathSegment;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_infer::infer::{self, RegionVariableOrigin};
Expand All @@ -46,7 +46,7 @@ use std::borrow::Cow;

use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
use rustc_hir::intravisit::Visitor;
use rustc_hir::intravisit::{self, Visitor};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
Expand Down Expand Up @@ -188,6 +188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn report_method_error(
&self,
span: Span,
rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
rcvr_ty: Ty<'tcx>,
item_name: Ident,
source: SelfSource<'tcx>,
Expand All @@ -212,6 +213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
MethodError::NoMatch(mut no_match_data) => {
return self.report_no_match_method_error(
span,
rcvr_opt,
rcvr_ty,
item_name,
source,
Expand Down Expand Up @@ -356,9 +358,197 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err
}

pub fn suggest_use_shadowed_binding_with_method(
&self,
rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
method_name: Ident,
ty_str_reported: &str,
err: &mut Diag<'_>,
) {
#[derive(Debug)]
struct LetStmt {
ty_hir_id_opt: Option<hir::HirId>,
binding_id: hir::HirId,
span: Span,
init_hir_id: hir::HirId,
}

// Used for finding suggest binding.
// ```rust
// earlier binding for suggesting:
// let y = vec![1, 2];
// now binding:
// if let Some(y) = x {
// y.push(y);
// }
// ```
struct LetVisitor<'a, 'tcx> {
// Error binding which don't have `method_name`.
binding_name: Symbol,
binding_id: hir::HirId,
// Used for check if the suggest binding has `method_name`.
fcx: &'a FnCtxt<'a, 'tcx>,
call_expr: &'tcx Expr<'tcx>,
method_name: Ident,
// Suggest the binding which is shallowed.
sugg_let: Option<LetStmt>,
}

impl<'a, 'tcx> LetVisitor<'a, 'tcx> {
// Check scope of binding.
fn is_sub_scope(&self, sub_id: hir::ItemLocalId, super_id: hir::ItemLocalId) -> bool {
let scope_tree = self.fcx.tcx.region_scope_tree(self.fcx.body_id);
if let Some(sub_var_scope) = scope_tree.var_scope(sub_id)
&& let Some(super_var_scope) = scope_tree.var_scope(super_id)
&& scope_tree.is_subscope_of(sub_var_scope, super_var_scope)
{
return true;
}
false
}

// Check if an earlier shadowed binding make `the receiver` of a MethodCall has the method.
// If it does, record the earlier binding for subsequent notes.
fn check_and_add_sugg_binding(&mut self, binding: LetStmt) -> bool {
if !self.is_sub_scope(self.binding_id.local_id, binding.binding_id.local_id) {
return false;
}

// Get the earlier shadowed binding'ty and use it to check the method.
if let Some(ty_hir_id) = binding.ty_hir_id_opt
&& let Some(tyck_ty) = self.fcx.node_ty_opt(ty_hir_id)
{
if self
.fcx
.lookup_probe_for_diagnostic(
self.method_name,
tyck_ty,
self.call_expr,
ProbeScope::TraitsInScope,
None,
)
.is_ok()
{
self.sugg_let = Some(binding);
return true;
} else {
return false;
}
}

// If the shadowed binding has an an itializer expression,
// use the initializer expression'ty to try to find the method again.
// For example like: `let mut x = Vec::new();`,
// `Vec::new()` is the itializer expression.
if let Some(self_ty) = self.fcx.node_ty_opt(binding.init_hir_id)
&& self
.fcx
.lookup_probe_for_diagnostic(
self.method_name,
self_ty,
self.call_expr,
ProbeScope::TraitsInScope,
None,
)
.is_ok()
{
self.sugg_let = Some(binding);
return true;
}
return false;
}
}

impl<'v> Visitor<'v> for LetVisitor<'_, '_> {
type Result = ControlFlow<()>;
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
if let hir::StmtKind::Let(&hir::LetStmt { pat, ty, init, .. }) = ex.kind
&& let hir::PatKind::Binding(_, binding_id, binding_name, ..) = pat.kind
&& let Some(init) = init
&& binding_name.name == self.binding_name
&& binding_id != self.binding_id
{
if self.check_and_add_sugg_binding(LetStmt {
ty_hir_id_opt: if let Some(ty) = ty { Some(ty.hir_id) } else { None },
binding_id: binding_id,
span: pat.span,
init_hir_id: init.hir_id,
}) {
return ControlFlow::Break(());
}
ControlFlow::Continue(())
} else {
hir::intravisit::walk_stmt(self, ex)
}
}

// Used for find the error binding.
// When the visitor reaches this point, all the shadowed bindings
// have been found, so the visitor ends.
fn visit_pat(&mut self, p: &'v hir::Pat<'v>) -> Self::Result {
match p.kind {
hir::PatKind::Binding(_, binding_id, binding_name, _) => {
if binding_name.name == self.binding_name && binding_id == self.binding_id {
return ControlFlow::Break(());
}
}
_ => {
intravisit::walk_pat(self, p);
}
}
ControlFlow::Continue(())
}
}

if let Some(rcvr) = rcvr_opt
&& let hir::ExprKind::Path(QPath::Resolved(_, path)) = rcvr.kind
&& let hir::def::Res::Local(recv_id) = path.res
&& let Some(segment) = path.segments.first()
{
let map = self.infcx.tcx.hir();
let body_id = self.tcx.hir().body_owned_by(self.body_id);
let body = map.body(body_id);

if let Node::Expr(call_expr) = self.tcx.parent_hir_node(rcvr.hir_id) {
let mut let_visitor = LetVisitor {
fcx: self,
call_expr,
binding_name: segment.ident.name,
binding_id: recv_id,
method_name,
sugg_let: None,
};
let_visitor.visit_body(body);
if let Some(sugg_let) = let_visitor.sugg_let
&& let Some(self_ty) = self.node_ty_opt(sugg_let.init_hir_id)
{
let _sm = self.infcx.tcx.sess.source_map();
let rcvr_name = segment.ident.name;
let mut span = MultiSpan::from_span(sugg_let.span);
span.push_span_label(sugg_let.span,
format!("`{rcvr_name}` of type `{self_ty}` that has method `{method_name}` defined earlier here"));
span.push_span_label(
self.tcx.hir().span(recv_id),
format!(
"earlier `{rcvr_name}` shadowed here with type `{ty_str_reported}`"
),
);
err.span_note(
span,
format!(
"there's an earlier shadowed binding `{rcvr_name}` of type `{self_ty}` \
that has method `{method_name}` available"
),
);
}
}
}
}

pub fn report_no_match_method_error(
&self,
mut span: Span,
rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
rcvr_ty: Ty<'tcx>,
item_name: Ident,
source: SelfSource<'tcx>,
Expand Down Expand Up @@ -451,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
self.suggest_missing_writer(rcvr_ty, rcvr_expr)
} else {
tcx.dcx().create_err(NoAssociatedItem {
let mut err = tcx.dcx().create_err(NoAssociatedItem {
span,
item_kind,
item_name,
Expand All @@ -461,9 +651,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
rcvr_ty.prefix_string(self.tcx)
},
ty_str: ty_str_reported,
ty_str: ty_str_reported.clone(),
trait_missing_method,
})
});

if is_method {
self.suggest_use_shadowed_binding_with_method(
rcvr_opt,
item_name,
&ty_str_reported,
&mut err,
);
}

err
};
if tcx.sess.source_map().is_multiline(sugg_span) {
err.span_label(sugg_span.with_hi(span.lo()), "");
Expand Down Expand Up @@ -2240,7 +2441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
type Result = ControlFlow<Option<&'v hir::Expr<'v>>>;
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
if let hir::StmtKind::Let(&hir::LetStmt { pat, init, .. }) = ex.kind
&& let Binding(_, _, ident, ..) = pat.kind
&& let hir::PatKind::Binding(_, _, ident, ..) = pat.kind
&& ident.name == self.ident_name
{
ControlFlow::Break(init)
Expand Down
3 changes: 0 additions & 3 deletions library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ addr2line = { version = "0.21.0", optional = true, default-features = false }
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }

[target.'cfg(all(windows, target_env = "msvc"))'.dependencies]
libc = { version = "0.2.153", default-features = false }

[target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }

Expand Down
27 changes: 17 additions & 10 deletions library/std/src/io/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ where
fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
let prev_written = cursor.written();

Read::read_buf(&mut self.fill_buf()?, cursor.reborrow())?;
Read::read_buf(&mut self.remaining_slice(), cursor.reborrow())?;

self.pos += (cursor.written() - prev_written) as u64;

Expand All @@ -352,17 +352,24 @@ where
}

fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
let n = buf.len();
Read::read_exact(&mut self.remaining_slice(), buf)?;
self.pos += n as u64;
Ok(())
let result = Read::read_exact(&mut self.remaining_slice(), buf);

match result {
Ok(_) => self.pos += buf.len() as u64,
// The only possible error condition is EOF, so place the cursor at "EOF"
Err(_) => self.pos = self.inner.as_ref().len() as u64,
}

result
}

fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
let n = cursor.capacity();
Read::read_buf_exact(&mut self.remaining_slice(), cursor)?;
self.pos += n as u64;
Ok(())
fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
let prev_written = cursor.written();

let result = Read::read_buf_exact(&mut self.remaining_slice(), cursor.reborrow());
self.pos += (cursor.written() - prev_written) as u64;

result
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
Expand Down
6 changes: 6 additions & 0 deletions library/std/src/io/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ impl Read for &[u8] {
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
if buf.len() > self.len() {
// `read_exact` makes no promise about the content of `buf` if it
// fails so don't bother about that.
*self = &self[self.len()..];
return Err(io::Error::READ_EXACT_EOF);
}
let (a, b) = self.split_at(buf.len());
Expand All @@ -307,6 +310,9 @@ impl Read for &[u8] {
#[inline]
fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
if cursor.capacity() > self.len() {
// Append everything we can to the cursor.
cursor.append(*self);
*self = &self[self.len()..];
return Err(io::Error::READ_EXACT_EOF);
}
let (a, b) = self.split_at(cursor.capacity());
Expand Down
Loading
Loading