Skip to content

Commit a1fc711

Browse files
committed
Auto merge of #106177 - matthiaskrgr:rollup-oe7z8ix, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #105515 (Account for macros in const generics) - #106146 (Readme: update section on how to run `x.py`) - #106150 (Detect when method call on LHS might be shadowed) - #106174 (Remove unused empty CSS rules in ayu theme) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0ca5003 + d5810e8 commit a1fc711

File tree

12 files changed

+306
-27
lines changed

12 files changed

+306
-27
lines changed

README.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,23 @@ Read ["Installation"] from [The Book].
2020
The Rust build system uses a Python script called `x.py` to build the compiler,
2121
which manages the bootstrapping process. It lives at the root of the project.
2222

23-
The `x.py` command can be run directly on most systems in the following format:
23+
The `x.py` command can be run directly on most Unix systems in the following format:
2424

2525
```sh
2626
./x.py <subcommand> [flags]
2727
```
2828

29-
This is how the documentation and examples assume you are running `x.py`.
30-
31-
Systems such as Ubuntu 20.04 LTS do not create the necessary `python` command by default when Python is installed that allows `x.py` to be run directly. In that case, you can either create a symlink for `python` (Ubuntu provides the `python-is-python3` package for this), or run `x.py` using Python itself:
29+
This is how the documentation and examples assume you are running `x.py`. Some alternative ways are:
3230

3331
```sh
34-
# Python 3
35-
python3 x.py <subcommand> [flags]
32+
# On a Unix shell if you don't have the necessary `python3` command
33+
./x <subcommand> [flags]
34+
35+
# On the Windows Command Prompt (if .py files are configured to run Python)
36+
x.py <subcommand> [flags]
3637

37-
# Python 2.7
38-
python2.7 x.py <subcommand> [flags]
38+
# You can also run Python yourself, e.g.:
39+
python x.py <subcommand> [flags]
3940
```
4041

4142
More information about `x.py` can be found

compiler/rustc_hir_typeck/src/demand.rs

+160-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::FnCtxt;
22
use rustc_ast::util::parser::PREC_POSTFIX;
3+
use rustc_errors::MultiSpan;
34
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
45
use rustc_hir as hir;
56
use rustc_hir::def::CtorKind;
@@ -30,12 +31,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3031
expr_ty: Ty<'tcx>,
3132
expected: Ty<'tcx>,
3233
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
33-
_error: Option<TypeError<'tcx>>,
34+
error: Option<TypeError<'tcx>>,
3435
) {
3536
if expr_ty == expected {
3637
return;
3738
}
3839

40+
self.annotate_alternative_method_deref(err, expr, error);
41+
3942
// Use `||` to give these suggestions a precedence
4043
let _ = self.suggest_missing_parentheses(err, expr)
4144
|| self.suggest_remove_last_method_call(err, expr, expected)
@@ -316,6 +319,162 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
316319
}
317320
}
318321

322+
fn annotate_alternative_method_deref(
323+
&self,
324+
err: &mut Diagnostic,
325+
expr: &hir::Expr<'_>,
326+
error: Option<TypeError<'tcx>>,
327+
) {
328+
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
329+
let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;};
330+
let Some(hir::Node::Expr(hir::Expr {
331+
kind: hir::ExprKind::Assign(lhs, rhs, _), ..
332+
})) = self.tcx.hir().find(parent) else {return; };
333+
if rhs.hir_id != expr.hir_id || expected.is_closure() {
334+
return;
335+
}
336+
let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; };
337+
let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; };
338+
let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; };
339+
340+
let Ok(pick) = self
341+
.probe_for_name(
342+
probe::Mode::MethodCall,
343+
path.ident,
344+
probe::IsSuggestion(true),
345+
self_ty,
346+
deref.hir_id,
347+
probe::ProbeScope::TraitsInScope,
348+
) else {
349+
return;
350+
};
351+
let in_scope_methods = self.probe_for_name_many(
352+
probe::Mode::MethodCall,
353+
path.ident,
354+
probe::IsSuggestion(true),
355+
self_ty,
356+
deref.hir_id,
357+
probe::ProbeScope::TraitsInScope,
358+
);
359+
let other_methods_in_scope: Vec<_> =
360+
in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
361+
362+
let all_methods = self.probe_for_name_many(
363+
probe::Mode::MethodCall,
364+
path.ident,
365+
probe::IsSuggestion(true),
366+
self_ty,
367+
deref.hir_id,
368+
probe::ProbeScope::AllTraits,
369+
);
370+
let suggestions: Vec<_> = all_methods
371+
.into_iter()
372+
.filter(|c| c.item.def_id != pick.item.def_id)
373+
.map(|c| {
374+
let m = c.item;
375+
let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| {
376+
self.var_for_def(deref.span, param)
377+
});
378+
vec![
379+
(
380+
deref.span.until(base.span),
381+
format!(
382+
"{}({}",
383+
with_no_trimmed_paths!(
384+
self.tcx.def_path_str_with_substs(m.def_id, substs,)
385+
),
386+
match self.tcx.fn_sig(m.def_id).input(0).skip_binder().kind() {
387+
ty::Ref(_, _, hir::Mutability::Mut) => "&mut ",
388+
ty::Ref(_, _, _) => "&",
389+
_ => "",
390+
},
391+
),
392+
),
393+
match &args[..] {
394+
[] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()),
395+
[first, ..] => (base.span.between(first.span), ", ".to_string()),
396+
},
397+
]
398+
})
399+
.collect();
400+
if suggestions.is_empty() {
401+
return;
402+
}
403+
let mut path_span: MultiSpan = path.ident.span.into();
404+
path_span.push_span_label(
405+
path.ident.span,
406+
with_no_trimmed_paths!(format!(
407+
"refers to `{}`",
408+
self.tcx.def_path_str(pick.item.def_id),
409+
)),
410+
);
411+
let container_id = pick.item.container_id(self.tcx);
412+
let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
413+
for def_id in pick.import_ids {
414+
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
415+
path_span.push_span_label(
416+
self.tcx.hir().span(hir_id),
417+
format!("`{container}` imported here"),
418+
);
419+
}
420+
let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] {
421+
[] => return,
422+
[candidate] => format!(
423+
"the method of the same name on {} `{}`",
424+
match candidate.kind {
425+
probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
426+
_ => "trait",
427+
},
428+
self.tcx.def_path_str(candidate.item.container_id(self.tcx))
429+
),
430+
[.., last] if other_methods_in_scope.len() < 5 => {
431+
format!(
432+
"the methods of the same name on {} and `{}`",
433+
other_methods_in_scope[..other_methods_in_scope.len() - 1]
434+
.iter()
435+
.map(|c| format!(
436+
"`{}`",
437+
self.tcx.def_path_str(c.item.container_id(self.tcx))
438+
))
439+
.collect::<Vec<String>>()
440+
.join(", "),
441+
self.tcx.def_path_str(last.item.container_id(self.tcx))
442+
)
443+
}
444+
_ => format!(
445+
"the methods of the same name on {} other traits",
446+
other_methods_in_scope.len()
447+
),
448+
});
449+
err.span_note(
450+
path_span,
451+
&format!(
452+
"the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
453+
path.ident,
454+
),
455+
);
456+
if suggestions.len() > other_methods_in_scope.len() {
457+
err.note(&format!(
458+
"additionally, there are {} other available methods that aren't in scope",
459+
suggestions.len() - other_methods_in_scope.len()
460+
));
461+
}
462+
err.multipart_suggestions(
463+
&format!(
464+
"you might have meant to call {}; you can use the fully-qualified path to call {} \
465+
explicitly",
466+
if suggestions.len() == 1 {
467+
"the other method"
468+
} else {
469+
"one of the other methods"
470+
},
471+
if suggestions.len() == 1 { "it" } else { "one of them" },
472+
),
473+
suggestions,
474+
Applicability::MaybeIncorrect,
475+
);
476+
}
477+
319478
/// If the expected type is an enum (Issue #55250) with any variants whose
320479
/// sole field is of the found type, suggest such variants. (Issue #42764)
321480
fn suggest_compatible_variants(

compiler/rustc_hir_typeck/src/method/probe.rs

+35-5
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
9797
}
9898

9999
#[derive(Debug, Clone)]
100-
struct Candidate<'tcx> {
100+
pub(crate) struct Candidate<'tcx> {
101101
// Candidates are (I'm not quite sure, but they are mostly) basically
102102
// some metadata on top of a `ty::AssocItem` (without substs).
103103
//
@@ -131,13 +131,13 @@ struct Candidate<'tcx> {
131131
// if `T: Sized`.
132132
xform_self_ty: Ty<'tcx>,
133133
xform_ret_ty: Option<Ty<'tcx>>,
134-
item: ty::AssocItem,
135-
kind: CandidateKind<'tcx>,
136-
import_ids: SmallVec<[LocalDefId; 1]>,
134+
pub(crate) item: ty::AssocItem,
135+
pub(crate) kind: CandidateKind<'tcx>,
136+
pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
137137
}
138138

139139
#[derive(Debug, Clone)]
140-
enum CandidateKind<'tcx> {
140+
pub(crate) enum CandidateKind<'tcx> {
141141
InherentImplCandidate(
142142
SubstsRef<'tcx>,
143143
// Normalize obligations
@@ -322,6 +322,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
322322
)
323323
}
324324

325+
#[instrument(level = "debug", skip(self))]
326+
pub(crate) fn probe_for_name_many(
327+
&self,
328+
mode: Mode,
329+
item_name: Ident,
330+
is_suggestion: IsSuggestion,
331+
self_ty: Ty<'tcx>,
332+
scope_expr_id: hir::HirId,
333+
scope: ProbeScope,
334+
) -> Vec<Candidate<'tcx>> {
335+
self.probe_op(
336+
item_name.span,
337+
mode,
338+
Some(item_name),
339+
None,
340+
is_suggestion,
341+
self_ty,
342+
scope_expr_id,
343+
scope,
344+
|probe_cx| {
345+
Ok(probe_cx
346+
.inherent_candidates
347+
.into_iter()
348+
.chain(probe_cx.extension_candidates)
349+
.collect())
350+
},
351+
)
352+
.unwrap()
353+
}
354+
325355
fn probe_op<OP, R>(
326356
&'a self,
327357
span: Span,

compiler/rustc_lint/src/unused.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,7 @@ impl UnusedDelimLint for UnusedBraces {
11421142
&& !cx.sess().source_map().is_multiline(value.span)
11431143
&& value.attrs.is_empty()
11441144
&& !value.span.from_expansion()
1145+
&& !inner.span.from_expansion()
11451146
{
11461147
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
11471148
}

src/ci/run.sh

+1-9
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,6 @@ fi
4545
ci_dir=`cd $(dirname $0) && pwd`
4646
source "$ci_dir/shared.sh"
4747

48-
if command -v python > /dev/null; then
49-
PYTHON="python"
50-
elif command -v python3 > /dev/null; then
51-
PYTHON="python3"
52-
else
53-
PYTHON="python2"
54-
fi
55-
5648
if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
5749
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
5850
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
@@ -201,7 +193,7 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
201193
mv metrics.json build
202194
fi
203195

204-
CARGO_INCREMENTAL=0 $PYTHON ../x.py check
196+
CARGO_INCREMENTAL=0 ../x check
205197
fi
206198

207199
sccache --show-stats || true

src/librustdoc/html/static/css/themes/ayu.css

-4
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,7 @@ individually rather than as a group) */
183183
/* FIXME: these rules should be at the bottom of the file but currently must be
184184
above the `@media (max-width: 700px)` rules due to a bug in the css checker */
185185
/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
186-
pre.rust .lifetime {}
187-
pre.rust .kw {}
188186
#search-tabs > button:hover, #search-tabs > button.selected {}
189-
pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, pre.rust .attribute {}
190-
pre.rust .kw-2, pre.rust .prelude-ty {}
191187

192188
#settings-menu > a img {
193189
filter: invert(100);
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// build-pass
2+
pub fn foo<const BAR: bool> () {}
3+
4+
fn main() {
5+
foo::<{cfg!(feature = "foo")}>();
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![allow(unused)]
2+
3+
struct X {
4+
x: (),
5+
}
6+
pub trait A {
7+
fn foo(&mut self, _: usize) -> &mut ();
8+
}
9+
impl A for X {
10+
fn foo(&mut self, _: usize) -> &mut () {
11+
&mut self.x
12+
}
13+
}
14+
impl X {
15+
fn foo(&mut self, _: usize) -> &mut Self {
16+
self
17+
}
18+
}
19+
20+
fn main() {
21+
let mut x = X { x: () };
22+
*x.foo(0) = (); //~ ERROR E0308
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/shadowed-lplace-method-2.rs:22:17
3+
|
4+
LL | *x.foo(0) = ();
5+
| --------- ^^ expected struct `X`, found `()`
6+
| |
7+
| expected due to the type of this binding
8+
|
9+
note: the `foo` call is resolved to the method in `X`, shadowing the method of the same name on trait `A`
10+
--> $DIR/shadowed-lplace-method-2.rs:22:8
11+
|
12+
LL | *x.foo(0) = ();
13+
| ^^^ refers to `X::foo`
14+
help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
15+
|
16+
LL | *<_ as A>::foo(&mut x, 0) = ();
17+
| ++++++++++++++++++ ~
18+
help: try wrapping the expression in `X`
19+
|
20+
LL | *x.foo(0) = X { x: () };
21+
| ++++++ +
22+
23+
error: aborting due to previous error
24+
25+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// run-rustfix
2+
#![allow(unused_imports)]
3+
use std::borrow::BorrowMut;
4+
use std::cell::RefCell;
5+
use std::rc::Rc;
6+
7+
fn main() {
8+
let rc = Rc::new(RefCell::new(true));
9+
*std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308
10+
}

0 commit comments

Comments
 (0)