diff options
Diffstat (limited to 'compiler')
24 files changed, 223 insertions, 251 deletions
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index d66774040f7..6a0ace04d4b 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -242,6 +242,17 @@ impl Attribute { } } + pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> { + match self.kind { + AttrKind::DocComment(kind, data) => Some((data, kind)), + AttrKind::Normal(ref item, _) if item.path == sym::doc => item + .meta_kind() + .and_then(|kind| kind.value_str()) + .map(|data| (data, CommentKind::Line)), + _ => None, + } + } + pub fn doc_str(&self) -> Option<Symbol> { match self.kind { AttrKind::DocComment(.., data) => Some(data), diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index 0a391123dd3..612ee71f350 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -1,3 +1,4 @@ +use crate::token::CommentKind; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol}; @@ -25,7 +26,7 @@ pub struct Comment { /// Makes a doc string more presentable to users. /// Used by rustdoc and perhaps other tools, but not by rustc. -pub fn beautify_doc_string(data: Symbol) -> Symbol { +pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> { let mut i = 0; let mut j = lines.len(); @@ -42,10 +43,28 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol { if i != 0 || j != lines.len() { Some((i, j)) } else { None } } - fn get_horizontal_trim(lines: &[&str]) -> Option<usize> { + fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> { let mut i = usize::MAX; let mut first = true; + // In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are + // present. However, we first need to strip the empty lines so they don't get in the middle + // when we try to compute the "horizontal trim". + let lines = if kind == CommentKind::Block { + let mut i = 0; + let mut j = lines.len(); + + while i < j && lines[i].trim().is_empty() { + i += 1; + } + while j > i && lines[j - 1].trim().is_empty() { + j -= 1; + } + &lines[i..j] + } else { + lines + }; + for line in lines { for (j, c) in line.chars().enumerate() { if j > i || !"* \t".contains(c) { @@ -79,11 +98,13 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol { } else { &mut lines }; - if let Some(horizontal) = get_horizontal_trim(&lines) { + if let Some(horizontal) = get_horizontal_trim(&lines, kind) { changes = true; // remove a "[ \t]*\*" block from each line, if possible for line in lines.iter_mut() { - *line = &line[horizontal + 1..]; + if horizontal + 1 < line.len() { + *line = &line[horizontal + 1..]; + } } } if changes { diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs index 6d137f3774f..98f692a7724 100644 --- a/compiler/rustc_ast/src/util/comments/tests.rs +++ b/compiler/rustc_ast/src/util/comments/tests.rs @@ -5,7 +5,7 @@ use rustc_span::create_default_session_globals_then; fn test_block_doc_comment_1() { create_default_session_globals_then(|| { let comment = "\n * Test \n ** Test\n * Test\n"; - let stripped = beautify_doc_string(Symbol::intern(comment)); + let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block); assert_eq!(stripped.as_str(), " Test \n* Test\n Test"); }) } @@ -14,7 +14,7 @@ fn test_block_doc_comment_1() { fn test_block_doc_comment_2() { create_default_session_globals_then(|| { let comment = "\n * Test\n * Test\n"; - let stripped = beautify_doc_string(Symbol::intern(comment)); + let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block); assert_eq!(stripped.as_str(), " Test\n Test"); }) } @@ -23,7 +23,7 @@ fn test_block_doc_comment_2() { fn test_block_doc_comment_3() { create_default_session_globals_then(|| { let comment = "\n let a: *i32;\n *a = 5;\n"; - let stripped = beautify_doc_string(Symbol::intern(comment)); + let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block); assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;"); }) } @@ -31,13 +31,13 @@ fn test_block_doc_comment_3() { #[test] fn test_line_doc_comment() { create_default_session_globals_then(|| { - let stripped = beautify_doc_string(Symbol::intern(" test")); + let stripped = beautify_doc_string(Symbol::intern(" test"), CommentKind::Line); assert_eq!(stripped.as_str(), " test"); - let stripped = beautify_doc_string(Symbol::intern("! test")); + let stripped = beautify_doc_string(Symbol::intern("! test"), CommentKind::Line); assert_eq!(stripped.as_str(), "! test"); - let stripped = beautify_doc_string(Symbol::intern("test")); + let stripped = beautify_doc_string(Symbol::intern("test"), CommentKind::Line); assert_eq!(stripped.as_str(), "test"); - let stripped = beautify_doc_string(Symbol::intern("!test")); + let stripped = beautify_doc_string(Symbol::intern("!test"), CommentKind::Line); assert_eq!(stripped.as_str(), "!test"); }) } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f7fe194d207..acf65259f61 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -667,7 +667,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( cmd.env_remove(k); } - if sess.opts.debugging_opts.print_link_args { + if sess.opts.prints.contains(&PrintRequest::LinkArgs) { println!("{:?}", &cmd); } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 694c679c158..19fa6812b45 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -645,9 +645,9 @@ impl RustcDefaultCalls { temps_dir: &Option<PathBuf>, ) -> Compilation { use rustc_session::config::PrintRequest::*; - // PrintRequest::NativeStaticLibs is special - printed during linking + // NativeStaticLibs and LinkArgs are special - printed during linking // (empty iterator returns true) - if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) { + if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) { return Compilation::Continue; } @@ -738,7 +738,8 @@ impl RustcDefaultCalls { codegen_backend.print(*req, sess); } // Any output here interferes with Cargo's parsing of other printed output - PrintRequest::NativeStaticLibs => {} + NativeStaticLibs => {} + LinkArgs => {} } } Compilation::Stop diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 43aa0ae265a..a9dbdd483fe 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2726,6 +2726,10 @@ pub struct FnHeader { } impl FnHeader { + pub fn is_async(&self) -> bool { + matches!(&self.asyncness, IsAsync::Async) + } + pub fn is_const(&self) -> bool { matches!(&self.constness, Constness::Const) } @@ -3169,7 +3173,7 @@ impl<'hir> Node<'hir> { } } - pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> { + pub fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> { match self { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) @@ -3181,6 +3185,15 @@ impl<'hir> Node<'hir> { } } + pub fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> { + match self { + Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) + | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + _ => None, + } + } + pub fn body_id(&self) -> Option<BodyId> { match self { Node::TraitItem(TraitItem { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e98b9c3b03c..14ab635a2ae 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -65,11 +65,11 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::dep_graph::DepContext; -use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, + error::TypeError, subst::{GenericArgKind, Subst, SubstsRef}, - Region, Ty, TyCtxt, TypeFoldable, + Binder, Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; @@ -1765,7 +1765,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.note_error_origin(diag, cause, exp_found, terr); } - pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { + pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> { if let ty::Opaque(def_id, substs) = ty.kind() { let future_trait = self.tcx.require_lang_item(LangItem::Future, None); // Future::Output @@ -1775,13 +1775,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for (predicate, _) in bounds { let predicate = predicate.subst(self.tcx, substs); - if let ty::PredicateKind::Projection(projection_predicate) = - predicate.kind().skip_binder() - { - if projection_predicate.projection_ty.item_def_id == item_def_id { - // We don't account for multiple `Future::Output = Ty` contraints. - return projection_predicate.term.ty(); - } + let output = predicate + .kind() + .map_bound(|kind| match kind { + ty::PredicateKind::Projection(projection_predicate) + if projection_predicate.projection_ty.item_def_id == item_def_id => + { + projection_predicate.term.ty() + } + _ => None, + }) + .transpose(); + if output.is_some() { + // We don't account for multiple `Future::Output = Ty` contraints. + return output; } } } @@ -1823,8 +1830,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } match ( - self.get_impl_future_output_ty(exp_found.expected), - self.get_impl_future_output_ty(exp_found.found), + self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder), + self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder), ) { (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() { ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index ac57796763f..4eec492b3ae 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -106,90 +106,47 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { None => String::new(), }; - let (span_1, span_2, main_label, span_label, future_return_type) = - match (sup_is_ret_type, sub_is_ret_type) { - (None, None) => { - let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id { - ( - "this type is declared with multiple lifetimes...".to_owned(), - "...but data with one lifetime flows into the other here".to_owned(), - ) - } else { - ( - "these two types are declared with different lifetimes...".to_owned(), - format!("...but data{} flows{} here", span_label_var1, span_label_var2), - ) - }; - (ty_sup.span, ty_sub.span, main_label_1, span_label_1, None) - } + debug!( + "try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}", + sub_is_ret_type, sup_is_ret_type + ); - (Some(ret_span), _) => { - let sup_future = self.future_return_type(scope_def_id_sup); - let (return_type, action) = if sup_future.is_some() { - ("returned future", "held across an await point") - } else { - ("return type", "returned") - }; + let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); - ( - ty_sub.span, - ret_span, - format!( - "this parameter and the {} are declared with different lifetimes...", - return_type - ), - format!("...but data{} is {} here", span_label_var1, action), - sup_future, - ) - } - (_, Some(ret_span)) => { - let sub_future = self.future_return_type(scope_def_id_sub); - let (return_type, action) = if sub_future.is_some() { - ("returned future", "held across an await point") - } else { - ("return type", "returned") - }; + match (sup_is_ret_type, sub_is_ret_type) { + (ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => { + let param_span = + if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span }; + + err.span_label( + param_span, + "this parameter and the return type are declared with different lifetimes...", + ); + err.span_label(ret_span, ""); + err.span_label(span, format!("...but data{} is returned here", span_label_var1)); + } - ( + (None, None) => { + if ty_sup.hir_id == ty_sub.hir_id { + err.span_label(ty_sup.span, "this type is declared with multiple lifetimes..."); + err.span_label(ty_sub.span, ""); + err.span_label(span, "...but data with one lifetime flows into the other here"); + } else { + err.span_label( ty_sup.span, - ret_span, - format!( - "this parameter and the {} are declared with different lifetimes...", - return_type - ), - format!("...but data{} is {} here", span_label_var1, action), - sub_future, - ) + "these two types are declared with different lifetimes...", + ); + err.span_label(ty_sub.span, ""); + err.span_label( + span, + format!("...but data{} flows{} here", span_label_var1, span_label_var2), + ); } - }; - - let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); - - err.span_label(span_1, main_label); - err.span_label(span_2, String::new()); - err.span_label(span, span_label); + } + } self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err); - if let Some(t) = future_return_type { - let snip = self - .tcx() - .sess - .source_map() - .span_to_snippet(t.span) - .ok() - .and_then(|s| match (&t.kind, s.as_str()) { - (rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()), - (_, "") => None, - _ => Some(s), - }) - .unwrap_or_else(|| "{unnamed_type}".to_string()); - - err.span_label( - t.span, - &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip), - ); - } err.emit(); Some(ErrorReported) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 07bba000566..b1535701bb3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -1,6 +1,5 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::Node; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime as rl; @@ -25,25 +24,19 @@ pub(crate) fn find_anon_type<'tcx>( tcx: TyCtxt<'tcx>, region: Region<'tcx>, br: &ty::BoundRegionKind, -) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnDecl<'tcx>)> { +) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> { if let Some(anon_reg) = tcx.is_suitable_region(region) { let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id); - let fndecl = match tcx.hir().get(hir_id) { - Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. }) - | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Fn(ref m, ..), .. - }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => { - &m.decl - } - _ => return None, + let Some(fn_sig) = tcx.hir().get(hir_id).fn_sig() else { + return None }; - fndecl + fn_sig + .decl .inputs .iter() .find_map(|arg| find_component_for_bound_region(tcx, arg, br)) - .map(|ty| (ty, &**fndecl)) + .map(|ty| (ty, fn_sig)) } else { None } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 3fa71d1a3d8..6d71d702cc8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -4,7 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_middle::ty::{self, DefIdTree, Region, Ty}; +use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeFoldable}; use rustc_span::Span; /// Information about the anonymous region we are searching for. @@ -94,81 +94,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }) } - pub(super) fn future_return_type( - &self, - local_def_id: LocalDefId, - ) -> Option<&rustc_hir::Ty<'_>> { - if let Some(hir::IsAsync::Async) = self.asyncness(local_def_id) { - if let rustc_middle::ty::Opaque(def_id, _) = - self.tcx().type_of(local_def_id).fn_sig(self.tcx()).output().skip_binder().kind() - { - match self.tcx().hir().get_if_local(*def_id) { - Some(hir::Node::Item(hir::Item { - kind: - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - bounds, - origin: hir::OpaqueTyOrigin::AsyncFn(..), - .. - }), - .. - })) => { - for b in bounds.iter() { - if let hir::GenericBound::LangItemTrait( - hir::LangItem::Future, - _span, - _hir_id, - generic_args, - ) = b - { - for type_binding in generic_args.bindings.iter() { - if type_binding.ident.name == rustc_span::sym::Output { - if let hir::TypeBindingKind::Equality { - term: hir::Term::Ty(ty), - } = type_binding.kind - { - return Some(ty); - } - } - } - } - } - } - _ => {} - } - } - } - None - } - - pub(super) fn asyncness(&self, local_def_id: LocalDefId) -> Option<hir::IsAsync> { - // similar to the asyncness fn in rustc_ty_utils::ty - let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id); - let node = self.tcx().hir().get(hir_id); - let fn_kind = node.fn_kind()?; - Some(fn_kind.asyncness()) - } - // Here, we check for the case where the anonymous region - // is in the return type. + // is in the return type as written by the user. // FIXME(#42703) - Need to handle certain cases here. pub(super) fn is_return_type_anon( &self, scope_def_id: LocalDefId, br: ty::BoundRegionKind, - decl: &hir::FnDecl<'_>, + hir_sig: &hir::FnSig<'_>, ) -> Option<Span> { - let ret_ty = self.tcx().type_of(scope_def_id); - if let ty::FnDef(_, _) = ret_ty.kind() { - let sig = ret_ty.fn_sig(self.tcx()); - let late_bound_regions = - self.tcx().collect_referenced_late_bound_regions(&sig.output()); - if late_bound_regions.iter().any(|r| *r == br) { - return Some(decl.output.span()); - } + let fn_ty = self.tcx().type_of(scope_def_id); + if let ty::FnDef(_, _) = fn_ty.kind() { + let ret_ty = fn_ty.fn_sig(self.tcx()).output(); + let span = hir_sig.decl.output.span(); + let future_output = if hir_sig.header.is_async() { + ret_ty.map_bound(|ty| self.infcx.get_impl_future_output_ty(ty)).transpose() + } else { + None + }; + return match future_output { + Some(output) if self.includes_region(output, br) => Some(span), + None if self.includes_region(ret_ty, br) => Some(span), + _ => None, + }; } None } + fn includes_region( + &self, + ty: Binder<'tcx, impl TypeFoldable<'tcx>>, + region: ty::BoundRegionKind, + ) -> bool { + let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty); + late_bound_regions.iter().any(|r| *r == region) + } + // Here we check for the case where anonymous region // corresponds to self and if yes, we display E0312. // FIXME(#42700) - Need to format self properly to diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0e27a82b2b1..44acbd3cf21 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -678,7 +678,6 @@ fn test_debugging_options_tracking_hash() { // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(profile_closures, true); - untracked!(print_link_args, true); untracked!(print_llvm_passes, true); untracked!(print_mono_items, Some(String::from("abc"))); untracked!(print_type_sizes, true); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 66a89492abd..38e1669d331 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1247,7 +1247,7 @@ declare_lint! { /// [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html MUTABLE_TRANSMUTES, Deny, - "mutating transmuted &mut T from &T may cause undefined behavior" + "transmuting &T to &mut T is undefined behavior, even if the reference is unused" } declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]); @@ -1259,8 +1259,8 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes { get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind())) { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { - let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \ - consider instead using an UnsafeCell"; + let msg = "transmuting &T to &mut T is undefined behavior, \ + even if the reference is unused, consider instead using an UnsafeCell"; cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit()); } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e7b99995ca4..8d591d67812 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1210,11 +1210,25 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(Error(DelaySpanBugEmitted(()))) } - /// Like `err` but for constants. + /// Like [TyCtxt::ty_error] but for constants. #[track_caller] pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { - self.sess - .delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported."); + self.const_error_with_message( + ty, + DUMMY_SP, + "ty::ConstKind::Error constructed but no error reported", + ) + } + + /// Like [TyCtxt::ty_error_with_message] but for constants. + #[track_caller] + pub fn const_error_with_message<S: Into<MultiSpan>>( + self, + ty: Ty<'tcx>, + span: S, + msg: &str, + ) -> &'tcx Const<'tcx> { + self.sess.delay_span_bug(span, msg); self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty }) } diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 77bc209539b..cda9ba9dcc8 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -3,8 +3,7 @@ use crate::MirPass; use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::mir::{ - BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, - TerminatorKind, + BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, TerminatorKind, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; @@ -56,7 +55,10 @@ fn variant_discriminants<'tcx>( match &layout.variants { Variants::Single { index } => { let mut res = FxHashSet::default(); - res.insert(index.as_u32() as u128); + res.insert( + ty.discriminant_for_variant(tcx, *index) + .map_or(index.as_u32() as u128, |discr| discr.val), + ); res } Variants::Multiple { variants, .. } => variants @@ -75,16 +77,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if body.source.promoted.is_some() { - return; - } - trace!("UninhabitedEnumBranching starting for {:?}", body.source); - let basic_block_count = body.basic_blocks().len(); - - for bb in 0..basic_block_count { - let bb = BasicBlock::from_usize(bb); + for bb in body.basic_blocks().indices() { trace!("processing block {:?}", bb); let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) else { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 2c968991973..0b4579b299d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1148,19 +1148,11 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { if self.visit(ty).is_break() { return; } + } else { + // We don't do anything for const infers here. } } else { - let local_id = self.tcx.hir().local_def_id(inf.hir_id); - if let Some(did) = self.tcx.opt_const_param_of(local_id) { - if self.visit_def_id(did, "inferred", &"").is_break() { - return; - } - } - - // FIXME see above note for same issue. - if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() { - return; - } + bug!("visit_infer without typeck_results"); } intravisit::walk_inf(self, inf); } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 21cb93cc5f4..b95fe1b0549 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -821,9 +821,9 @@ impl<'tcx> SaveContext<'tcx> { let mut result = String::new(); for attr in attrs { - if let Some(val) = attr.doc_str() { + if let Some((val, kind)) = attr.doc_str_and_comment_kind() { // FIXME: Should save-analysis beautify doc strings itself or leave it to users? - result.push_str(beautify_doc_string(val).as_str()); + result.push_str(beautify_doc_string(val, kind).as_str()); result.push('\n'); } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 62b351f5e02..92ad0723f48 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -565,6 +565,7 @@ pub enum PrintRequest { TargetSpec, NativeStaticLibs, StackProtectorStrategies, + LinkArgs, } #[derive(Copy, Clone)] @@ -1187,7 +1188,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ target-cpus|target-features|relocation-models|code-models|\ - tls-models|target-spec-json|native-static-libs|stack-protector-strategies]", + tls-models|target-spec-json|native-static-libs|stack-protector-strategies\ + link-args]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), @@ -1619,6 +1621,7 @@ fn collect_print_requests( ); } } + "link-args" => PrintRequest::LinkArgs, req => early_error(error_format, &format!("unknown print request `{}`", req)), })); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c48d8d689c1..e7ab8fffdf3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1339,8 +1339,6 @@ options! { See #77382 and #74551."), print_fuel: Option<String> = (None, parse_opt_string, [TRACKED], "make rustc print the total optimization fuel used by a crate"), - print_link_args: bool = (false, parse_bool, [UNTRACKED], - "print the arguments passed to the linker (default: no)"), print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "print the LLVM optimization passes being run (default: no)"), print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED], diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 7c53e49e280..d9b3f51b5bd 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -6,7 +6,7 @@ mod errors; mod generics; use crate::bounds::Bounds; -use crate::collect::PlaceholderHirTyCollector; +use crate::collect::HirPlaceholderCollector; use crate::errors::{ AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits, TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified, @@ -2504,7 +2504,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!(?bound_vars); // We proactively collect all the inferred type params to emit a single error per fn def. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); for ty in decl.inputs { visitor.visit_ty(ty); } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 3e73cc659ec..f6abeff60cd 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1909,7 +1909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => return, }; let mut add_label = true; - if let ty::Adt(def, _) = output_ty.kind() { + if let ty::Adt(def, _) = output_ty.skip_binder().kind() { // no field access on enum type if !def.is_enum() { if def diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 473c848ad8f..be4c9ec99b9 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -609,14 +609,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.normalize_associated_types_in(expr.span, ty); let ty = match self.tcx.asyncness(fn_id.owner) { - hir::IsAsync::Async => self.tcx.infer_ctxt().enter(|infcx| { - infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| { - span_bug!( - fn_decl.output.span(), - "failed to get output type of async function" - ) + hir::IsAsync::Async => self + .tcx + .infer_ctxt() + .enter(|infcx| { + infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| { + span_bug!( + fn_decl.output.span(), + "failed to get output type of async function" + ) + }) }) - }), + .skip_binder(), hir::IsAsync::NotAsync => ty, }; if self.can_coerce(found, ty) { diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 56f4d5afe40..96ab800afaf 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1274,7 +1274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, ) { let output_ty = match self.infcx.get_impl_future_output_ty(ty) { - Some(output_ty) => self.resolve_vars_if_possible(output_ty), + Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(), _ => return, }; let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 403aa16689f..cf519a9ab32 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -112,9 +112,9 @@ pub struct ItemCtxt<'tcx> { /////////////////////////////////////////////////////////////////////////// #[derive(Default)] -crate struct PlaceholderHirTyCollector(crate Vec<Span>); +crate struct HirPlaceholderCollector(crate Vec<Span>); -impl<'v> Visitor<'v> for PlaceholderHirTyCollector { +impl<'v> Visitor<'v> for HirPlaceholderCollector { fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { if let hir::TyKind::Infer = t.kind { self.0.push(t.span); @@ -131,6 +131,12 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector { _ => {} } } + fn visit_array_length(&mut self, length: &'v hir::ArrayLen) { + if let &hir::ArrayLen::Infer(_, span) = length { + self.0.push(span); + } + intravisit::walk_array_len(self, length) + } } struct CollectItemTypesVisitor<'tcx> { @@ -175,7 +181,7 @@ crate fn placeholder_type_error<'tcx>( sugg.push((span, format!(", {}", type_name))); } - let mut err = bad_placeholder(tcx, "type", placeholder_types, kind); + let mut err = bad_placeholder(tcx, placeholder_types, kind); // Suggest, but only if it is not a function in const or static if suggest { @@ -233,7 +239,7 @@ fn reject_placeholder_type_signatures_in_item<'tcx>( _ => return, }; - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_item(item); placeholder_type_error( @@ -311,7 +317,6 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { fn bad_placeholder<'tcx>( tcx: TyCtxt<'tcx>, - placeholder_kind: &'static str, mut spans: Vec<Span>, kind: &'static str, ) -> rustc_errors::DiagnosticBuilder<'tcx> { @@ -322,8 +327,7 @@ fn bad_placeholder<'tcx>( tcx.sess, spans.clone(), E0121, - "the {} placeholder `_` is not allowed within types on item signatures for {}", - placeholder_kind, + "the placeholder `_` is not allowed within types on item signatures for {}", kind ); for span in spans { @@ -381,7 +385,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - self.tcx().ty_error_with_message(span, "bad_placeholder_type") + self.tcx().ty_error_with_message(span, "bad placeholder type") } fn ct_infer( @@ -390,13 +394,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { _: Option<&ty::GenericParamDef>, span: Span, ) -> &'tcx Const<'tcx> { - bad_placeholder(self.tcx(), "const", vec![span], "generic").emit(); - // Typeck doesn't expect erased regions to be returned from `type_of`. let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r { ty::ReErased => self.tcx.lifetimes.re_static, _ => r, }); - self.tcx().const_error(ty) + self.tcx().const_error_with_message(ty, span, "bad placeholder constant") } fn projected_ty_from_poly_trait_ref( @@ -743,7 +745,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { match item.kind { hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id), hir::ForeignItemKind::Static(..) => { - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_foreign_item(item); placeholder_type_error( tcx, @@ -826,7 +828,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => { // (#75889): Account for `const C: dyn Fn() -> _ = "";` if let hir::TyKind::TraitObject(..) = ty.kind { - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_item(it); placeholder_type_error( tcx, @@ -862,7 +864,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { hir::TraitItemKind::Const(..) => { tcx.ensure().type_of(trait_item_id.def_id); // Account for `const C: _;`. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant"); } @@ -871,7 +873,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { tcx.ensure().item_bounds(trait_item_id.def_id); tcx.ensure().type_of(trait_item_id.def_id); // Account for `type T = _;`. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); } @@ -880,7 +882,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { tcx.ensure().item_bounds(trait_item_id.def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); @@ -902,7 +904,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { } hir::ImplItemKind::TyAlias(_) => { // Account for `type T = _;` - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_impl_item(impl_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); @@ -1822,10 +1824,14 @@ fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool { /// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to /// use inference to provide suggestions for the appropriate type if possible. fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { + debug!(?ty); use hir::TyKind::*; match &ty.kind { Infer => true, - Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty), + Slice(ty) => is_suggestable_infer_ty(ty), + Array(ty, length) => { + is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _)) + } Tup(tys) => tys.iter().any(is_suggestable_infer_ty), Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args), @@ -1877,9 +1883,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { }); let fn_sig = ty::Binder::dummy(fn_sig); - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_ty(ty); - let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type"); + let mut diag = bad_placeholder(tcx, visitor.0, "return type"); let ret_ty = fn_sig.skip_binder().output(); if !ret_ty.references_error() { if !ret_ty.is_closure() { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index bc7507bcc50..63020b7f90f 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -20,9 +20,6 @@ use super::{bad_placeholder, is_suggestable_infer_ty}; /// This should be called using the query `tcx.opt_const_param_of`. #[instrument(level = "debug", skip(tcx))] pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> { - // FIXME(generic_arg_infer): allow for returning DefIds of inference of - // GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag - // for const or type. use hir::*; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -753,7 +750,7 @@ fn infer_placeholder_type<'a>( err.emit(); } None => { - let mut diag = bad_placeholder(tcx, "type", vec![span], kind); + let mut diag = bad_placeholder(tcx, vec![span], kind); if !ty.references_error() { let mut mk_nameable = MakeNameable::new(tcx); |
