]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #106174 - GuillaumeGomez:rm-unused-ayu-css-rules, r=notriddle
authorMatthias Krüger <matthias.krueger@famsik.de>
Tue, 27 Dec 2022 07:57:48 +0000 (08:57 +0100)
committerGitHub <noreply@github.com>
Tue, 27 Dec 2022 07:57:48 +0000 (08:57 +0100)
Remove unused empty CSS rules in ayu theme

r? `@notriddle`

13 files changed:
README.md
compiler/rustc_hir_typeck/src/demand.rs
compiler/rustc_hir_typeck/src/method/probe.rs
compiler/rustc_lint/src/unused.rs
src/bootstrap/flags.rs
src/bootstrap/lib.rs
src/ci/run.sh
src/test/ui/lint/unused_braces_macro.rs [new file with mode: 0644]
src/test/ui/suggestions/shadowed-lplace-method-2.rs [new file with mode: 0644]
src/test/ui/suggestions/shadowed-lplace-method-2.stderr [new file with mode: 0644]
src/test/ui/suggestions/shadowed-lplace-method.fixed [new file with mode: 0644]
src/test/ui/suggestions/shadowed-lplace-method.rs [new file with mode: 0644]
src/test/ui/suggestions/shadowed-lplace-method.stderr [new file with mode: 0644]

index 2b7edf2c3c90758a298267b15228246dc280fab0..ac39435a8c7fb9338a0f278452e2d8ff8afa525d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -20,22 +20,23 @@ Read ["Installation"] from [The Book].
 The Rust build system uses a Python script called `x.py` to build the compiler,
 which manages the bootstrapping process. It lives at the root of the project.
 
-The `x.py` command can be run directly on most systems in the following format:
+The `x.py` command can be run directly on most Unix systems in the following format:
 
 ```sh
 ./x.py <subcommand> [flags]
 ```
 
-This is how the documentation and examples assume you are running `x.py`.
-
-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:
+This is how the documentation and examples assume you are running `x.py`. Some alternative ways are:
 
 ```sh
-# Python 3
-python3 x.py <subcommand> [flags]
+# On a Unix shell if you don't have the necessary `python3` command
+./x <subcommand> [flags]
+
+# On the Windows Command Prompt (if .py files are configured to run Python)
+x.py <subcommand> [flags]
 
-# Python 2.7
-python2.7 x.py <subcommand> [flags]
+# You can also run Python yourself, e.g.:
+python x.py <subcommand> [flags]
 ```
 
 More information about `x.py` can be found
index 042ff0b46a5afbc6bd31205d2600a732d9c002c0..0335c45a946d55322d9fa2f52521a499442fe241 100644 (file)
@@ -1,5 +1,6 @@
 use crate::FnCtxt;
 use rustc_ast::util::parser::PREC_POSTFIX;
+use rustc_errors::MultiSpan;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -30,12 +31,14 @@ pub fn emit_type_mismatch_suggestions(
         expr_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
-        _error: Option<TypeError<'tcx>>,
+        error: Option<TypeError<'tcx>>,
     ) {
         if expr_ty == expected {
             return;
         }
 
+        self.annotate_alternative_method_deref(err, expr, error);
+
         // Use `||` to give these suggestions a precedence
         let _ = self.suggest_missing_parentheses(err, expr)
             || self.suggest_remove_last_method_call(err, expr, expected)
@@ -316,6 +319,162 @@ fn annotate_expected_due_to_let_ty(
         }
     }
 
+    fn annotate_alternative_method_deref(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        error: Option<TypeError<'tcx>>,
+    ) {
+        let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;};
+        let Some(hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Assign(lhs, rhs, _), ..
+                })) = self.tcx.hir().find(parent) else {return; };
+        if rhs.hir_id != expr.hir_id || expected.is_closure() {
+            return;
+        }
+        let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; };
+        let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; };
+        let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; };
+
+        let Ok(pick) = self
+            .probe_for_name(
+                probe::Mode::MethodCall,
+                path.ident,
+                probe::IsSuggestion(true),
+                self_ty,
+                deref.hir_id,
+                probe::ProbeScope::TraitsInScope,
+            ) else {
+                return;
+            };
+        let in_scope_methods = self.probe_for_name_many(
+            probe::Mode::MethodCall,
+            path.ident,
+            probe::IsSuggestion(true),
+            self_ty,
+            deref.hir_id,
+            probe::ProbeScope::TraitsInScope,
+        );
+        let other_methods_in_scope: Vec<_> =
+            in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
+
+        let all_methods = self.probe_for_name_many(
+            probe::Mode::MethodCall,
+            path.ident,
+            probe::IsSuggestion(true),
+            self_ty,
+            deref.hir_id,
+            probe::ProbeScope::AllTraits,
+        );
+        let suggestions: Vec<_> = all_methods
+            .into_iter()
+            .filter(|c| c.item.def_id != pick.item.def_id)
+            .map(|c| {
+                let m = c.item;
+                let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| {
+                    self.var_for_def(deref.span, param)
+                });
+                vec![
+                    (
+                        deref.span.until(base.span),
+                        format!(
+                            "{}({}",
+                            with_no_trimmed_paths!(
+                                self.tcx.def_path_str_with_substs(m.def_id, substs,)
+                            ),
+                            match self.tcx.fn_sig(m.def_id).input(0).skip_binder().kind() {
+                                ty::Ref(_, _, hir::Mutability::Mut) => "&mut ",
+                                ty::Ref(_, _, _) => "&",
+                                _ => "",
+                            },
+                        ),
+                    ),
+                    match &args[..] {
+                        [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()),
+                        [first, ..] => (base.span.between(first.span), ", ".to_string()),
+                    },
+                ]
+            })
+            .collect();
+        if suggestions.is_empty() {
+            return;
+        }
+        let mut path_span: MultiSpan = path.ident.span.into();
+        path_span.push_span_label(
+            path.ident.span,
+            with_no_trimmed_paths!(format!(
+                "refers to `{}`",
+                self.tcx.def_path_str(pick.item.def_id),
+            )),
+        );
+        let container_id = pick.item.container_id(self.tcx);
+        let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
+        for def_id in pick.import_ids {
+            let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+            path_span.push_span_label(
+                self.tcx.hir().span(hir_id),
+                format!("`{container}` imported here"),
+            );
+        }
+        let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] {
+            [] => return,
+            [candidate] => format!(
+                "the method of the same name on {} `{}`",
+                match candidate.kind {
+                    probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
+                    _ => "trait",
+                },
+                self.tcx.def_path_str(candidate.item.container_id(self.tcx))
+            ),
+            [.., last] if other_methods_in_scope.len() < 5 => {
+                format!(
+                    "the methods of the same name on {} and `{}`",
+                    other_methods_in_scope[..other_methods_in_scope.len() - 1]
+                        .iter()
+                        .map(|c| format!(
+                            "`{}`",
+                            self.tcx.def_path_str(c.item.container_id(self.tcx))
+                        ))
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    self.tcx.def_path_str(last.item.container_id(self.tcx))
+                )
+            }
+            _ => format!(
+                "the methods of the same name on {} other traits",
+                other_methods_in_scope.len()
+            ),
+        });
+        err.span_note(
+            path_span,
+            &format!(
+                "the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
+                path.ident,
+            ),
+        );
+        if suggestions.len() > other_methods_in_scope.len() {
+            err.note(&format!(
+                "additionally, there are {} other available methods that aren't in scope",
+                suggestions.len() - other_methods_in_scope.len()
+            ));
+        }
+        err.multipart_suggestions(
+            &format!(
+                "you might have meant to call {}; you can use the fully-qualified path to call {} \
+                 explicitly",
+                if suggestions.len() == 1 {
+                    "the other method"
+                } else {
+                    "one of the other methods"
+                },
+                if suggestions.len() == 1 { "it" } else { "one of them" },
+            ),
+            suggestions,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     fn suggest_compatible_variants(
index b9e7830bf079214af2a29491fff1ab458fbee011..6b3fa664d9c5a9d0badbe66b9445dd9d737dfac9 100644 (file)
@@ -97,7 +97,7 @@ fn deref(&self) -> &Self::Target {
 }
 
 #[derive(Debug, Clone)]
-struct Candidate<'tcx> {
+pub(crate) struct Candidate<'tcx> {
     // Candidates are (I'm not quite sure, but they are mostly) basically
     // some metadata on top of a `ty::AssocItem` (without substs).
     //
@@ -131,13 +131,13 @@ struct Candidate<'tcx> {
     // if `T: Sized`.
     xform_self_ty: Ty<'tcx>,
     xform_ret_ty: Option<Ty<'tcx>>,
-    item: ty::AssocItem,
-    kind: CandidateKind<'tcx>,
-    import_ids: SmallVec<[LocalDefId; 1]>,
+    pub(crate) item: ty::AssocItem,
+    pub(crate) kind: CandidateKind<'tcx>,
+    pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
 }
 
 #[derive(Debug, Clone)]
-enum CandidateKind<'tcx> {
+pub(crate) enum CandidateKind<'tcx> {
     InherentImplCandidate(
         SubstsRef<'tcx>,
         // Normalize obligations
@@ -322,6 +322,36 @@ pub fn probe_for_name(
         )
     }
 
+    #[instrument(level = "debug", skip(self))]
+    pub(crate) fn probe_for_name_many(
+        &self,
+        mode: Mode,
+        item_name: Ident,
+        is_suggestion: IsSuggestion,
+        self_ty: Ty<'tcx>,
+        scope_expr_id: hir::HirId,
+        scope: ProbeScope,
+    ) -> Vec<Candidate<'tcx>> {
+        self.probe_op(
+            item_name.span,
+            mode,
+            Some(item_name),
+            None,
+            is_suggestion,
+            self_ty,
+            scope_expr_id,
+            scope,
+            |probe_cx| {
+                Ok(probe_cx
+                    .inherent_candidates
+                    .into_iter()
+                    .chain(probe_cx.extension_candidates)
+                    .collect())
+            },
+        )
+        .unwrap()
+    }
+
     fn probe_op<OP, R>(
         &'a self,
         span: Span,
index 3b8df61a0eab771a704f9ed9006bbd1807b612fa..a7a5234049fe63db04d6789e5a509238dd4346ae 100644 (file)
@@ -1142,6 +1142,7 @@ fn check_unused_delims_expr(
                             && !cx.sess().source_map().is_multiline(value.span)
                             && value.attrs.is_empty()
                             && !value.span.from_expansion()
+                            && !inner.span.from_expansion()
                         {
                             self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
                         }
index 851cb5ecf4c2694ee7c77b7b97e4bd92a1c7d6a4..de39868d692d47a3498f5dc28190fdf961f3a6b0 100644 (file)
@@ -351,7 +351,17 @@ pub fn parse(args: &[String]) -> Flags {
 
         // fn usage()
         let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
-            let config = Config::parse(&["setup".to_string()]);
+            // We have an unfortunate situation here: some Steps use `builder.in_tree_crates` to determine their paths.
+            // To determine those crates, we need to run `cargo metadata`, which means we need all submodules to be checked out.
+            // That takes a while to run, so only do it when paths were explicitly requested, not on all CLI errors.
+            // `Build::new` won't load submodules for the `setup` command.
+            let cmd = if verbose {
+                println!("note: updating submodules before printing available paths");
+                "build"
+            } else {
+                "setup"
+            };
+            let config = Config::parse(&[cmd.to_string()]);
             let build = Build::new(config);
             let paths = Builder::get_help(&build, subcommand);
 
index f84fcd21cfcfeacb7be2938ed3e5239377822a48..ced1e397807e42f77e2b24d18195e046c3375b16 100644 (file)
@@ -1400,7 +1400,10 @@ fn in_tree_crates(&self, root: &str, target: Option<TargetSelection>) -> Vec<&Cr
         let mut list = vec![INTERNER.intern_str(root)];
         let mut visited = HashSet::new();
         while let Some(krate) = list.pop() {
-            let krate = &self.crates[&krate];
+            let krate = self
+                .crates
+                .get(&krate)
+                .unwrap_or_else(|| panic!("metadata missing for {krate}: {:?}", self.crates));
             ret.push(krate);
             for dep in &krate.deps {
                 if !self.crates.contains_key(dep) {
index f05bb81d4a1e3b31ba260b357e237911979d8f17..b64300277508dd15af81644f540beca9ccafbcfb 100755 (executable)
@@ -45,14 +45,6 @@ fi
 ci_dir=`cd $(dirname $0) && pwd`
 source "$ci_dir/shared.sh"
 
-if command -v python > /dev/null; then
-    PYTHON="python"
-elif command -v python3 > /dev/null; then
-    PYTHON="python3"
-else
-    PYTHON="python2"
-fi
-
 if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
@@ -201,7 +193,7 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
     mv metrics.json build
   fi
 
-  CARGO_INCREMENTAL=0 $PYTHON ../x.py check
+  CARGO_INCREMENTAL=0 ../x check
 fi
 
 sccache --show-stats || true
diff --git a/src/test/ui/lint/unused_braces_macro.rs b/src/test/ui/lint/unused_braces_macro.rs
new file mode 100644 (file)
index 0000000..bfee953
--- /dev/null
@@ -0,0 +1,6 @@
+// build-pass
+pub fn foo<const BAR: bool> () {}
+
+fn main() {
+    foo::<{cfg!(feature = "foo")}>();
+}
diff --git a/src/test/ui/suggestions/shadowed-lplace-method-2.rs b/src/test/ui/suggestions/shadowed-lplace-method-2.rs
new file mode 100644 (file)
index 0000000..dab99fb
--- /dev/null
@@ -0,0 +1,23 @@
+#![allow(unused)]
+
+struct X {
+    x: (),
+}
+pub trait A {
+    fn foo(&mut self, _: usize) -> &mut ();
+}
+impl A for X {
+    fn foo(&mut self, _: usize) -> &mut () {
+        &mut self.x
+    }
+}
+impl X {
+    fn foo(&mut self, _: usize) -> &mut Self {
+        self
+    }
+}
+
+fn main() {
+    let mut x = X { x: () };
+    *x.foo(0) = (); //~ ERROR E0308
+}
diff --git a/src/test/ui/suggestions/shadowed-lplace-method-2.stderr b/src/test/ui/suggestions/shadowed-lplace-method-2.stderr
new file mode 100644 (file)
index 0000000..94eef15
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/shadowed-lplace-method-2.rs:22:17
+   |
+LL |     *x.foo(0) = ();
+   |     ---------   ^^ expected struct `X`, found `()`
+   |     |
+   |     expected due to the type of this binding
+   |
+note: the `foo` call is resolved to the method in `X`, shadowing the method of the same name on trait `A`
+  --> $DIR/shadowed-lplace-method-2.rs:22:8
+   |
+LL |     *x.foo(0) = ();
+   |        ^^^ refers to `X::foo`
+help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
+   |
+LL |     *<_ as A>::foo(&mut x, 0) = ();
+   |      ++++++++++++++++++  ~
+help: try wrapping the expression in `X`
+   |
+LL |     *x.foo(0) = X { x: () };
+   |                 ++++++    +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/shadowed-lplace-method.fixed b/src/test/ui/suggestions/shadowed-lplace-method.fixed
new file mode 100644 (file)
index 0000000..740ac77
--- /dev/null
@@ -0,0 +1,10 @@
+// run-rustfix
+#![allow(unused_imports)]
+use std::borrow::BorrowMut;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+fn main() {
+    let rc = Rc::new(RefCell::new(true));
+    *std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308
+}
diff --git a/src/test/ui/suggestions/shadowed-lplace-method.rs b/src/test/ui/suggestions/shadowed-lplace-method.rs
new file mode 100644 (file)
index 0000000..6bf1287
--- /dev/null
@@ -0,0 +1,10 @@
+// run-rustfix
+#![allow(unused_imports)]
+use std::borrow::BorrowMut;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+fn main() {
+    let rc = Rc::new(RefCell::new(true));
+    *rc.borrow_mut() = false; //~ ERROR E0308
+}
diff --git a/src/test/ui/suggestions/shadowed-lplace-method.stderr b/src/test/ui/suggestions/shadowed-lplace-method.stderr
new file mode 100644 (file)
index 0000000..91d0d12
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+  --> $DIR/shadowed-lplace-method.rs:9:24
+   |
+LL |     *rc.borrow_mut() = false;
+   |     ----------------   ^^^^^ expected struct `Rc`, found `bool`
+   |     |
+   |     expected due to the type of this binding
+   |
+   = note: expected struct `Rc<RefCell<bool>>`
+                found type `bool`
+note: the `borrow_mut` call is resolved to the method in `std::borrow::BorrowMut`, shadowing the method of the same name on the inherent impl for `std::cell::RefCell<T>`
+  --> $DIR/shadowed-lplace-method.rs:9:9
+   |
+LL | use std::borrow::BorrowMut;
+   |     ---------------------- `std::borrow::BorrowMut` imported here
+...
+LL |     *rc.borrow_mut() = false;
+   |         ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut`
+help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
+   |
+LL |     *std::cell::RefCell::<_>::borrow_mut(&rc) = false;
+   |      +++++++++++++++++++++++++++++++++++++  ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.