From 2bf56b9aa7f92f665c40ddbe8259417de84bb142 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 26 Feb 2022 11:32:07 +0100 Subject: [PATCH 1/8] Document that pre-expansion lint passes are deprecated --- compiler/rustc_lint/src/context.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 0582a4e01bfeb..ad9a16fb39ae2 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -166,7 +166,12 @@ impl LintStore { self.early_passes.push(Box::new(pass)); } - /// Used by clippy. + /// This lint pass is softly deprecated. It misses expanded code and has caused a few + /// errors in the past. Currently, it is only used in Clippy. New implementations + /// should avoid using this interface, as it might be removed in the future. + /// + /// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838) + /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518) pub fn register_pre_expansion_pass( &mut self, pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync, From ca2ad69143eff606f051aed98422d98a8d4e43d8 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 26 Feb 2022 07:43:47 -0300 Subject: [PATCH 2/8] Make more use of `let_chains` --- compiler/rustc_typeck/src/astconv/mod.rs | 11 ++- compiler/rustc_typeck/src/check/check.rs | 39 ++++----- compiler/rustc_typeck/src/check/coercion.rs | 11 ++- compiler/rustc_typeck/src/check/demand.rs | 19 ++--- compiler/rustc_typeck/src/check/expr.rs | 6 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 34 ++++---- .../rustc_typeck/src/check/method/suggest.rs | 82 +++++++++---------- compiler/rustc_typeck/src/check/pat.rs | 9 +- compiler/rustc_typeck/src/collect.rs | 69 ++++++++-------- compiler/rustc_typeck/src/lib.rs | 13 +-- .../src/outlives/implicit_infer.rs | 13 ++- 11 files changed, 142 insertions(+), 164 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 4a310e2be3e3c..14a6e686a6424 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1054,12 +1054,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut result = Vec::new(); for ast_bound in ast_bounds { - if let Some(trait_ref) = ast_bound.trait_ref() { - if let Some(trait_did) = trait_ref.trait_def_id() { - if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) { - result.push(ast_bound.clone()); - } - } + if let Some(trait_ref) = ast_bound.trait_ref() + && let Some(trait_did) = trait_ref.trait_def_id() + && self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) + { + result.push(ast_bound.clone()); } } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 8ed87497f1b32..100d2d07a5c9f 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -282,13 +282,12 @@ pub(super) fn check_fn<'a, 'tcx>( sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); } - if let Node::Item(item) = hir.get(fn_id) { - if let ItemKind::Fn(_, ref generics, _) = item.kind { - if !generics.params.is_empty() { + if let Node::Item(item) = hir.get(fn_id) + && let ItemKind::Fn(_, ref generics, _) = item.kind + && !generics.params.is_empty() + { sess.span_err(span, "should have no type parameters"); } - } - } } else { let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); @@ -319,17 +318,15 @@ pub(super) fn check_fn<'a, 'tcx>( sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); } - if let Node::Item(item) = hir.get(fn_id) { - if let ItemKind::Fn(_, ref generics, _) = item.kind { - if !generics.params.is_empty() { + if let Node::Item(item) = hir.get(fn_id) + && let ItemKind::Fn(_, ref generics, _) = item.kind + && !generics.params.is_empty() + { sess.span_err( span, - "`#[alloc_error_handler]` function should have no type \ - parameters", + "`#[alloc_error_handler]` function should have no type parameters", ); } - } - } } else { let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); @@ -1146,9 +1143,10 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) { if repr.packed() { for attr in tcx.get_attrs(def.did).iter() { for r in attr::find_repr_attrs(&tcx.sess, attr) { - if let attr::ReprPacked(pack) = r { - if let Some(repr_pack) = repr.pack { - if pack as u64 != repr_pack.bytes() { + if let attr::ReprPacked(pack) = r + && let Some(repr_pack) = repr.pack + && pack as u64 != repr_pack.bytes() + { struct_span_err!( tcx.sess, sp, @@ -1156,8 +1154,6 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) { "type has conflicting packed representation hints" ) .emit(); - } - } } } } @@ -1399,12 +1395,11 @@ fn display_discriminant_value<'tcx>( ) -> String { if let Some(expr) = &variant.disr_expr { let body = &tcx.hir().body(expr.body).value; - if let hir::ExprKind::Lit(lit) = &body.kind { - if let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node { - if evaluated != *lit_value { + if let hir::ExprKind::Lit(lit) = &body.kind + && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node + && evaluated != *lit_value + { return format!("`{}` (overflowed from `{}`)", evaluated, lit_value); - } - } } } format!("`{}`", evaluated) diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 8ca27b010b6af..c6b14d3e10458 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1696,13 +1696,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { - if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) { - if let hir::FnRetTy::Return(ty) = fn_decl.output { - let ty = >::ast_ty_to_ty(fcx, ty); - if let ty::Dynamic(..) = ty.kind() { + if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) + && let hir::FnRetTy::Return(ty) = fn_decl.output + && let ty = >::ast_ty_to_ty(fcx, ty) + && let ty::Dynamic(..) = ty.kind() + { return true; - } - } } false } diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 80096b90f9530..faead1bf5cd6d 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -587,9 +587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match (&expr.kind, expected.kind(), checked_ty.kind()) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (exp.kind(), check.kind()) { (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => { - if let hir::ExprKind::Lit(_) = expr.kind { - if let Ok(src) = sm.span_to_snippet(sp) { - if replace_prefix(&src, "b\"", "\"").is_some() { + if let hir::ExprKind::Lit(_) = expr.kind + && let Ok(src) = sm.span_to_snippet(sp) + && replace_prefix(&src, "b\"", "\"").is_some() + { let pos = sp.lo() + BytePos(1); return Some(( sp.with_hi(pos), @@ -600,12 +601,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } } - } - } (&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => { - if let hir::ExprKind::Lit(_) = expr.kind { - if let Ok(src) = sm.span_to_snippet(sp) { - if replace_prefix(&src, "\"", "b\"").is_some() { + if let hir::ExprKind::Lit(_) = expr.kind + && let Ok(src) = sm.span_to_snippet(sp) + && replace_prefix(&src, "\"", "b\"").is_some() + { return Some(( sp.shrink_to_lo(), "consider adding a leading `b`", @@ -613,8 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, true, )); - } - } + } } _ => {} diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 8d4ffefda73bb..14a1318517a19 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -810,10 +810,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Use the span of the trailing expression for our cause, // not the span of the entire function if !explicit_return { - if let ExprKind::Block(body, _) = return_expr.kind { - if let Some(last_expr) = body.expr { - span = last_expr.span; - } + if let ExprKind::Block(body, _) = return_expr.kind && let Some(last_expr) = body.expr { + span = last_expr.span; } } ret_coercion.borrow_mut().coerce( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 4b6460b62b77a..76339998a2fbb 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -402,25 +402,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if arg_count == 0 || i + 1 == arg_count { &label } else { "" }, ); } - if let Some(def_id) = fn_def_id { - if let Some(def_span) = tcx.def_ident_span(def_id) { - let mut spans: MultiSpan = def_span.into(); - - let params = tcx - .hir() - .get_if_local(def_id) - .and_then(|node| node.body_id()) - .into_iter() - .map(|id| tcx.hir().body(id).params) - .flatten(); - - for param in params { - spans.push_span_label(param.span, String::new()); - } - - let def_kind = tcx.def_kind(def_id); - err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id))); + if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) { + let mut spans: MultiSpan = def_span.into(); + + let params = tcx + .hir() + .get_if_local(def_id) + .and_then(|node| node.body_id()) + .into_iter() + .map(|id| tcx.hir().body(id).params) + .flatten(); + + for param in params { + spans.push_span_label(param.span, String::new()); } + + let def_kind = tcx.def_kind(def_id); + err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id))); } if sugg_unit { let sugg_span = tcx.sess.source_map().end_point(call_expr.span); diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index ccaea10233dc1..32de5d23c1ea7 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -430,12 +430,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { actual.prefix_string(self.tcx), ty_str_reported, ); - if let Mode::MethodCall = mode { - if let SelfSource::MethodCall(call) = source { - self.suggest_await_before_method( - &mut err, item_name, actual, call, span, - ); - } + if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source { + self.suggest_await_before_method( + &mut err, item_name, actual, cal, span, + ); } if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) @@ -1525,43 +1523,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"), (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"), ] { - if let Some(new_rcvr_t) = *rcvr_ty { - if let Ok(pick) = self.lookup_probe( - span, - item_name, - new_rcvr_t, - rcvr, - crate::check::method::probe::ProbeScope::AllTraits, - ) { - debug!("try_alt_rcvr: pick candidate {:?}", pick); - let did = Some(pick.item.container.id()); - // We don't want to suggest a container type when the missing - // method is `.clone()` or `.deref()` otherwise we'd suggest - // `Arc::new(foo).clone()`, which is far from what the user wants. - // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not - // implement the `AsRef` trait. - let skip = skippable.contains(&did) - || (("Pin::new" == *pre) && (sym::as_ref == item_name.name)); - // Make sure the method is defined for the *actual* receiver: we don't - // want to treat `Box` as a receiver if it only works because of - // an autoderef to `&self` - if pick.autoderefs == 0 && !skip { - err.span_label( - pick.item.ident(self.tcx).span, - &format!("the method is available for `{}` here", new_rcvr_t), - ); - err.multipart_suggestion( - "consider wrapping the receiver expression with the \ - appropriate type", - vec![ - (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)), - (rcvr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MaybeIncorrect, - ); - // We don't care about the other suggestions. - alt_rcvr_sugg = true; - } + if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe( + span, + item_name, + new_rcvr_t, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + debug!("try_alt_rcvr: pick candidate {:?}", pick); + let did = Some(pick.item.container.id()); + // We don't want to suggest a container type when the missing + // method is `.clone()` or `.deref()` otherwise we'd suggest + // `Arc::new(foo).clone()`, which is far from what the user wants. + // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not + // implement the `AsRef` trait. + let skip = skippable.contains(&did) + || (("Pin::new" == *pre) && (sym::as_ref == item_name.name)); + // Make sure the method is defined for the *actual* receiver: we don't + // want to treat `Box` as a receiver if it only works because of + // an autoderef to `&self` + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident(self.tcx).span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + err.multipart_suggestion( + "consider wrapping the receiver expression with the \ + appropriate type", + vec![ + (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)), + (rcvr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + // We don't care about the other suggestions. + alt_rcvr_sugg = true; } } } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 7c6917734b2ae..9963a922268a4 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -685,9 +685,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat<'_>) -> bool { - if let PatKind::Binding(..) = inner.kind { - if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { - if let ty::Dynamic(..) = mt.ty.kind() { + if let PatKind::Binding(..) = inner.kind + && let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) + && let ty::Dynamic(..) = mt.ty.kind() + { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. let type_str = self.ty_to_string(expected); @@ -705,8 +706,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); return false; } - } - } true } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 2317ae43f1143..88e3e67c99ee3 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -190,25 +190,23 @@ crate fn placeholder_type_error<'tcx>( let mut is_fn = false; let mut is_const_or_static = false; - if let Some(hir_ty) = hir_ty { - if let hir::TyKind::BareFn(_) = hir_ty.kind { - is_fn = true; - - // Check if parent is const or static - let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); - let parent_node = tcx.hir().get(parent_id); - - is_const_or_static = matches!( - parent_node, - Node::Item(&hir::Item { - kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), - .. - }) | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Const(..), - .. - }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) - ); - } + if let Some(hir_ty) = hir_ty && let hir::TyKind::BareFn(_) = hir_ty.kind { + is_fn = true; + + // Check if parent is const or static + let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); + let parent_node = tcx.hir().get(parent_id); + + is_const_or_static = matches!( + parent_node, + Node::Item(&hir::Item { + kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), + .. + }) | Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Const(..), + .. + }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + ); } // if function is wrapped around a const or static, @@ -2417,16 +2415,14 @@ fn const_evaluatable_predicates_of<'tcx>( let node = tcx.hir().get(hir_id); let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; - if let hir::Node::Item(item) = node { - if let hir::ItemKind::Impl(ref impl_) = item.kind { - if let Some(of_trait) = &impl_.of_trait { - debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); - collector.visit_trait_ref(of_trait); - } - - debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); - collector.visit_ty(impl_.self_ty); + if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(ref impl_) = item.kind { + if let Some(of_trait) = &impl_.of_trait { + debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); + collector.visit_trait_ref(of_trait); } + + debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); + collector.visit_ty(impl_.self_ty); } if let Some(generics) = node.generics() { @@ -3280,15 +3276,14 @@ fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> &'tcx FxHashSet, def_id: DefId) -> bool { - if let Some(impl_item) = tcx.opt_associated_item(def_id) { - if let ty::AssocItemContainer::ImplContainer(_) = impl_item.container { - if let Some(trait_item) = impl_item.trait_item_def_id { - return tcx - .codegen_fn_attrs(trait_item) - .flags - .intersects(CodegenFnAttrFlags::TRACK_CALLER); - } - } + if let Some(impl_item) = tcx.opt_associated_item(def_id) + && let ty::AssocItemContainer::ImplContainer(_) = impl_item.container + && let Some(trait_item) = impl_item.trait_item_def_id + { + return tcx + .codegen_fn_attrs(trait_item) + .flags + .intersects(CodegenFnAttrFlags::TRACK_CALLER); } false diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index f0289fd505a47..de030c5b60bcc 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -55,22 +55,23 @@ This API is completely unstable and subject to change. */ +#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] +#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] +#![feature(hash_drain_filter)] #![feature(if_let_guard)] #![feature(is_sorted)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] -#![feature(nll)] -#![feature(try_blocks)] #![feature(never_type)] -#![feature(slice_partition_dedup)] -#![feature(control_flow_enum)] -#![feature(hash_drain_filter)] +#![feature(nll)] #![feature(once_cell)] +#![feature(slice_partition_dedup)] +#![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index 89f0bd8d42154..61ca09f6b982c 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -304,13 +304,12 @@ pub fn check_explicit_predicates<'tcx>( // = X` binding from the object type (there must be such a // binding) and thus infer an outlives requirement that `X: // 'b`. - if let Some(self_ty) = ignored_self_ty { - if let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() { - if ty.walk().any(|arg| arg == self_ty.into()) { - debug!("skipping self ty = {:?}", &ty); - continue; - } - } + if let Some(self_ty) = ignored_self_ty + && let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() + && ty.walk().any(|arg| arg == self_ty.into()) + { + debug!("skipping self ty = {:?}", &ty); + continue; } let predicate = outlives_predicate.subst(tcx, substs); From 915740c392e0147a5afa6f6fd0e2c303c066ac34 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 26 Feb 2022 16:58:21 +0100 Subject: [PATCH 3/8] Add test for #79465 to prevent regression --- src/test/rustdoc-ui/issue-79465.rs | 3 +++ src/test/rustdoc-ui/issue-79465.stderr | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/rustdoc-ui/issue-79465.rs create mode 100644 src/test/rustdoc-ui/issue-79465.stderr diff --git a/src/test/rustdoc-ui/issue-79465.rs b/src/test/rustdoc-ui/issue-79465.rs new file mode 100644 index 0000000000000..f1a77982fb523 --- /dev/null +++ b/src/test/rustdoc-ui/issue-79465.rs @@ -0,0 +1,3 @@ +pub fn f1(x: T::A) {} +//~^ ERROR +//~^^ ERROR diff --git a/src/test/rustdoc-ui/issue-79465.stderr b/src/test/rustdoc-ui/issue-79465.stderr new file mode 100644 index 0000000000000..489cc14420a4c --- /dev/null +++ b/src/test/rustdoc-ui/issue-79465.stderr @@ -0,0 +1,15 @@ +error[E0220]: associated type `A` not found for `T` + --> $DIR/issue-79465.rs:1:20 + | +LL | pub fn f1(x: T::A) {} + | ^ associated type `A` not found + +error[E0220]: associated type `A` not found for `T` + --> $DIR/issue-79465.rs:1:20 + | +LL | pub fn f1(x: T::A) {} + | ^ associated type `A` not found + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0220`. From 35e3aaf8d87180b7b11568d7bd49b832d7fb63d8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 26 Feb 2022 19:07:02 -0500 Subject: [PATCH 4/8] avoid rebuilding bootstrap when PATH changes --- src/bootstrap/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/build.rs b/src/bootstrap/build.rs index 6e39ea00f808c..8a5bf933d56ec 100644 --- a/src/bootstrap/build.rs +++ b/src/bootstrap/build.rs @@ -4,13 +4,13 @@ use std::path::PathBuf; fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-env-changed=RUSTC"); - println!("cargo:rerun-if-env-changed=PATH"); println!("cargo:rustc-env=BUILD_TRIPLE={}", env::var("HOST").unwrap()); // This may not be a canonicalized path. let mut rustc = PathBuf::from(env::var_os("RUSTC").unwrap()); if rustc.is_relative() { + println!("cargo:rerun-if-env-changed=PATH"); for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let absolute = dir.join(&rustc); if absolute.exists() { From 7ad4297a4960c657932885173bef77fde0f26ccd Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 27 Feb 2022 10:59:10 +0100 Subject: [PATCH 5/8] Use the first codegen backend in the config.toml as default It is currently hard coded to llvm if enabled and cranelift otherwise. This made some sense when cranelift was the only alternative codegen backend. Since the introduction of the gcc backend this doesn't make much sense anymore. Before this PR bootstrapping rustc using a backend other than llvm or cranelift required changing the source of rustc_interface. With this PR it becomes a matter of putting the right backend as first enabled backend in config.toml. --- compiler/rustc_interface/src/util.rs | 8 ++------ config.toml.example | 4 +++- src/bootstrap/compile.rs | 4 ++++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 83b54810db2f2..046f4f9451f58 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -236,13 +236,9 @@ pub fn get_codegen_backend( static LOAD: SyncOnceCell Box> = SyncOnceCell::new(); let load = LOAD.get_or_init(|| { - #[cfg(feature = "llvm")] - const DEFAULT_CODEGEN_BACKEND: &str = "llvm"; + let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm"); - #[cfg(not(feature = "llvm"))] - const DEFAULT_CODEGEN_BACKEND: &str = "cranelift"; - - match backend_name.unwrap_or(DEFAULT_CODEGEN_BACKEND) { + match backend_name.unwrap_or(default_codegen_backend) { filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, diff --git a/config.toml.example b/config.toml.example index ad48cc881f3e6..466a3a29c4c78 100644 --- a/config.toml.example +++ b/config.toml.example @@ -551,7 +551,9 @@ changelog-seen = 2 # This is an array of the codegen backends that will be compiled for the rustc # that's being compiled. The default is to only build the LLVM codegen backend, -# and currently the only standard options supported are `"llvm"` and `"cranelift"`. +# and currently the only standard options supported are `"llvm"`, `"cranelift"` +# and `"gcc"`. The first backend in this list will be used as default by rustc +# when no explicit backend is specified. #codegen-backends = ["llvm"] # Indicates whether LLD will be compiled and made available in the sysroot for diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 53226977fd881..2ceca28da0c6e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -662,6 +662,10 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("CFG_VERSION", builder.rust_version()); + if let Some(backend) = builder.config.rust_codegen_backends.get(0) { + cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend); + } + let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib")); let target_config = builder.config.target_config.get(&target); From 7e0a2a765e4214597e5db690463c10634347d71f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 27 Feb 2022 12:07:38 +0100 Subject: [PATCH 6/8] Correctly generate links in the sidebar for impls --- src/librustdoc/html/render/mod.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 3e3302f8f4db7..3c1737c5e3f5f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -74,7 +74,7 @@ use crate::html::format::{ PrintWithSpace, }; use crate::html::highlight; -use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine}; +use crate::html::markdown::{HeadingOffset, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine}; use crate::html::sources; use crate::scrape_examples::{CallData, CallLocation}; use crate::try_none; @@ -1950,8 +1950,10 @@ fn small_url_encode(s: String) -> String { fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { let did = it.def_id.expect_def_id(); let cache = cx.cache(); + if let Some(v) = cache.impls.get(&did) { let mut used_links = FxHashSet::default(); + let mut id_map = IdMap::new(); { let used_links_bor = &mut used_links; @@ -1992,7 +1994,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { sidebar_deref_methods(cx, out, impl_, v, &mut derefs); } - let format_impls = |impls: Vec<&Impl>| { + let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| { let mut links = FxHashSet::default(); let mut ret = impls @@ -2001,13 +2003,14 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { if let Some(ref i) = it.inner_impl().trait_ { let i_display = format!("{:#}", i.print(cx)); let out = Escape(&i_display); - let encoded = small_url_encode(format!("{:#}", i.print(cx))); + let encoded = + id_map.derive(small_url_encode(format!("impl-{:#}", i.print(cx)))); let prefix = match it.inner_impl().polarity { ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", ty::ImplPolarity::Negative => "!", }; let generated = - format!("{}{}", encoded, prefix, out); + format!("{}{}", encoded, prefix, out); if links.insert(generated.clone()) { Some(generated) } else { None } } else { None @@ -2023,9 +2026,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete.into_iter().partition::, _>(|i| i.inner_impl().kind.is_blanket()); - let concrete_format = format_impls(concrete); - let synthetic_format = format_impls(synthetic); - let blanket_format = format_impls(blanket_impl); + let concrete_format = format_impls(concrete, &mut id_map); + let synthetic_format = format_impls(synthetic, &mut id_map); + let blanket_format = format_impls(blanket_impl, &mut id_map); if !concrete_format.is_empty() { print_sidebar_block( From 9b8a6b97e5fc08a8f5a1aedc803e1f7b44dd50b5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 27 Feb 2022 12:07:54 +0100 Subject: [PATCH 7/8] Add test to ensure that links to impls are correctly generated --- src/test/rustdoc/issue-78701.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/rustdoc/issue-78701.rs diff --git a/src/test/rustdoc/issue-78701.rs b/src/test/rustdoc/issue-78701.rs new file mode 100644 index 0000000000000..796d553fac45e --- /dev/null +++ b/src/test/rustdoc/issue-78701.rs @@ -0,0 +1,20 @@ +#![crate_name = "foo"] + +// This test ensures that if a blanket impl has the same ID as another impl, it'll +// link to the blanket impl and not the other impl. Basically, we're checking if +// the ID is correctly derived. + +// @has 'foo/struct.AnotherStruct.html' +// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait"]' 1 +// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-1"]' 1 + +pub trait Something {} + +pub trait AnAmazingTrait {} + +impl AnAmazingTrait for T {} + +pub struct AnotherStruct(T); + +impl Something for AnotherStruct {} +impl AnAmazingTrait for AnotherStruct<()> {} From 0eb8b32de3b40ce45827af33f290b53ffa012919 Mon Sep 17 00:00:00 2001 From: Caio Date: Sun, 27 Feb 2022 11:10:20 -0300 Subject: [PATCH 8/8] 3 - Make more use of let_chains Continuation of #94376. cc #53667 --- .../src/diagnostics/conflict_errors.rs | 21 +++++++-------- .../src/diagnostics/explain_borrow.rs | 15 +++++------ .../src/diagnostics/mutability_errors.rs | 26 ++++++++----------- .../src/diagnostics/region_errors.rs | 13 ++++------ compiler/rustc_borrowck/src/lib.rs | 21 +++++++-------- .../rustc_borrowck/src/places_conflict.rs | 6 ++--- 6 files changed, 44 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index cd1f73d529818..eb906d5fde7b4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1921,17 +1921,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(assigned_span, format!("first assignment to {}", place_description)); } } - if let Some(decl) = local_decl { - if let Some(name) = local_name { - if decl.can_be_made_mutable() { - err.span_suggestion( - decl.source_info.span, - "consider making this binding mutable", - format!("mut {}", name), - Applicability::MachineApplicable, - ); - } - } + if let Some(decl) = local_decl + && let Some(name) = local_name + && decl.can_be_made_mutable() + { + err.span_suggestion( + decl.source_info.span, + "consider making this binding mutable", + format!("mut {}", name), + Applicability::MachineApplicable, + ); } err.span_label(span, msg); self.buffer_error(err); diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index da6610c002efc..2217c0e14b2aa 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -375,15 +375,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(Cause::DropVar(local, location)) => { let mut should_note_order = false; - if self.local_names[local].is_some() { - if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place { - if let Some(borrowed_local) = place.as_local() { - if self.local_names[borrowed_local].is_some() && local != borrowed_local - { - should_note_order = true; - } - } - } + if self.local_names[local].is_some() + && let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place + && let Some(borrowed_local) = place.as_local() + && self.local_names[borrowed_local].is_some() && local != borrowed_local + { + should_note_order = true; } BorrowExplanation::UsedLaterWhenDropped { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 2c9bd8ea96e9a..610798c7c05c8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1086,21 +1086,17 @@ fn get_mut_span_in_struct_field<'tcx>( field: &mir::Field, ) -> Option { // Expect our local to be a reference to a struct of some kind. - if let ty::Ref(_, ty, _) = ty.kind() { - if let ty::Adt(def, _) = ty.kind() { - let field = def.all_fields().nth(field.index())?; - // Use the HIR types to construct the diagnostic message. - let node = tcx.hir().find_by_def_id(field.did.as_local()?)?; - // Now we're dealing with the actual struct that we're going to suggest a change to, - // we can expect a field that is an immutable reference to a type. - if let hir::Node::Field(field) = node { - if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = - field.ty.kind - { - return Some(lifetime.span.between(ty.span)); - } - } - } + if let ty::Ref(_, ty, _) = ty.kind() + && let ty::Adt(def, _) = ty.kind() + && let field = def.all_fields().nth(field.index())? + // Use the HIR types to construct the diagnostic message. + && let node = tcx.hir().find_by_def_id(field.did.as_local()?)? + // Now we're dealing with the actual struct that we're going to suggest a change to, + // we can expect a field that is an immutable reference to a type. + && let hir::Node::Field(field) = node + && let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind + { + return Some(lt.span.between(ty.span)); } None diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 64f05f6004f53..369aef6798ba6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -140,14 +140,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// Returns `true` if a closure is inferred to be an `FnMut` closure. fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { - if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref() { - if let ty::BoundRegionKind::BrEnv = free_region.bound_region { - if let DefiningTy::Closure(_, substs) = - self.regioncx.universal_regions().defining_ty - { - return substs.as_closure().kind() == ty::ClosureKind::FnMut; - } - } + if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref() + && let ty::BoundRegionKind::BrEnv = free_region.bound_region + && let DefiningTy::Closure(_, substs) = self.regioncx.universal_regions().defining_ty + { + return substs.as_closure().kind() == ty::ClosureKind::FnMut; } false diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c489f409fb53b..82d2d0dd4557f 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1,15 +1,16 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. +#![allow(rustc::potential_query_instability)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] #![feature(trusted_step)] #![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate rustc_middle; @@ -159,16 +160,14 @@ fn do_mir_borrowck<'a, 'tcx>( for var_debug_info in &input_body.var_debug_info { if let VarDebugInfoContents::Place(place) = var_debug_info.value { if let Some(local) = place.as_local() { - if let Some(prev_name) = local_names[local] { - if var_debug_info.name != prev_name { - span_bug!( - var_debug_info.source_info.span, - "local {:?} has many names (`{}` vs `{}`)", - local, - prev_name, - var_debug_info.name - ); - } + if let Some(prev_name) = local_names[local] && var_debug_info.name != prev_name { + span_bug!( + var_debug_info.source_info.span, + "local {:?} has many names (`{}` vs `{}`)", + local, + prev_name, + var_debug_info.name + ); } local_names[local] = Some(var_debug_info.name); } diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 773e9e90b0c6b..5a935c3b8fbfd 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -60,10 +60,8 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( // This Local/Local case is handled by the more general code below, but // it's so common that it's a speed win to check for it first. - if let Some(l1) = borrow_place.as_local() { - if let Some(l2) = access_place.as_local() { - return l1 == l2; - } + if let Some(l1) = borrow_place.as_local() && let Some(l2) = access_place.as_local() { + return l1 == l2; } place_components_conflict(tcx, body, borrow_place, borrow_kind, access_place, access, bias)