diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 9f670893b27..35ee0c53046 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -651,9 +651,11 @@ trait UnusedDelimLint { fn is_expr_delims_necessary( inner: &ast::Expr, + ctx: UnusedDelimsCtx, followed_by_block: bool, - followed_by_else: bool, ) -> bool { + let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse; + if followed_by_else { match inner.kind { ast::ExprKind::Binary(op, ..) if op.node.is_lazy() => return true, @@ -662,6 +664,13 @@ trait UnusedDelimLint { } } + // Check it's range in LetScrutineeExpr + if let ast::ExprKind::Range(..) = inner.kind + && matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr) + { + return true; + } + // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`. { let mut innermost = inner; @@ -1007,8 +1016,7 @@ impl UnusedDelimLint for UnusedParens { ) { match value.kind { ast::ExprKind::Paren(ref inner) => { - let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse; - if !Self::is_expr_delims_necessary(inner, followed_by_block, followed_by_else) + if !Self::is_expr_delims_necessary(inner, ctx, followed_by_block) && value.attrs.is_empty() && !value.span.from_expansion() && (ctx != UnusedDelimsCtx::LetScrutineeExpr @@ -1334,7 +1342,7 @@ impl UnusedDelimLint for UnusedBraces { // FIXME(const_generics): handle paths when #67075 is fixed. if let [stmt] = inner.stmts.as_slice() { if let ast::StmtKind::Expr(ref expr) = stmt.kind { - if !Self::is_expr_delims_necessary(expr, followed_by_block, false) + if !Self::is_expr_delims_necessary(expr, ctx, followed_by_block) && (ctx != UnusedDelimsCtx::AnonConst || (matches!(expr.kind, ast::ExprKind::Lit(_)) && !expr.span.from_expansion())) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 61e449b8b56..7033a4a833d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1053,12 +1053,6 @@ impl<'tcx> TyCtxtAt<'tcx> { name: Symbol, def_kind: DefKind, ) -> TyCtxtFeed<'tcx, LocalDefId> { - // This function modifies `self.definitions` using a side-effect. - // We need to ensure that these side effects are re-run by the incr. comp. engine. - // Depending on the forever-red node will tell the graph that the calling query - // needs to be re-evaluated. - self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); - // The following call has the side effect of modifying the tables inside `definitions`. // These very tables are relied on by the incr. comp. engine to decode DepNodes and to // decode the on-disk cache. @@ -1087,6 +1081,12 @@ impl<'tcx> TyCtxt<'tcx> { let data = def_kind.def_path_data(name); let def_id = self.untracked.definitions.write().create_def(parent, data); + // This function modifies `self.definitions` using a side-effect. + // We need to ensure that these side effects are re-run by the incr. comp. engine. + // Depending on the forever-red node will tell the graph that the calling query + // needs to be re-evaluated. + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + let feed = self.feed_local_def_id(def_id); feed.def_kind(def_kind); // Unique types created for closures participate in type privacy checking. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ae6544b9dbe..66086ac87f1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2373,6 +2373,20 @@ impl<'tcx> Ty<'tcx> { /// to represent the closure kind, because it has not yet been /// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`) /// is complete, that type variable will be unified. + /// + /// To be noted that you can use [`ClosureArgs::kind()`] or [`CoroutineClosureArgs::kind()`] + /// to get the same information, which you can get by calling [`GenericArgs::as_closure()`] + /// or [`GenericArgs::as_coroutine_closure()`], depending on the type of the closure. + /// + /// Otherwise, this method can be used as follows: + /// + /// ```rust,ignore (snippet of compiler code) + /// let TyKind::Closure(def_id, [closure_fn_kind_ty, ..]) = closure_ty.kind() + /// && let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() + /// { + /// // your code + /// } + /// ``` pub fn to_opt_closure_kind(self) -> Option { match self.kind() { Int(int_ty) => match int_ty { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 5d712461993..cb3b95a4434 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -460,7 +460,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { return (err, Vec::new()); } - let (found, candidates) = self.try_lookup_name_relaxed( + let (found, mut candidates) = self.try_lookup_name_relaxed( &mut err, source, path, @@ -473,10 +473,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { return (err, candidates); } - let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); + if self.suggest_shadowed(&mut err, source, path, following_seg, span) { + // if there is already a shadowed name, don'suggest candidates for importing + candidates.clear(); + } - // if we have suggested using pattern matching, then don't add needless suggestions - // for typos. + let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error); if fallback { @@ -872,25 +874,6 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let ident_span = path.last().map_or(span, |ident| ident.ident.span); let typo_sugg = self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); - let is_in_same_file = &|sp1, sp2| { - let source_map = self.r.tcx.sess.source_map(); - let file1 = source_map.span_to_filename(sp1); - let file2 = source_map.span_to_filename(sp2); - file1 == file2 - }; - // print 'you might have meant' if the candidate is (1) is a shadowed name with - // accessible definition and (2) either defined in the same crate as the typo - // (could be in a different file) or introduced in the same file as the typo - // (could belong to a different crate) - if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg - && res.opt_def_id().is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span)) - { - err.span_label( - sugg_span, - format!("you might have meant to refer to this {}", res.descr()), - ); - return true; - } let mut fallback = false; let typo_sugg = typo_sugg.to_opt_suggestion(); if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { @@ -918,6 +901,39 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fallback } + fn suggest_shadowed( + &mut self, + err: &mut Diagnostic, + source: PathSource<'_>, + path: &[Segment], + following_seg: Option<&Segment>, + span: Span, + ) -> bool { + let is_expected = &|res| source.is_expected(res); + let typo_sugg = + self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); + let is_in_same_file = &|sp1, sp2| { + let source_map = self.r.tcx.sess.source_map(); + let file1 = source_map.span_to_filename(sp1); + let file2 = source_map.span_to_filename(sp2); + file1 == file2 + }; + // print 'you might have meant' if the candidate is (1) is a shadowed name with + // accessible definition and (2) either defined in the same crate as the typo + // (could be in a different file) or introduced in the same file as the typo + // (could belong to a different crate) + if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg + && res.opt_def_id().is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span)) + { + err.span_label( + sugg_span, + format!("you might have meant to refer to this {}", res.descr()), + ); + return true; + } + false + } + fn err_code_special_cases( &mut self, err: &mut Diagnostic, diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index aaef80f4aef..4cd8e6a703e 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -537,18 +537,29 @@ impl Rewrite for ast::Lifetime { impl Rewrite for ast::GenericBound { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { - ast::GenericBound::Trait(ref poly_trait_ref, modifiers) => { + ast::GenericBound::Trait( + ref poly_trait_ref, + ast::TraitBoundModifiers { + constness, + asyncness, + polarity, + }, + ) => { let snippet = context.snippet(self.span()); let has_paren = snippet.starts_with('(') && snippet.ends_with(')'); - let mut constness = modifiers.constness.as_str().to_string(); + let mut constness = constness.as_str().to_string(); if !constness.is_empty() { constness.push(' '); } - let polarity = modifiers.polarity.as_str(); + let mut asyncness = asyncness.as_str().to_string(); + if !asyncness.is_empty() { + asyncness.push(' '); + } + let polarity = polarity.as_str(); let shape = shape.offset_left(constness.len() + polarity.len())?; poly_trait_ref .rewrite(context, shape) - .map(|s| format!("{constness}{polarity}{s}")) + .map(|s| format!("{constness}{asyncness}{polarity}{s}")) .map(|s| if has_paren { format!("({})", s) } else { s }) } ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape), diff --git a/src/tools/rustfmt/tests/target/asyncness.rs b/src/tools/rustfmt/tests/target/asyncness.rs new file mode 100644 index 00000000000..d91ac960499 --- /dev/null +++ b/src/tools/rustfmt/tests/target/asyncness.rs @@ -0,0 +1,3 @@ +// rustfmt-edition: 2018 + +fn foo() -> impl async Fn() {} diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 03f8a701627..1dbd221fde5 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -14,7 +14,7 @@ use std::path::{Path, PathBuf}; // #73494. const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1794; +const ISSUES_ENTRY_LIMIT: usize = 1781; const ROOT_ENTRY_LIMIT: usize = 870; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/tests/ui/issues/issue-10682.rs b/tests/ui/closures/issue-10682.rs similarity index 100% rename from tests/ui/issues/issue-10682.rs rename to tests/ui/closures/issue-10682.rs diff --git a/tests/ui/issues/issue-44255.rs b/tests/ui/consts/issue-44255.rs similarity index 100% rename from tests/ui/issues/issue-44255.rs rename to tests/ui/consts/issue-44255.rs diff --git a/tests/ui/issues/issue-18576.rs b/tests/ui/extern/issue-18576.rs similarity index 100% rename from tests/ui/issues/issue-18576.rs rename to tests/ui/extern/issue-18576.rs diff --git a/tests/ui/issues/issue-18819.rs b/tests/ui/extern/issue-18819.rs similarity index 100% rename from tests/ui/issues/issue-18819.rs rename to tests/ui/extern/issue-18819.rs diff --git a/tests/ui/issues/issue-18819.stderr b/tests/ui/extern/issue-18819.stderr similarity index 100% rename from tests/ui/issues/issue-18819.stderr rename to tests/ui/extern/issue-18819.stderr diff --git a/tests/ui/issues/issue-23781.rs b/tests/ui/fmt/issue-23781.rs similarity index 100% rename from tests/ui/issues/issue-23781.rs rename to tests/ui/fmt/issue-23781.rs diff --git a/tests/ui/issues/issue-29746.rs b/tests/ui/hygiene/issue-29746.rs similarity index 100% rename from tests/ui/issues/issue-29746.rs rename to tests/ui/hygiene/issue-29746.rs diff --git a/tests/ui/issues/issue-12028.rs b/tests/ui/inference/issue-12028.rs similarity index 100% rename from tests/ui/issues/issue-12028.rs rename to tests/ui/inference/issue-12028.rs diff --git a/tests/ui/issues/issue-12028.stderr b/tests/ui/inference/issue-12028.stderr similarity index 100% rename from tests/ui/issues/issue-12028.stderr rename to tests/ui/inference/issue-12028.stderr diff --git a/tests/ui/issues/issue-19707.rs b/tests/ui/lifetimes/issue-19707.rs similarity index 100% rename from tests/ui/issues/issue-19707.rs rename to tests/ui/lifetimes/issue-19707.rs diff --git a/tests/ui/issues/issue-19707.stderr b/tests/ui/lifetimes/issue-19707.stderr similarity index 100% rename from tests/ui/issues/issue-19707.stderr rename to tests/ui/lifetimes/issue-19707.stderr diff --git a/tests/ui/lint/issue-121070-let-range.rs b/tests/ui/lint/issue-121070-let-range.rs new file mode 100644 index 00000000000..84598dcd258 --- /dev/null +++ b/tests/ui/lint/issue-121070-let-range.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(let_chains)] +#![allow(irrefutable_let_patterns)] +fn main() { + let _a = 0..1; + + if let x = (0..1) { + eprintln!("x: {:?}", x); + } + if let x = (0..1) && + let _y = (0..2) + { + eprintln!("x: {:?}", x); + } +} diff --git a/tests/ui/issues/issue-19102.rs b/tests/ui/lint/issue-19102.rs similarity index 100% rename from tests/ui/issues/issue-19102.rs rename to tests/ui/lint/issue-19102.rs diff --git a/tests/ui/resolve/issue-120559.rs b/tests/ui/resolve/issue-120559.rs new file mode 100644 index 00000000000..e874e840de7 --- /dev/null +++ b/tests/ui/resolve/issue-120559.rs @@ -0,0 +1,5 @@ +use std::io::Read; + +fn f() {} //~ ERROR expected trait, found type parameter `Read` + +fn main() {} diff --git a/tests/ui/resolve/issue-120559.stderr b/tests/ui/resolve/issue-120559.stderr new file mode 100644 index 00000000000..9150fb38ad5 --- /dev/null +++ b/tests/ui/resolve/issue-120559.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found type parameter `Read` + --> $DIR/issue-120559.rs:3:9 + | +LL | use std::io::Read; + | ---- you might have meant to refer to this trait +LL | +LL | fn f() {} + | ^^^^ ---- found this type parameter + | | + | not a trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr index 4c4b100da3d..d3014f276fd 100644 --- a/tests/ui/span/issue-35987.stderr +++ b/tests/ui/span/issue-35987.stderr @@ -8,11 +8,6 @@ LL | impl Add for Foo { | --- ^^^ not a trait | | | found this type parameter - | -help: consider importing this trait instead - | -LL + use std::ops::Add; - | error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-5008-borrowed-traitobject-method-call.rs b/tests/ui/traits/issue-5008-borrowed-traitobject-method-call.rs similarity index 100% rename from tests/ui/issues/issue-5008-borrowed-traitobject-method-call.rs rename to tests/ui/traits/issue-5008-borrowed-traitobject-method-call.rs