diff options
Diffstat (limited to 'compiler')
156 files changed, 1487 insertions, 1676 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 11e7b80f85e..9c2cf58efed 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -354,7 +354,7 @@ pub trait LayoutCalculator { if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized } }; - let mut st = self.univariant(dl, &variants[v], &repr, kind)?; + let mut st = self.univariant(dl, &variants[v], repr, kind)?; st.variants = Variants::Single { index: v }; if is_unsafe_cell { @@ -457,7 +457,7 @@ pub trait LayoutCalculator { let mut variant_layouts = variants .iter_enumerated() .map(|(j, v)| { - let mut st = self.univariant(dl, v, &repr, StructKind::AlwaysSized)?; + let mut st = self.univariant(dl, v, repr, StructKind::AlwaysSized)?; st.variants = Variants::Single { index: j }; align = align.max(st.align); @@ -647,8 +647,8 @@ pub trait LayoutCalculator { .map(|(i, field_layouts)| { let mut st = self.univariant( dl, - &field_layouts, - &repr, + field_layouts, + repr, StructKind::Prefixed(min_ity.size(), prefix_align), )?; st.variants = Variants::Single { index: i }; @@ -755,7 +755,7 @@ pub trait LayoutCalculator { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; let mut common_prim_initialized_in_all_variants = true; - for (field_layouts, layout_variant) in iter::zip(&*variants, &layout_variants) { + for (field_layouts, layout_variant) in iter::zip(variants, &layout_variants) { let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else { panic!(); }; diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 6a2f1f0c574..4d80f904ac4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1179,7 +1179,7 @@ impl Expr { pub fn peel_parens(&self) -> &Expr { let mut expr = self; while let ExprKind::Paren(inner) = &expr.kind { - expr = &inner; + expr = inner; } expr } @@ -1312,8 +1312,10 @@ pub struct Closure { pub movability: Movability, pub fn_decl: P<FnDecl>, pub body: P<Expr>, - /// The span of the argument block `|...|`. + /// The span of the declaration block: 'move |...| -> ...' pub fn_decl_span: Span, + /// The span of the argument block `|...|` + pub fn_arg_span: Span, } /// Limit types of a range (inclusive or exclusive) @@ -2027,7 +2029,7 @@ impl Ty { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { - final_ty = &ty; + final_ty = ty; } final_ty } @@ -2517,10 +2519,7 @@ pub struct Variant { #[derive(Clone, Encodable, Decodable, Debug)] pub enum UseTreeKind { /// `use prefix` or `use prefix as rename` - /// - /// The extra `NodeId`s are for HIR lowering, when additional statements are created for each - /// namespace. - Simple(Option<Ident>, NodeId, NodeId), + Simple(Option<Ident>), /// `use prefix::{...}` Nested(Vec<(UseTree, NodeId)>), /// `use prefix::*` @@ -2539,8 +2538,8 @@ pub struct UseTree { impl UseTree { pub fn ident(&self) -> Ident { match self.kind { - UseTreeKind::Simple(Some(rename), ..) => rename, - UseTreeKind::Simple(None, ..) => { + UseTreeKind::Simple(Some(rename)) => rename, + UseTreeKind::Simple(None) => { self.prefix.segments.last().expect("empty prefix in a simple import").ident } _ => panic!("`UseTree::ident` can only be used on a simple import"), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index cb3c54fa03c..a45ee6067bb 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -410,11 +410,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) { let UseTree { prefix, kind, span } = use_tree; vis.visit_path(prefix); match kind { - UseTreeKind::Simple(rename, id1, id2) => { - visit_opt(rename, |rename| vis.visit_ident(rename)); - vis.visit_id(id1); - vis.visit_id(id2); - } + UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)), UseTreeKind::Nested(items) => { for (tree, id) in items { vis.visit_use_tree(tree); @@ -740,8 +736,7 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) { return; // Avoid visiting the span for the second time. } token::Interpolated(nt) => { - let mut nt = Lrc::make_mut(nt); - visit_nonterminal(&mut nt, vis); + visit_nonterminal(Lrc::make_mut(nt), vis); } _ => {} } @@ -1372,6 +1367,7 @@ pub fn noop_visit_expr<T: MutVisitor>( fn_decl, body, fn_decl_span, + fn_arg_span: _, }) => { vis.visit_closure_binder(binder); vis.visit_asyncness(asyncness); diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 58c6d397ea2..482c302950f 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -64,7 +64,7 @@ impl TokenTree { match (self, other) { (TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind, (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => { - delim == delim2 && tts.eq_unspanned(&tts2) + delim == delim2 && tts.eq_unspanned(tts2) } _ => false, } @@ -402,7 +402,7 @@ impl TokenStream { let mut t1 = self.trees(); let mut t2 = other.trees(); for (t1, t2) in iter::zip(&mut t1, &mut t2) { - if !t1.eq_unspanned(&t2) { + if !t1.eq_unspanned(t2) { return false; } } @@ -475,7 +475,7 @@ impl TokenStream { token::Interpolated(nt) => TokenTree::Delimited( DelimSpan::from_single(token.span), Delimiter::Invisible, - TokenStream::from_nonterminal_ast(&nt).flattened(), + TokenStream::from_nonterminal_ast(nt).flattened(), ), _ => TokenTree::Token(token.clone(), spacing), } @@ -511,7 +511,7 @@ impl TokenStream { fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool { if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = vec.last() && let TokenTree::Token(tok, spacing) = tt - && let Some(glued_tok) = last_tok.glue(&tok) + && let Some(glued_tok) = last_tok.glue(tok) { // ...then overwrite the last token tree in `vec` with the // glued token, and skip the first token tree from `stream`. diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index fbb4cf43a95..cdc244c1218 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -21,6 +21,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::TryBlock(..) + | ast::ExprKind::ConstBlock(..) ) } diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index c96474ccb42..35454c3a670 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -110,7 +110,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { } else { &mut lines }; - if let Some(horizontal) = get_horizontal_trim(&lines, kind) { + 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() { @@ -147,7 +147,7 @@ fn all_whitespace(s: &str, col: CharPos) -> Option<usize> { fn trim_whitespace_prefix(s: &str, col: CharPos) -> &str { let len = s.len(); - match all_whitespace(&s, col) { + match all_whitespace(s, col) { Some(col) => { if col < len { &s[col..] diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 1d6e7914f3a..f6f186b5107 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -52,14 +52,14 @@ impl LitKind { // new symbol because the string in the LitKind is different to the // string in the token. let s = symbol.as_str(); - let symbol = if s.contains(&['\\', '\r']) { + let symbol = if s.contains(['\\', '\r']) { let mut buf = String::with_capacity(s.len()); let mut error = Ok(()); // Force-inlining here is aggressive but the closure is // called on every char in the string, so it can be // hot in programs with many long strings. unescape_literal( - &s, + s, Mode::Str, &mut #[inline(always)] |_, unescaped_char| match unescaped_char { @@ -85,7 +85,7 @@ impl LitKind { if s.contains('\r') { let mut buf = String::with_capacity(s.len()); let mut error = Ok(()); - unescape_literal(&s, Mode::RawStr, &mut |_, unescaped_char| { + unescape_literal(s, Mode::RawStr, &mut |_, unescaped_char| { match unescaped_char { Ok(c) => buf.push(c), Err(err) => { @@ -106,7 +106,7 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c { + unescape_literal(s, Mode::ByteStr, &mut |_, c| match c { Ok(c) => buf.push(byte_from_char(c)), Err(err) => { if err.is_fatal() { @@ -122,7 +122,7 @@ impl LitKind { let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c { + unescape_literal(s, Mode::RawByteStr, &mut |_, c| match c { Ok(c) => buf.push(byte_from_char(c)), Err(err) => { if err.is_fatal() { diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index f65f1f069cb..819f1884a06 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -384,7 +384,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { | ast::ExprKind::AssignOp(_, lhs, rhs) | ast::ExprKind::Binary(_, lhs, rhs) => { // X { y: 1 } + X { y: 2 } - contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) + contains_exterior_struct_lit(lhs) || contains_exterior_struct_lit(rhs) } ast::ExprKind::Await(x) | ast::ExprKind::Unary(_, x) @@ -393,12 +393,12 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { | ast::ExprKind::Field(x, _) | ast::ExprKind::Index(x, _) => { // &X { y: 1 }, X { y: 1 }.y - contains_exterior_struct_lit(&x) + contains_exterior_struct_lit(x) } ast::ExprKind::MethodCall(box ast::MethodCall { receiver, .. }) => { // X { y: 1 }.bar(...) - contains_exterior_struct_lit(&receiver) + contains_exterior_struct_lit(receiver) } _ => false, diff --git a/compiler/rustc_ast/src/util/unicode.rs b/compiler/rustc_ast/src/util/unicode.rs index f009f7b300c..0eae791b25e 100644 --- a/compiler/rustc_ast/src/util/unicode.rs +++ b/compiler/rustc_ast/src/util/unicode.rs @@ -17,7 +17,7 @@ pub fn contains_text_flow_control_chars(s: &str) -> bool { // U+2069 - E2 81 A9 let mut bytes = s.as_bytes(); loop { - match core::slice::memchr::memchr(0xE2, &bytes) { + match core::slice::memchr::memchr(0xE2, bytes) { Some(idx) => { // bytes are valid UTF-8 -> E2 must be followed by two bytes let ch = &bytes[idx..idx + 3]; diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index c528118be08..991eb489f6b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -439,7 +439,7 @@ pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) { pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree, id: NodeId) { visitor.visit_path(&use_tree.prefix, id); match &use_tree.kind { - UseTreeKind::Simple(rename, ..) => { + UseTreeKind::Simple(rename) => { // The extra IDs are handled during HIR lowering. if let &Some(rename) = rename { visitor.visit_ident(rename); @@ -840,6 +840,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { fn_decl, body, fn_decl_span: _, + fn_arg_span: _, }) => { visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id) } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 2a0338adc9c..dfef6ec70fc 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -222,7 +222,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Wrap the expression in an AnonConst. let parent_def_id = self.current_hir_id_owner; let node_id = self.next_node_id(); - self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst); + self.create_def( + parent_def_id.def_id, + node_id, + DefPathData::AnonConst, + *op_sp, + ); let anon_const = AnonConst { id: node_id, value: P(expr) }; hir::InlineAsmOperand::SymFn { anon_const: self.lower_anon_const(&anon_const), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 82912a733d5..4260805f1dd 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -176,6 +176,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl, body, fn_decl_span, + fn_arg_span, }) => { if let Async::Yes { closure_id, .. } = asyncness { self.lower_expr_async_closure( @@ -186,6 +187,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl, body, *fn_decl_span, + *fn_arg_span, ) } else { self.lower_expr_closure( @@ -196,6 +198,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl, body, *fn_decl_span, + *fn_arg_span, ) } } @@ -365,7 +368,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst); + self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst, f.span); let anon_const = AnonConst { id: node_id, value: arg }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); @@ -642,6 +645,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl, body, fn_decl_span: self.lower_span(span), + fn_arg_span: None, movability: Some(hir::Movability::Static), }); @@ -898,6 +902,7 @@ impl<'hir> LoweringContext<'_, 'hir> { decl: &FnDecl, body: &Expr, fn_decl_span: Span, + fn_arg_span: Span, ) -> hir::ExprKind<'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); @@ -928,6 +933,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl, body: body_id, fn_decl_span: self.lower_span(fn_decl_span), + fn_arg_span: Some(self.lower_span(fn_arg_span)), movability: generator_option, }); @@ -984,6 +990,7 @@ impl<'hir> LoweringContext<'_, 'hir> { decl: &FnDecl, body: &Expr, fn_decl_span: Span, + fn_arg_span: Span, ) -> hir::ExprKind<'hir> { if let &ClosureBinder::For { span, .. } = binder { self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); @@ -1038,6 +1045,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl, body, fn_decl_span: self.lower_span(fn_decl_span), + fn_arg_span: Some(self.lower_span(fn_arg_span)), movability: None, }); hir::ExprKind::Closure(c) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 2b47e908912..f6275433fc5 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -19,7 +19,6 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, Symbol}; use rustc_target::spec::abi; use smallvec::{smallvec, SmallVec}; -use std::iter; use thin_vec::ThinVec; pub(super) struct ItemLowerer<'a, 'hir> { @@ -179,36 +178,22 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut node_ids = smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; if let ItemKind::Use(use_tree) = &i.kind { - self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); + self.lower_item_id_use_tree(use_tree, &mut node_ids); } node_ids } - fn lower_item_id_use_tree( - &mut self, - tree: &UseTree, - base_id: NodeId, - vec: &mut SmallVec<[hir::ItemId; 1]>, - ) { + fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) { match &tree.kind { UseTreeKind::Nested(nested_vec) => { for &(ref nested, id) in nested_vec { vec.push(hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, }); - self.lower_item_id_use_tree(nested, id, vec); - } - } - UseTreeKind::Glob => {} - UseTreeKind::Simple(_, id1, id2) => { - for (_, id) in - iter::zip(self.expect_full_res_from_use(base_id).skip(1), [*id1, *id2]) - { - vec.push(hir::ItemId { - owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, - }); + self.lower_item_id_use_tree(nested, vec); } } + UseTreeKind::Simple(..) | UseTreeKind::Glob => {} } } @@ -489,7 +474,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect(); match tree.kind { - UseTreeKind::Simple(rename, id1, id2) => { + UseTreeKind::Simple(rename) => { *ident = tree.ident(); // First, apply the prefix to the path. @@ -505,66 +490,16 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - let mut resolutions = self.expect_full_res_from_use(id).fuse(); - // We want to return *something* from this function, so hold onto the first item - // for later. - let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err)); - - // Here, we are looping over namespaces, if they exist for the definition - // being imported. We only handle type and value namespaces because we - // won't be dealing with macros in the rest of the compiler. - // Essentially a single `use` which imports two names is desugared into - // two imports. - for new_node_id in [id1, id2] { - let new_id = self.local_def_id(new_node_id); - let Some(res) = resolutions.next() else { - debug_assert!(self.children.iter().find(|(id, _)| id == &new_id).is_none()); - // Associate an HirId to both ids even if there is no resolution. - self.children.push(( - new_id, - hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id))), - ); - continue; - }; - let ident = *ident; - let mut path = path.clone(); - for seg in &mut path.segments { - // Give the cloned segment the same resolution information - // as the old one (this is needed for stability checking). - let new_id = self.next_node_id(); - self.resolver.clone_res(seg.id, new_id); - seg.id = new_id; - } - let span = path.span; - - self.with_hir_id_owner(new_node_id, |this| { - let res = this.lower_res(res); - let path = this.lower_path_extra(res, &path, ParamMode::Explicit); - let kind = hir::ItemKind::Use(path, hir::UseKind::Single); - if let Some(attrs) = attrs { - this.attrs.insert(hir::ItemLocalId::new(0), attrs); - } - - let item = hir::Item { - owner_id: hir::OwnerId { def_id: new_id }, - ident: this.lower_ident(ident), - kind, - vis_span, - span: this.lower_span(span), - }; - hir::OwnerNode::Item(this.arena.alloc(item)) - }); - } - - let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit); + let res = + self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); + let path = self.lower_use_path(res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Single) } UseTreeKind::Glob => { - let path = self.lower_path( - id, - &Path { segments, span: path.span, tokens: None }, - ParamMode::Explicit, - ); + let res = self.expect_full_res(id); + let res = smallvec![self.lower_res(res)]; + let path = Path { segments, span: path.span, tokens: None }; + let path = self.lower_use_path(res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Glob) } UseTreeKind::Nested(ref trees) => { @@ -634,9 +569,9 @@ impl<'hir> LoweringContext<'_, 'hir> { }); } - let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err); - let res = self.lower_res(res); - let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit); + let res = + self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); + let path = self.lower_use_path(res, &prefix, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::ListStem) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1d279706278..0258f8fd2d9 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -487,6 +487,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parent: LocalDefId, node_id: ast::NodeId, data: DefPathData, + span: Span, ) -> LocalDefId { debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( @@ -497,7 +498,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.tcx.hir().def_key(self.local_def_id(node_id)), ); - let def_id = self.tcx.create_def(parent, data).def_id(); + let def_id = self.tcx.at(span).create_def(parent, data).def_id(); debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.resolver.node_id_to_def_id.insert(node_id, def_id); @@ -823,6 +824,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.current_hir_id_owner.def_id, param, DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ident.span, ); debug!(?_def_id); @@ -1151,15 +1153,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let parent_def_id = self.current_hir_id_owner; let node_id = self.next_node_id(); + let span = self.lower_span(ty.span); // Add a definition for the in-band const def. let def_id = self.create_def( parent_def_id.def_id, node_id, DefPathData::AnonConst, + span, ); - let span = self.lower_span(ty.span); let path_expr = Expr { id: ty.id, kind: ExprKind::Path(qself.clone(), path.clone()), @@ -1353,12 +1356,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx, ), ImplTraitContext::Universal => { + let span = t.span; self.create_def( self.current_hir_id_owner.def_id, *def_node_id, DefPathData::ImplTrait, + span, ); - let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); let (param, bounds, path) = self.lower_generic_and_bounds(*def_node_id, span, ident, bounds); @@ -1455,6 +1459,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.current_hir_id_owner.def_id, opaque_ty_node_id, DefPathData::ImplTrait, + opaque_ty_span, ); debug!(?opaque_ty_def_id); @@ -1608,6 +1613,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parent_def_id, node_id, DefPathData::LifetimeNs(lifetime.ident.name), + lifetime.ident.span, ); remapping.insert(old_def_id, new_def_id); @@ -1624,6 +1630,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parent_def_id, node_id, DefPathData::LifetimeNs(kw::UnderscoreLifetime), + lifetime.ident.span, ); remapping.insert(old_def_id, new_def_id); @@ -1806,7 +1813,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let fn_def_id = self.local_def_id(fn_node_id); let opaque_ty_def_id = - self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait); + self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait, opaque_ty_span); // When we create the opaque type for this async fn, it is going to have // to capture all the lifetimes involved in the signature (including in the @@ -1866,6 +1873,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_def_id, inner_node_id, DefPathData::LifetimeNs(ident.name), + ident.span, ); new_remapping.insert(outer_def_id, inner_def_id); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index dc85b5e95ea..8d23c26e603 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -12,7 +12,7 @@ use rustc_hir::GenericArg; use rustc_span::symbol::{kw, Ident}; use rustc_span::{BytePos, Span, DUMMY_SP}; -use smallvec::smallvec; +use smallvec::{smallvec, SmallVec}; impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "trace", skip(self))] @@ -144,13 +144,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); } - pub(crate) fn lower_path_extra( + pub(crate) fn lower_use_path( &mut self, - res: Res, + res: SmallVec<[Res; 3]>, p: &Path, param_mode: ParamMode, - ) -> &'hir hir::Path<'hir> { - self.arena.alloc(hir::Path { + ) -> &'hir hir::UsePath<'hir> { + self.arena.alloc(hir::UsePath { res, segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { self.lower_path_segment( @@ -165,17 +165,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } - pub(crate) fn lower_path( - &mut self, - id: NodeId, - p: &Path, - param_mode: ParamMode, - ) -> &'hir hir::Path<'hir> { - let res = self.expect_full_res(id); - let res = self.lower_res(res); - self.lower_path_extra(res, p, param_mode) - } - pub(crate) fn lower_path_segment( &mut self, path_span: Span, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index ebe55a4b771..d3d8431c163 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -519,7 +519,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere ast::MetaItemKind::List(items) => { self.print_path(&item.path, false, 0); self.popen(); - self.commasep(Consistent, &items, |s, i| s.print_meta_list_item(i)); + self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i)); self.pclose(); } } @@ -536,7 +536,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) { match tt { TokenTree::Token(token, _) => { - let token_str = self.token_to_string_ext(&token, convert_dollar_crate); + let token_str = self.token_to_string_ext(token, convert_dollar_crate); self.word(token_str); if let token::DocComment(..) = token.kind { self.hardbreak() @@ -998,7 +998,7 @@ impl<'a> State<'a> { ast::AssocConstraintKind::Bound { bounds } => { if !bounds.is_empty() { self.word_nbsp(":"); - self.print_type_bounds(&bounds); + self.print_type_bounds(bounds); } } } @@ -1035,7 +1035,7 @@ impl<'a> State<'a> { } ast::TyKind::Tup(elts) => { self.popen(); - self.commasep(Inconsistent, &elts, |s, ty| s.print_type(ty)); + self.commasep(Inconsistent, elts, |s, ty| s.print_type(ty)); if elts.len() == 1 { self.word(","); } @@ -1254,7 +1254,7 @@ impl<'a> State<'a> { self.popen(); self.commasep(Consistent, &args, |s, arg| match arg { - AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked), + AsmArg::Template(template) => s.print_string(template, ast::StrStyle::Cooked), AsmArg::Operand(op) => { let print_reg_or_class = |s: &mut Self, r: &InlineAsmRegOrRegClass| match r { InlineAsmRegOrRegClass::Reg(r) => s.print_symbol(*r, ast::StrStyle::Cooked), @@ -1424,11 +1424,11 @@ impl<'a> State<'a> { self.print_path(path, true, 0); } self.popen(); - self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); + self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); self.pclose(); } PatKind::Or(pats) => { - self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(p)); + self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p)); } PatKind::Path(None, path) => { self.print_path(path, true, 0); @@ -1450,7 +1450,7 @@ impl<'a> State<'a> { } self.commasep_cmnt( Consistent, - &fields, + fields, |s, f| { s.cbox(INDENT_UNIT); if !f.is_shorthand { @@ -1475,7 +1475,7 @@ impl<'a> State<'a> { } PatKind::Tuple(elts) => { self.popen(); - self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); + self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); if elts.len() == 1 { self.word(","); } @@ -1498,7 +1498,7 @@ impl<'a> State<'a> { self.print_pat(inner); } } - PatKind::Lit(e) => self.print_expr(&**e), + PatKind::Lit(e) => self.print_expr(e), PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => { if let Some(e) = begin { self.print_expr(e); @@ -1514,7 +1514,7 @@ impl<'a> State<'a> { } PatKind::Slice(elts) => { self.word("["); - self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); + self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); self.word("]"); } PatKind::Rest => self.word(".."), @@ -1600,7 +1600,7 @@ impl<'a> State<'a> { self.word("<"); - self.commasep(Inconsistent, &generic_params, |s, param| { + self.commasep(Inconsistent, generic_params, |s, param| { s.print_outer_attributes_inline(¶m.attrs); match ¶m.kind { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 81483ac30d1..4ed16e337d2 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -305,10 +305,10 @@ impl<'a> State<'a> { self.print_expr_tup(exprs); } ast::ExprKind::Call(func, args) => { - self.print_expr_call(func, &args); + self.print_expr_call(func, args); } ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => { - self.print_expr_method_call(seg, &receiver, &args); + self.print_expr_method_call(seg, receiver, args); } ast::ExprKind::Binary(op, lhs, rhs) => { self.print_expr_binary(*op, lhs, rhs); @@ -402,6 +402,7 @@ impl<'a> State<'a> { fn_decl, body, fn_decl_span: _, + fn_arg_span: _, }) => { self.print_closure_binder(binder); self.print_movability(*movability); @@ -605,7 +606,7 @@ impl<'a> State<'a> { match binder { ast::ClosureBinder::NotPresent => {} ast::ClosureBinder::For { generic_params, .. } => { - self.print_formal_generic_params(&generic_params) + self.print_formal_generic_params(generic_params) } } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index c52f15401ab..e68a7b3f202 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -663,7 +663,7 @@ impl<'a> State<'a> { fn print_use_tree(&mut self, tree: &ast::UseTree) { match &tree.kind { - ast::UseTreeKind::Simple(rename, ..) => { + ast::UseTreeKind::Simple(rename) => { self.print_path(&tree.prefix, false, 0); if let &Some(rename) = rename { self.nbsp(); diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 4a12e1b1b92..e379e647062 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -73,7 +73,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>( // Replace all remaining regions with fresh inference variables. renumber::renumber_mir(infcx, body, promoted); - dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(())); + dump_mir(infcx.tcx, false, "renumber", &0, body, |_, _| Ok(())); universal_regions } @@ -331,7 +331,7 @@ pub(super) fn dump_mir_results<'tcx>( return; } - dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| { + dump_mir(infcx.tcx, false, "nll", &0, body, |pass_where, out| { match pass_where { // Before the CFG, dump out the values for each region variable. PassWhere::BeforeCFG => { @@ -358,15 +358,13 @@ pub(super) fn dump_mir_results<'tcx>( // Also dump the inference graph constraints as a graphviz file. let _: io::Result<()> = try { - let mut file = - create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?; + let mut file = create_dump_file(infcx.tcx, "regioncx.all.dot", false, "nll", &0, body)?; regioncx.dump_graphviz_raw_constraints(&mut file)?; }; // Also dump the inference graph constraints as a graphviz file. let _: io::Result<()> = try { - let mut file = - create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?; + let mut file = create_dump_file(infcx.tcx, "regioncx.scc.dot", false, "nll", &0, body)?; regioncx.dump_graphviz_scc_constraints(&mut file)?; }; } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index bd415901ae3..d82bc0453f5 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -106,7 +106,7 @@ impl<'cx, 'a> Context<'cx, 'a> { ( UseTree { prefix: this.cx.path(this.span, vec![Ident::with_dummy_span(sym)]), - kind: UseTreeKind::Simple(None, DUMMY_NODE_ID, DUMMY_NODE_ID), + kind: UseTreeKind::Simple(None), span: this.span, }, DUMMY_NODE_ID, diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 1cbbfb43264..75cfac72384 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -45,6 +45,7 @@ mod log_syntax; mod source_util; mod test; mod trace_macros; +mod type_ascribe; mod util; pub mod asm; @@ -92,6 +93,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { unreachable: edition_panic::expand_unreachable, stringify: source_util::expand_stringify, trace_macros: trace_macros::expand_trace_macros, + type_ascribe: type_ascribe::expand_type_ascribe, } register_attr! { diff --git a/compiler/rustc_builtin_macros/src/type_ascribe.rs b/compiler/rustc_builtin_macros/src/type_ascribe.rs new file mode 100644 index 00000000000..72b85af1486 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/type_ascribe.rs @@ -0,0 +1,35 @@ +use rustc_ast::ptr::P; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{token, Expr, ExprKind, Ty}; +use rustc_errors::PResult; +use rustc_expand::base::{self, DummyResult, ExtCtxt, MacEager}; +use rustc_span::Span; + +pub fn expand_type_ascribe( + cx: &mut ExtCtxt<'_>, + span: Span, + tts: TokenStream, +) -> Box<dyn base::MacResult + 'static> { + let (expr, ty) = match parse_ascribe(cx, tts) { + Ok(parsed) => parsed, + Err(mut err) => { + err.emit(); + return DummyResult::any(span); + } + }; + + let asc_expr = cx.expr(span, ExprKind::Type(expr, ty)); + + return MacEager::expr(asc_expr); +} + +fn parse_ascribe<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Expr>, P<Ty>)> { + let mut parser = cx.new_parser_from_tts(stream); + + let expr = parser.parse_expr()?; + parser.expect(&token::Comma)?; + + let ty = parser.parse_ty()?; + + Ok((expr, ty)) +} diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 3fa9d56cd01..3b406036c35 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -20,11 +20,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142" [[package]] -name = "ar" -version = "0.8.0" -source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648" - -[[package]] name = "arrayvec" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -324,7 +319,6 @@ dependencies = [ name = "rustc_codegen_cranelift" version = "0.1.0" dependencies = [ - "ar", "cranelift-codegen", "cranelift-frontend", "cranelift-jit", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 09cf5b4a1ed..0fdd5de118c 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -18,7 +18,6 @@ target-lexicon = "0.12.0" gimli = { version = "0.26.0", default-features = false, features = ["write"]} object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } -ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.9.1" libloading = { version = "0.7.3", optional = true } once_cell = "1.10.0" diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index f2e3bf16e61..5a29bc18def 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -1,35 +1,15 @@ -//! Creation of ar archives like for the lib and staticlib crate type - -use std::collections::BTreeMap; -use std::fs::File; -use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; +use rustc_codegen_ssa::back::archive::{ + get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, +}; use rustc_session::Session; -use object::read::archive::ArchiveFile; -use object::{Object, ObjectSymbol, ReadCache}; - -#[derive(Debug)] -enum ArchiveEntry { - FromArchive { archive_index: usize, file_range: (u64, u64) }, - File(PathBuf), -} - pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> { - Box::new(ArArchiveBuilder { - sess, - use_gnu_style_archive: sess.target.archive_format == "gnu", - // FIXME fix builtin ranlib on macOS - no_builtin_ranlib: sess.target.is_like_osx, - - src_archives: vec![], - entries: vec![], - }) + Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) } fn create_dll_import_lib( @@ -40,200 +20,6 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { _tmpdir: &Path, _is_direct_dependency: bool, ) -> PathBuf { - bug!("creating dll imports is not supported"); - } -} - -pub(crate) struct ArArchiveBuilder<'a> { - sess: &'a Session, - use_gnu_style_archive: bool, - no_builtin_ranlib: bool, - - src_archives: Vec<File>, - // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at - // the end of an archive for linkers to not get confused. - entries: Vec<(Vec<u8>, ArchiveEntry)>, -} - -impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn add_file(&mut self, file: &Path) { - self.entries.push(( - file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), - ArchiveEntry::File(file.to_owned()), - )); - } - - fn add_archive( - &mut self, - archive_path: &Path, - mut skip: Box<dyn FnMut(&str) -> bool + 'static>, - ) -> std::io::Result<()> { - let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?); - let archive = ArchiveFile::parse(&read_cache).unwrap(); - let archive_index = self.src_archives.len(); - - for entry in archive.members() { - let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let file_name = String::from_utf8(entry.name().to_vec()) - .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - if !skip(&file_name) { - self.entries.push(( - file_name.into_bytes(), - ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, - )); - } - } - - self.src_archives.push(read_cache.into_inner()); - Ok(()) - } - - fn build(mut self: Box<Self>, output: &Path) -> bool { - enum BuilderKind { - Bsd(ar::Builder<File>), - Gnu(ar::GnuBuilder<File>), - } - - let sess = self.sess; - - let mut symbol_table = BTreeMap::new(); - - let mut entries = Vec::new(); - - for (mut entry_name, entry) in self.entries { - // FIXME only read the symbol table of the object files to avoid having to keep all - // object files in memory at once, or read them twice. - let data = match entry { - ArchiveEntry::FromArchive { archive_index, file_range } => { - // FIXME read symbols from symtab - let src_read_cache = &mut self.src_archives[archive_index]; - - src_read_cache.seek(io::SeekFrom::Start(file_range.0)).unwrap(); - let mut data = std::vec::from_elem(0, usize::try_from(file_range.1).unwrap()); - src_read_cache.read_exact(&mut data).unwrap(); - - data - } - ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| { - sess.fatal(&format!( - "error while reading object file during archive building: {}", - err - )); - }), - }; - - if !self.no_builtin_ranlib { - if symbol_table.contains_key(&entry_name) { - // The ar crate can't handle creating a symbol table in case of multiple archive - // members with the same name. Work around this by prepending a number until we - // get a unique name. - for i in 1.. { - let new_name = format!("{}_", i) - .into_bytes() - .into_iter() - .chain(entry_name.iter().copied()) - .collect::<Vec<_>>(); - if !symbol_table.contains_key(&new_name) { - entry_name = new_name; - break; - } - } - } - - match object::File::parse(&*data) { - Ok(object) => { - symbol_table.insert( - entry_name.to_vec(), - object - .symbols() - .filter_map(|symbol| { - if symbol.is_undefined() || symbol.is_local() { - None - } else { - symbol.name().map(|name| name.as_bytes().to_vec()).ok() - } - }) - .collect::<Vec<_>>(), - ); - } - Err(err) => { - let err = err.to_string(); - if err == "Unknown file magic" { - // Not an object file; skip it. - } else if object::read::archive::ArchiveFile::parse(&*data).is_ok() { - // Nested archive file; skip it. - } else { - sess.fatal(&format!( - "error parsing `{}` during archive creation: {}", - String::from_utf8_lossy(&entry_name), - err - )); - } - } - } - } - - entries.push((entry_name, data)); - } - - let mut builder = if self.use_gnu_style_archive { - BuilderKind::Gnu( - ar::GnuBuilder::new( - File::create(output).unwrap_or_else(|err| { - sess.fatal(&format!( - "error opening destination during archive building: {}", - err - )); - }), - entries.iter().map(|(name, _)| name.clone()).collect(), - ar::GnuSymbolTableFormat::Size32, - symbol_table, - ) - .unwrap(), - ) - } else { - BuilderKind::Bsd( - ar::Builder::new( - File::create(output).unwrap_or_else(|err| { - sess.fatal(&format!( - "error opening destination during archive building: {}", - err - )); - }), - symbol_table, - ) - .unwrap(), - ) - }; - - let any_members = !entries.is_empty(); - - // Add all files - for (entry_name, data) in entries.into_iter() { - let header = ar::Header::new(entry_name, data.len() as u64); - match builder { - BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(), - BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(), - } - } - - // Finalize archive - std::mem::drop(builder); - - if self.no_builtin_ranlib { - let ranlib = crate::toolchain::get_toolchain_binary(self.sess, "ranlib"); - - // Run ranlib to be able to link the archive - let status = std::process::Command::new(ranlib) - .arg(output) - .status() - .expect("Couldn't run ranlib"); - - if !status.success() { - self.sess.fatal(&format!("Ranlib exited with code {:?}", status.code())); - } - } - - any_members + unimplemented!("creating dll imports is not yet supported"); } } diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index 6df2102470f..1cb219e12e0 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -12,12 +12,6 @@ dependencies = [ ] [[package]] -name = "ar" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1" - -[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -212,10 +206,8 @@ dependencies = [ name = "rustc_codegen_gcc" version = "0.1.0" dependencies = [ - "ar", "gccjit", "lang_tester", - "target-lexicon", "tempfile", ] @@ -229,12 +221,6 @@ dependencies = [ ] [[package]] -name = "target-lexicon" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" - -[[package]] name = "tempfile" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml index 211d19a8dc8..1f3da2f799b 100644 --- a/compiler/rustc_codegen_gcc/Cargo.toml +++ b/compiler/rustc_codegen_gcc/Cargo.toml @@ -27,10 +27,6 @@ gccjit = { git = "https://github.com/antoyo/gccjit.rs" } # Local copy. #gccjit = { path = "../gccjit.rs" } -target-lexicon = "0.10.0" - -ar = "0.8.0" - [dev-dependencies] lang_tester = "0.3.9" tempfile = "3.1.0" diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index f18ae7ea5e9..11fa074f5ac 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -1,44 +1,17 @@ -use std::fs::File; use std::path::{Path, PathBuf}; -use crate::errors::RanlibFailure; - -use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; +use rustc_codegen_ssa::back::archive::{ + get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, +}; use rustc_session::Session; use rustc_session::cstore::DllImport; -struct ArchiveConfig<'a> { - sess: &'a Session, - use_native_ar: bool, - use_gnu_style_archive: bool, -} - -#[derive(Debug)] -enum ArchiveEntry { - FromArchive { - archive_index: usize, - entry_index: usize, - }, - File(PathBuf), -} - -pub struct ArArchiveBuilderBuilder; +pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> { - let config = ArchiveConfig { - sess, - use_native_ar: false, - // FIXME test for linux and System V derivatives instead - use_gnu_style_archive: sess.target.options.archive_format == "gnu", - }; - - Box::new(ArArchiveBuilder { - config, - src_archives: vec![], - entries: vec![], - }) + Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) } fn create_dll_import_lib( @@ -49,144 +22,6 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { _tmpdir: &Path, _is_direct_dependency: bool, ) -> PathBuf { - unimplemented!(); - } -} - -pub struct ArArchiveBuilder<'a> { - config: ArchiveConfig<'a>, - src_archives: Vec<(PathBuf, ar::Archive<File>)>, - // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at - // the end of an archive for linkers to not get confused. - entries: Vec<(String, ArchiveEntry)>, -} - -impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn add_file(&mut self, file: &Path) { - self.entries.push(( - file.file_name().unwrap().to_str().unwrap().to_string(), - ArchiveEntry::File(file.to_owned()), - )); - } - - fn add_archive( - &mut self, - archive_path: &Path, - mut skip: Box<dyn FnMut(&str) -> bool + 'static>, - ) -> std::io::Result<()> { - let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?); - let archive_index = self.src_archives.len(); - - let mut i = 0; - while let Some(entry) = archive.next_entry() { - let entry = entry?; - let file_name = String::from_utf8(entry.header().identifier().to_vec()) - .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?; - if !skip(&file_name) { - self.entries - .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i })); - } - i += 1; - } - - self.src_archives.push((archive_path.to_owned(), archive)); - Ok(()) - } - - fn build(mut self: Box<Self>, output: &Path) -> bool { - use std::process::Command; - - fn add_file_using_ar(archive: &Path, file: &Path) { - Command::new("ar") - .arg("r") // add or replace file - .arg("-c") // silence created file message - .arg(archive) - .arg(&file) - .status() - .unwrap(); - } - - enum BuilderKind<'a> { - Bsd(ar::Builder<File>), - Gnu(ar::GnuBuilder<File>), - NativeAr(&'a Path), - } - - let mut builder = if self.config.use_native_ar { - BuilderKind::NativeAr(output) - } else if self.config.use_gnu_style_archive { - BuilderKind::Gnu(ar::GnuBuilder::new( - File::create(output).unwrap(), - self.entries - .iter() - .map(|(name, _)| name.as_bytes().to_vec()) - .collect(), - )) - } else { - BuilderKind::Bsd(ar::Builder::new(File::create(output).unwrap())) - }; - - let any_members = !self.entries.is_empty(); - - // Add all files - for (entry_name, entry) in self.entries.into_iter() { - match entry { - ArchiveEntry::FromArchive { - archive_index, - entry_index, - } => { - let (ref src_archive_path, ref mut src_archive) = - self.src_archives[archive_index]; - let entry = src_archive.jump_to_entry(entry_index).unwrap(); - let header = entry.header().clone(); - - match builder { - BuilderKind::Bsd(ref mut builder) => { - builder.append(&header, entry).unwrap() - } - BuilderKind::Gnu(ref mut builder) => { - builder.append(&header, entry).unwrap() - } - BuilderKind::NativeAr(archive_file) => { - Command::new("ar") - .arg("x") - .arg(src_archive_path) - .arg(&entry_name) - .status() - .unwrap(); - add_file_using_ar(archive_file, Path::new(&entry_name)); - std::fs::remove_file(entry_name).unwrap(); - } - } - } - ArchiveEntry::File(file) => - match builder { - BuilderKind::Bsd(ref mut builder) => { - builder - .append_file(entry_name.as_bytes(), &mut File::open(file).expect("file for bsd builder")) - .unwrap() - }, - BuilderKind::Gnu(ref mut builder) => { - builder - .append_file(entry_name.as_bytes(), &mut File::open(&file).expect(&format!("file {:?} for gnu builder", file))) - .unwrap() - }, - BuilderKind::NativeAr(archive_file) => add_file_using_ar(archive_file, &file), - }, - } - } - - // Finalize archive - std::mem::drop(builder); - - // Run ranlib to be able to link the archive - let status = - std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib"); - - if !status.success() { - self.config.sess.emit_fatal(RanlibFailure::new(status.code())); - } - - any_members + unimplemented!("creating dll imports is not yet supported"); } } diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 15ad90f9043..89fed7be131 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -17,18 +17,6 @@ impl IntoDiagnosticArg for ExitCode { } #[derive(Diagnostic)] -#[diag(codegen_gcc_ranlib_failure)] -pub(crate) struct RanlibFailure { - exit_code: ExitCode, -} - -impl RanlibFailure { - pub fn new(exit_code: Option<i32>) -> Self { - RanlibFailure { exit_code: ExitCode(exit_code) } - } -} - -#[derive(Diagnostic)] #[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")] pub(crate) struct InvalidMonomorphizationBasicInteger<'a> { #[primary_span] @@ -227,7 +215,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { #[diag(codegen_gcc_linkage_const_or_mut_type)] pub(crate) struct LinkageConstOrMutType { #[primary_span] - pub span: Span + pub span: Span, } #[derive(Diagnostic)] @@ -238,5 +226,5 @@ pub(crate) struct LTONotSupported; #[diag(codegen_gcc_unwinding_inline_asm)] pub(crate) struct UnwindingInlineAsm { #[primary_span] - pub span: Span + pub span: Span, } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 0ad39c24025..93d6234dc88 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,7 @@ bitflags = "1.0" cstr = "0.2" libc = "0.2" measureme = "10.0.0" -object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.29.0", default-features = false, features = ["std", "read"] } tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc-demangle = "0.1.21" diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index a8b47633519..f3bdacf6085 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -258,13 +258,12 @@ pub fn from_fn_attrs<'ll, 'tcx>( OptimizeAttr::Speed => {} } - let inline = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { - InlineAttr::Never - } else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) { - InlineAttr::Hint - } else { - codegen_fn_attrs.inline - }; + let inline = + if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) { + InlineAttr::Hint + } else { + codegen_fn_attrs.inline + }; to_add.extend(inline_attr(cx, inline)); // The `uwtable` attribute according to LLVM is: diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 5c68abeb08b..0aee1a1439b 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -1,31 +1,30 @@ //! A helper class for dealing with static archives use std::env; -use std::ffi::{CStr, CString, OsString}; -use std::fs; -use std::io::{self, Write}; +use std::ffi::{c_char, c_void, CStr, CString, OsString}; +use std::io; use std::mem; use std::path::{Path, PathBuf}; use std::ptr; use std::str; -use object::read::macho::FatArch; - use crate::common; use crate::errors::{ - ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, - ErrorWritingDEFFile, UnknownArchiveKind, + DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, }; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; -use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; -use rustc_data_structures::memmap::Mmap; +use rustc_codegen_ssa::back::archive::{ + get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder, + ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind, +}; + use rustc_session::cstore::DllImport; use rustc_session::Session; /// Helper for adding many files to an archive. #[must_use = "must call build() to finish building the archive"] -pub struct LlvmArchiveBuilder<'a> { +pub(crate) struct LlvmArchiveBuilder<'a> { sess: &'a Session, additions: Vec<Addition>, } @@ -61,57 +60,6 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType { } } -fn try_filter_fat_archs( - archs: object::read::Result<&[impl FatArch]>, - target_arch: object::Architecture, - archive_path: &Path, - archive_map_data: &[u8], -) -> io::Result<Option<PathBuf>> { - let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - - let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() { - Some(a) => a, - None => return Ok(None), - }; - - let (mut new_f, extracted_path) = tempfile::Builder::new() - .suffix(archive_path.file_name().unwrap()) - .tempfile()? - .keep() - .unwrap(); - - new_f.write_all( - desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, - )?; - - Ok(Some(extracted_path)) -} - -fn try_extract_macho_fat_archive( - sess: &Session, - archive_path: &Path, -) -> io::Result<Option<PathBuf>> { - let archive_map = unsafe { Mmap::map(fs::File::open(&archive_path)?)? }; - let target_arch = match sess.target.arch.as_ref() { - "aarch64" => object::Architecture::Aarch64, - "x86_64" => object::Architecture::X86_64, - _ => return Ok(None), - }; - - match object::macho::FatHeader::parse(&*archive_map) { - Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => { - let archs = object::macho::FatHeader::parse_arch32(&*archive_map); - try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) - } - Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => { - let archs = object::macho::FatHeader::parse_arch64(&*archive_map); - try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) - } - // Not a FatHeader at all, just return None. - _ => Ok(None), - } -} - impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { fn add_archive( &mut self, @@ -160,7 +108,11 @@ pub struct LlvmArchiveBuilderBuilder; impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> { - Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) + if sess.target.arch == "wasm32" || sess.target.arch == "wasm64" { + Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) + } else { + Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols)) + } } fn create_dll_import_lib( @@ -309,6 +261,61 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { } } +// The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files. +// As such we need to use LLVM for them. +#[deny(unsafe_op_in_unsafe_fn)] +fn get_llvm_object_symbols( + buf: &[u8], + f: &mut dyn FnMut(&[u8]) -> io::Result<()>, +) -> io::Result<bool> { + let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) }; + + // COFF bigobj file, msvc LTO file or import library. See + // https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51 + let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF"); + + if is_bitcode || is_unsupported_windows_obj_file { + let mut state = Box::new(f); + + let err = unsafe { + llvm::LLVMRustGetSymbols( + buf.as_ptr(), + buf.len(), + &mut *state as *mut &mut _ as *mut c_void, + callback, + error_callback, + ) + }; + + if err.is_null() { + return Ok(true); + } else { + return Err(unsafe { *Box::from_raw(err as *mut io::Error) }); + } + + unsafe extern "C" fn callback( + state: *mut c_void, + symbol_name: *const c_char, + ) -> *mut c_void { + let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) }; + match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) { + Ok(()) => std::ptr::null_mut(), + Err(err) => Box::into_raw(Box::new(err)) as *mut c_void, + } + } + + unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void { + let error = unsafe { CStr::from_ptr(error) }; + Box::into_raw(Box::new(io::Error::new( + io::ErrorKind::Other, + format!("LLVM error: {}", error.to_string_lossy()), + ))) as *mut c_void + } + } else { + get_native_object_symbols(buf, f) + } +} + impl<'a> LlvmArchiveBuilder<'a> { fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> { let kind = &*self.sess.target.archive_format; diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 0fafc214f2f..fddfbb23c67 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -73,12 +73,6 @@ pub(crate) struct LinkageConstOrMutType { pub(crate) struct SanitizerMemtagRequiresMte; #[derive(Diagnostic)] -#[diag(codegen_llvm_archive_build_failure)] -pub(crate) struct ArchiveBuildFailure { - pub error: std::io::Error, -} - -#[derive(Diagnostic)] #[diag(codegen_llvm_error_writing_def_file)] pub(crate) struct ErrorWritingDEFFile { pub error: std::io::Error, @@ -98,12 +92,6 @@ pub(crate) struct DlltoolFailImportLibrary<'a> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_unknown_archive_kind)] -pub(crate) struct UnknownArchiveKind<'a> { - pub kind: &'a str, -} - -#[derive(Diagnostic)] #[diag(codegen_llvm_dynamic_linking_with_lto)] #[note] pub(crate) struct DynamicLinkingWithLTO; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index c14e1656291..8a9392255b8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -983,6 +983,9 @@ pub type SelfProfileBeforePassCallback = unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char); pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); +pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; +pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; + extern "C" { pub fn LLVMRustInstallFatalErrorHandler(); pub fn LLVMRustDisableSystemDialogsOnCrash(); @@ -2474,4 +2477,14 @@ extern "C" { pub fn LLVMRustGetMangledName(V: &Value, out: &RustString); pub fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32; + + pub fn LLVMRustIsBitcode(ptr: *const u8, len: usize) -> bool; + + pub fn LLVMRustGetSymbols( + buf_ptr: *const u8, + buf_len: usize, + state: *mut c_void, + callback: GetSymbolsCallback, + error_callback: GetSymbolsErrorCallback, + ) -> *mut c_void; } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index c9f5dd0f2c6..2fa602520dc 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -494,6 +494,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str .flatten(); features.extend(feats); + // FIXME: Move v8a to target definition list when earliest supported LLVM is 14. + if get_version() >= (14, 0, 0) && sess.target.arch == "aarch64" { + features.push("+v8a".into()); + } + if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { sess.emit_err(TargetFeatureDisableOrEnable { features: f, diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index d868e3d56ba..345174fb595 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" test = false [dependencies] +ar_archive_writer = "0.1.1" bitflags = "1.2.1" cc = "1.0.69" itertools = "0.10.1" diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 2b1b06d1644..58558fb8c4b 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -6,14 +6,19 @@ use rustc_span::symbol::Symbol; use super::metadata::search_for_section; +pub use ar_archive_writer::get_native_object_symbols; +use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember}; use object::read::archive::ArchiveFile; +use object::read::macho::FatArch; +use tempfile::Builder as TempFileBuilder; use std::error::Error; use std::fs::File; -use std::io; +use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use crate::errors::ExtractBundledLibsError; +// Re-exporting for rustc_codegen_llvm::back::archive +pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind}; pub trait ArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>; @@ -80,3 +85,225 @@ pub trait ArchiveBuilder<'a> { fn build(self: Box<Self>, output: &Path) -> bool; } + +#[must_use = "must call build() to finish building the archive"] +pub struct ArArchiveBuilder<'a> { + sess: &'a Session, + get_object_symbols: + fn(buf: &[u8], f: &mut dyn FnMut(&[u8]) -> io::Result<()>) -> io::Result<bool>, + + src_archives: Vec<(PathBuf, Mmap)>, + // Don't use an `HashMap` here, as the order is important. `lib.rmeta` needs + // to be at the end of an archive in some cases for linkers to not get confused. + entries: Vec<(Vec<u8>, ArchiveEntry)>, +} + +#[derive(Debug)] +enum ArchiveEntry { + FromArchive { archive_index: usize, file_range: (u64, u64) }, + File(PathBuf), +} + +impl<'a> ArArchiveBuilder<'a> { + pub fn new( + sess: &'a Session, + get_object_symbols: fn( + buf: &[u8], + f: &mut dyn FnMut(&[u8]) -> io::Result<()>, + ) -> io::Result<bool>, + ) -> ArArchiveBuilder<'a> { + ArArchiveBuilder { sess, get_object_symbols, src_archives: vec![], entries: vec![] } + } +} + +fn try_filter_fat_archs( + archs: object::read::Result<&[impl FatArch]>, + target_arch: object::Architecture, + archive_path: &Path, + archive_map_data: &[u8], +) -> io::Result<Option<PathBuf>> { + let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + + let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() { + Some(a) => a, + None => return Ok(None), + }; + + let (mut new_f, extracted_path) = tempfile::Builder::new() + .suffix(archive_path.file_name().unwrap()) + .tempfile()? + .keep() + .unwrap(); + + new_f.write_all( + desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, + )?; + + Ok(Some(extracted_path)) +} + +pub fn try_extract_macho_fat_archive( + sess: &Session, + archive_path: &Path, +) -> io::Result<Option<PathBuf>> { + let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; + let target_arch = match sess.target.arch.as_ref() { + "aarch64" => object::Architecture::Aarch64, + "x86_64" => object::Architecture::X86_64, + _ => return Ok(None), + }; + + match object::macho::FatHeader::parse(&*archive_map) { + Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => { + let archs = object::macho::FatHeader::parse_arch32(&*archive_map); + try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) + } + Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => { + let archs = object::macho::FatHeader::parse_arch64(&*archive_map); + try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) + } + // Not a FatHeader at all, just return None. + _ => Ok(None), + } +} + +impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { + fn add_archive( + &mut self, + archive_path: &Path, + mut skip: Box<dyn FnMut(&str) -> bool + 'static>, + ) -> io::Result<()> { + let mut archive_path = archive_path.to_path_buf(); + if self.sess.target.llvm_target.contains("-apple-macosx") { + if let Some(new_archive_path) = + try_extract_macho_fat_archive(&self.sess, &archive_path)? + { + archive_path = new_archive_path + } + } + + if self.src_archives.iter().any(|archive| archive.0 == archive_path) { + return Ok(()); + } + + let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; + let archive = ArchiveFile::parse(&*archive_map) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + let archive_index = self.src_archives.len(); + + for entry in archive.members() { + let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + let file_name = String::from_utf8(entry.name().to_vec()) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + if !skip(&file_name) { + self.entries.push(( + file_name.into_bytes(), + ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, + )); + } + } + + self.src_archives.push((archive_path.to_owned(), archive_map)); + Ok(()) + } + + /// Adds an arbitrary file to this archive + fn add_file(&mut self, file: &Path) { + self.entries.push(( + file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), + ArchiveEntry::File(file.to_owned()), + )); + } + + /// Combine the provided files, rlibs, and native libraries into a single + /// `Archive`. + fn build(self: Box<Self>, output: &Path) -> bool { + let sess = self.sess; + match self.build_inner(output) { + Ok(any_members) => any_members, + Err(e) => sess.emit_fatal(ArchiveBuildFailure { error: e }), + } + } +} + +impl<'a> ArArchiveBuilder<'a> { + fn build_inner(self, output: &Path) -> io::Result<bool> { + let archive_kind = match &*self.sess.target.archive_format { + "gnu" => ArchiveKind::Gnu, + "bsd" => ArchiveKind::Bsd, + "darwin" => ArchiveKind::Darwin, + "coff" => ArchiveKind::Coff, + kind => { + self.sess.emit_fatal(UnknownArchiveKind { kind }); + } + }; + + let mut entries = Vec::new(); + + for (entry_name, entry) in self.entries { + let data = + match entry { + ArchiveEntry::FromArchive { archive_index, file_range } => { + let src_archive = &self.src_archives[archive_index]; + + let data = &src_archive.1 + [file_range.0 as usize..file_range.0 as usize + file_range.1 as usize]; + + Box::new(data) as Box<dyn AsRef<[u8]>> + } + ArchiveEntry::File(file) => unsafe { + Box::new( + Mmap::map(File::open(file).map_err(|err| { + io_error_context("failed to open object file", err) + })?) + .map_err(|err| io_error_context("failed to map object file", err))?, + ) as Box<dyn AsRef<[u8]>> + }, + }; + + entries.push(NewArchiveMember { + buf: data, + get_symbols: self.get_object_symbols, + member_name: String::from_utf8(entry_name).unwrap(), + mtime: 0, + uid: 0, + gid: 0, + perms: 0o644, + }) + } + + // Write to a temporary file first before atomically renaming to the final name. + // This prevents programs (including rustc) from attempting to read a partial archive. + // It also enables writing an archive with the same filename as a dependency on Windows as + // required by a test. + let mut archive_tmpfile = TempFileBuilder::new() + .suffix(".temp-archive") + .tempfile_in(output.parent().unwrap_or_else(|| Path::new(""))) + .map_err(|err| io_error_context("couldn't create a temp file", err))?; + + write_archive_to_stream( + archive_tmpfile.as_file_mut(), + &entries, + true, + archive_kind, + true, + false, + )?; + + let any_entries = !entries.is_empty(); + drop(entries); + // Drop src_archives to unmap all input archives, which is necessary if we want to write the + // output archive to the same location as an input archive on Windows. + drop(self.src_archives); + + archive_tmpfile + .persist(output) + .map_err(|err| io_error_context("failed to rename archive file", err.error))?; + + Ok(any_entries) + } +} + +fn io_error_context(context: &str, err: io::Error) -> io::Error { + io::Error::new(io::ErrorKind::Other, format!("{context}: {err}")) +} diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index ade50af0aee..e3b6fbf1bc7 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -534,3 +534,17 @@ pub struct ReadFileError { #[derive(Diagnostic)] #[diag(codegen_ssa_unsupported_link_self_contained)] pub struct UnsupportedLinkSelfContained; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_archive_build_failure)] +// Public for rustc_codegen_llvm::back::archive +pub struct ArchiveBuildFailure { + pub error: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unknown_archive_kind)] +// Public for rustc_codegen_llvm::back::archive +pub struct UnknownArchiveKind<'a> { + pub kind: &'a str, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 90855538589..fbe30154a7c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -309,14 +309,14 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // In the algorithm above, we can change // cast(relative_tag) + niche_variants.start() // into - // cast(tag) + (niche_variants.start() - niche_start) + // cast(tag + (niche_variants.start() - niche_start)) // if either the casted type is no larger than the original // type, or if the niche values are contiguous (in either the // signed or unsigned sense). - let can_incr_after_cast = cast_smaller || niches_ule || niches_sle; + let can_incr = cast_smaller || niches_ule || niches_sle; let data_for_boundary_niche = || -> Option<(IntPredicate, u128)> { - if !can_incr_after_cast { + if !can_incr { None } else if niche_start == low_unsigned { Some((IntPredicate::IntULE, niche_end)) @@ -353,24 +353,33 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // The algorithm is now this: // is_niche = tag <= niche_end // discr = if is_niche { - // cast(tag) + (niche_variants.start() - niche_start) + // cast(tag + (niche_variants.start() - niche_start)) // } else { // untagged_variant // } // (the first line may instead be tag >= niche_start, // and may be a signed or unsigned comparison) + // The arithmetic must be done before the cast, so we can + // have the correct wrapping behavior. See issue #104519 for + // the consequences of getting this wrong. let is_niche = bx.icmp(predicate, tag, bx.cx().const_uint_big(tag_llty, constant)); + let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start); + let incr_tag = if delta == 0 { + tag + } else { + bx.add(tag, bx.cx().const_uint_big(tag_llty, delta)) + }; + let cast_tag = if cast_smaller { - bx.intcast(tag, cast_to, false) + bx.intcast(incr_tag, cast_to, false) } else if niches_ule { - bx.zext(tag, cast_to) + bx.zext(incr_tag, cast_to) } else { - bx.sext(tag, cast_to) + bx.sext(incr_tag, cast_to) }; - let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start); - (is_niche, cast_tag, delta) + (is_niche, cast_tag, 0) } else { // The special cases don't apply, so we'll have to go with // the general algorithm. diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index f48bcd90809..6777fae74f1 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -318,14 +318,14 @@ impl<'tcx> Validator<'_, 'tcx> { match elem { ProjectionElem::Deref => { let mut promotable = false; + // When a static is used by-value, that gets desugared to `*STATIC_ADDR`, + // and we need to be able to promote this. So check if this deref matches + // that specific pattern. + // We need to make sure this is a `Deref` of a local with no further projections. // Discussion can be found at // https://github.com/rust-lang/rust/pull/74945#discussion_r463063247 if let Some(local) = place_base.as_local() { - // This is a special treatment for cases like *&STATIC where STATIC is a - // global static variable. - // This pattern is generated only when global static variables are directly - // accessed and is qualified for promotion safely. if let TempState::Defined { location, .. } = self.temps[local] { let def_stmt = self.body[location.block] .statements diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 11cbff8ea6a..76a1288e6d3 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -72,7 +72,7 @@ impl<'a, T: PartialOrd> PartialOrd for Interned<'a, T> { if ptr::eq(self.0, other.0) { Some(Ordering::Equal) } else { - let res = self.0.partial_cmp(&other.0); + let res = self.0.partial_cmp(other.0); debug_assert_ne!(res, Some(Ordering::Equal)); res } @@ -86,7 +86,7 @@ impl<'a, T: Ord> Ord for Interned<'a, T> { if ptr::eq(self.0, other.0) { Ordering::Equal } else { - let res = self.0.cmp(&other.0); + let res = self.0.cmp(other.0); debug_assert_ne!(res, Ordering::Equal); res } diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs index 917416df6b8..3d44e17f31d 100644 --- a/compiler/rustc_data_structures/src/memmap.rs +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -36,6 +36,12 @@ impl Deref for Mmap { #[inline] fn deref(&self) -> &[u8] { + &self.0 + } +} + +impl AsRef<[u8]> for Mmap { + fn as_ref(&self) -> &[u8] { &*self.0 } } @@ -96,13 +102,13 @@ impl Deref for MmapMut { #[inline] fn deref(&self) -> &[u8] { - &*self.0 + &self.0 } } impl DerefMut for MmapMut { #[inline] fn deref_mut(&mut self) -> &mut [u8] { - &mut *self.0 + &mut self.0 } } diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs index ed5e566184f..980a540ccba 100644 --- a/compiler/rustc_data_structures/src/owning_ref/mod.rs +++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs @@ -899,25 +899,25 @@ unsafe impl<O, T: ?Sized> StableAddress for OwningRef<O, T> {} impl<O, T: ?Sized> AsRef<T> for OwningRef<O, T> { fn as_ref(&self) -> &T { - &*self + self } } impl<O, T: ?Sized> AsRef<T> for OwningRefMut<O, T> { fn as_ref(&self) -> &T { - &*self + self } } impl<O, T: ?Sized> AsMut<T> for OwningRefMut<O, T> { fn as_mut(&mut self) -> &mut T { - &mut *self + self } } impl<O, T: ?Sized> Borrow<T> for OwningRef<O, T> { fn borrow(&self) -> &T { - &*self + self } } @@ -1021,7 +1021,7 @@ where T: PartialEq, { fn eq(&self, other: &Self) -> bool { - (&*self as &T).eq(&*other as &T) + self.deref().eq(other.deref()) } } @@ -1032,7 +1032,7 @@ where T: PartialOrd, { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - (&*self as &T).partial_cmp(&*other as &T) + self.deref().partial_cmp(other.deref()) } } @@ -1041,7 +1041,7 @@ where T: Ord, { fn cmp(&self, other: &Self) -> Ordering { - (&*self as &T).cmp(&*other as &T) + self.deref().cmp(other.deref()) } } @@ -1050,7 +1050,7 @@ where T: Hash, { fn hash<H: Hasher>(&self, state: &mut H) { - (&*self as &T).hash(state); + self.deref().hash(state); } } @@ -1059,7 +1059,7 @@ where T: PartialEq, { fn eq(&self, other: &Self) -> bool { - (&*self as &T).eq(&*other as &T) + self.deref().eq(other.deref()) } } @@ -1070,7 +1070,7 @@ where T: PartialOrd, { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - (&*self as &T).partial_cmp(&*other as &T) + self.deref().partial_cmp(other.deref()) } } @@ -1079,7 +1079,7 @@ where T: Ord, { fn cmp(&self, other: &Self) -> Ordering { - (&*self as &T).cmp(&*other as &T) + self.deref().cmp(other.deref()) } } @@ -1088,7 +1088,7 @@ where T: Hash, { fn hash<H: Hasher>(&self, state: &mut H) { - (&*self as &T).hash(state); + self.deref().hash(state); } } diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index ba1960805d8..aa7a01eed15 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -192,7 +192,7 @@ impl SelfProfilerRef { F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>, { let profiler = profiler_ref.profiler.as_ref().unwrap(); - f(&**profiler) + f(profiler) } if self.event_filter_mask.contains(event_filter) { @@ -466,7 +466,7 @@ impl SelfProfilerRef { pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) { if let Some(profiler) = &self.profiler { - f(&profiler) + f(profiler) } } @@ -733,7 +733,7 @@ impl Drop for VerboseTimingGuard<'_> { if let Some((start_time, start_rss, ref message)) = self.start_and_message { let end_rss = get_resident_set_size(); let dur = start_time.elapsed(); - print_time_passes_entry(&message, dur, start_rss, end_rss); + print_time_passes_entry(message, dur, start_rss, end_rss); } } } diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index ce859173418..cd392a7b678 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -366,7 +366,7 @@ impl<CTX> HashStable<CTX> for [u8] { impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> { #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (&self[..]).hash_stable(ctx, hasher); + self[..].hash_stable(ctx, hasher); } } @@ -399,13 +399,13 @@ where } } -impl<A, CTX> HashStable<CTX> for SmallVec<[A; 1]> +impl<A, const N: usize, CTX> HashStable<CTX> for SmallVec<[A; N]> where A: HashStable<CTX>, { #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (&self[..]).hash_stable(ctx, hasher); + self[..].hash_stable(ctx, hasher); } } @@ -440,7 +440,7 @@ impl<CTX> HashStable<CTX> for str { impl<CTX> HashStable<CTX> for String { #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - (&self[..]).hash_stable(hcx, hasher); + self[..].hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index c550f246e09..e4f47b22ac3 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -201,7 +201,7 @@ cfg_if! { #[inline(always)] fn deref(&self) -> &T { - &*self.0 + &self.0 } } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 380fbd732d5..22f87514dd8 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -245,10 +245,8 @@ fn run_compiler( interface::run_compiler(config, |compiler| { let sopts = &compiler.session().opts; if sopts.describe_lints { - let mut lint_store = rustc_lint::new_lint_store( - sopts.unstable_opts.no_interleave_lints, - compiler.session().enable_internal_lints(), - ); + let mut lint_store = + rustc_lint::new_lint_store(compiler.session().enable_internal_lints()); let registered_lints = if let Some(register_lints) = compiler.register_lints() { register_lints(compiler.session(), &mut lint_store); diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index 178e1a67cce..a1b7afeb709 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -1,6 +1,3 @@ -codegen_gcc_ranlib_failure = - Ranlib exited with code {$exit_code} - codegen_gcc_linkage_const_or_mut_type = must have type `*const T` or `*mut T` due to `#[linkage]` attribute diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 68a205df6c7..e273476b60b 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -29,9 +29,6 @@ codegen_llvm_linkage_const_or_mut_type = codegen_llvm_sanitizer_memtag_requires_mte = `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` -codegen_llvm_archive_build_failure = - failed to build archive: {$error} - codegen_llvm_error_writing_def_file = Error writing .DEF file: {$error} @@ -41,9 +38,6 @@ codegen_llvm_error_calling_dlltool = codegen_llvm_dlltool_fail_import_library = Dlltool could not create import library: {$stdout}\n{$stderr} -codegen_llvm_unknown_archive_kind = - Don't know how to build archive of type: {$kind} - codegen_llvm_target_feature_disable_or_enable = the target features {$features} must all be either enabled or disabled together diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 70ce559526c..4d1f9c1c901 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -186,3 +186,9 @@ codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {erro codegen_ssa_read_file = failed to read file: {message} codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target + +codegen_ssa_archive_build_failure = + failed to build archive: {$error} + +codegen_ssa_unknown_archive_kind = + Don't know how to build archive of type: {$kind} diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index c450c276366..d8879bf70ed 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -39,7 +39,7 @@ impl Translate for AnnotateSnippetEmitterWriter { } fn fallback_fluent_bundle(&self) -> &FluentBundle { - &**self.fallback_bundle + &self.fallback_bundle } } @@ -49,7 +49,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { let fluent_args = to_fluent_args(diag.args()); let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args); + let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( &mut primary_span, @@ -65,7 +65,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { &diag.code, &primary_span, &children, - &suggestions, + suggestions, ); } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 7d5e4723a6d..06bb5edc090 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -292,7 +292,7 @@ impl Diagnostic { let lint_index = expectation_id.get_lint_index(); expectation_id.set_lint_index(None); let mut stable_id = unstable_to_stable - .get(&expectation_id) + .get(expectation_id) .expect("each unstable `LintExpectationId` must have a matching stable id") .normalize(); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 1fabe15ff83..db595df8ec1 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -283,7 +283,7 @@ pub trait Emitter: Translate { if self .source_map() .map(|sm| is_case_difference( - &**sm, + sm, substitution, sugg.substitutions[0].parts[0].span, )) @@ -525,7 +525,7 @@ impl Translate for EmitterWriter { } fn fallback_fluent_bundle(&self) -> &FluentBundle { - &**self.fallback_bundle + &self.fallback_bundle } } @@ -538,7 +538,7 @@ impl Emitter for EmitterWriter { let fluent_args = to_fluent_args(diag.args()); let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args); + let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); debug!("emit_diagnostic: suggestions={:?}", suggestions); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( @@ -555,7 +555,7 @@ impl Emitter for EmitterWriter { &diag.code, &primary_span, &children, - &suggestions, + suggestions, self.track_diagnostics.then_some(&diag.emitted_at), ); } @@ -801,7 +801,7 @@ impl EmitterWriter { } let source_string = match file.get_line(line.line_index - 1) { - Some(s) => normalize_whitespace(&*s), + Some(s) => normalize_whitespace(&s), None => return Vec::new(), }; @@ -1148,7 +1148,7 @@ impl EmitterWriter { (pos + 2, annotation.start_col.saturating_sub(left)) }; if let Some(ref label) = annotation.label { - buffer.puts(line_offset + pos, code_offset + col, &label, style); + buffer.puts(line_offset + pos, code_offset + col, label, style); } } @@ -1358,7 +1358,7 @@ impl EmitterWriter { // only render error codes, not lint codes if let Some(DiagnosticId::Error(ref code)) = *code { buffer.append(0, "[", Style::Level(*level)); - buffer.append(0, &code, Style::Level(*level)); + buffer.append(0, code, Style::Level(*level)); buffer.append(0, "]", Style::Level(*level)); label_width += 2 + code.len(); } @@ -1683,7 +1683,7 @@ impl EmitterWriter { }; // Render the replacements for each suggestion - let suggestions = suggestion.splice_lines(&**sm); + let suggestions = suggestion.splice_lines(sm); debug!("emit_suggestion_default: suggestions={:?}", suggestions); if suggestions.is_empty() { @@ -1784,7 +1784,7 @@ impl EmitterWriter { buffer.puts( row_num - 1 + line - line_start, max_line_num_len + 3, - &normalize_whitespace(&*file_lines.file.get_line(line - 1).unwrap()), + &normalize_whitespace(&file_lines.file.get_line(line - 1).unwrap()), Style::Removal, ); } @@ -1926,7 +1926,7 @@ impl EmitterWriter { buffer.putc( row_num, (padding as isize + p) as usize, - if part.is_addition(&sm) { '+' } else { '~' }, + if part.is_addition(sm) { '+' } else { '~' }, Style::Addition, ); } @@ -1973,7 +1973,7 @@ impl EmitterWriter { buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle); } else if notice_capitalization { let msg = "notice the capitalization difference"; - buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle); + buffer.puts(row_num, max_line_num_len + 3, msg, Style::NoStyle); } emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; Ok(()) @@ -2028,7 +2028,7 @@ impl EmitterWriter { for child in children { let span = child.render_span.as_ref().unwrap_or(&child.span); if let Err(err) = self.emit_message_default( - &span, + span, &child.message, args, &None, @@ -2113,7 +2113,7 @@ impl EmitterWriter { *row_num - 1, max_line_num_len + 3, &normalize_whitespace( - &*file_lines.file.get_line(file_lines.lines[line_pos].line_index).unwrap(), + &file_lines.file.get_line(file_lines.lines[line_pos].line_index).unwrap(), ), Style::NoStyle, ); diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index c4498eafa4e..a37073d8fa3 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -136,7 +136,7 @@ impl Translate for JsonEmitter { } fn fallback_fluent_bundle(&self) -> &FluentBundle { - &**self.fallback_bundle + &self.fallback_bundle } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2be36a6eeb4..eb0506c459a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -470,6 +470,7 @@ pub enum StashKey { /// Maybe there was a typo where a comma was forgotten before /// FRU syntax MaybeFruTypo, + CallAssocMethod, } fn default_track_diagnostic(_: &Diagnostic) {} @@ -1328,7 +1329,7 @@ impl HandlerInner { diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {}); - self.emitter.emit_diagnostic(&diagnostic); + self.emitter.emit_diagnostic(diagnostic); if diagnostic.is_error() { self.deduplicated_err_count += 1; } else if let Warning(_) = diagnostic.level { diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index a452fac0747..afd660ff1bf 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -59,13 +59,13 @@ pub trait Translate { trace!(?message, ?args); let (identifier, attr) = match message { DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => { - return Cow::Borrowed(&msg); + return Cow::Borrowed(msg); } DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), }; let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> { - let message = bundle.get_message(&identifier)?; + let message = bundle.get_message(identifier)?; let value = match attr { Some(attr) => message.get_attribute(attr)?.value(), None => message.value()?, @@ -73,7 +73,7 @@ pub trait Translate { debug!(?message, ?value); let mut errs = vec![]; - let translated = bundle.format_pattern(value, Some(&args), &mut errs); + let translated = bundle.format_pattern(value, Some(args), &mut errs); debug!(?translated, ?errs); Some((translated, errs)) }; diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index c978297295d..4812bdd9dd8 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -539,6 +539,9 @@ impl<'a> ExtCtxt<'a> { fn_decl, body, fn_decl_span: span, + // FIXME(SarthakSingh31): This points to the start of the declaration block and + // not the span of the argument block. + fn_arg_span: span, })), ) } diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 63998bb6b00..a7dfce3b9b8 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -65,7 +65,7 @@ pub enum LinkOrCopy { pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> { let p = p.as_ref(); let q = q.as_ref(); - match fs::remove_file(&q) { + match fs::remove_file(q) { Ok(()) => (), Err(err) if err.kind() == io::ErrorKind::NotFound => (), Err(err) => return Err(err), diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 401d3f6689c..1f8268cc17c 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -410,7 +410,7 @@ impl<'a> Id<'a> { } pub fn as_slice(&'a self) -> &'a str { - &*self.name + &self.name } } @@ -515,7 +515,7 @@ impl<'a> LabelText<'a> { pub fn to_dot_string(&self) -> String { match *self { LabelStr(ref s) => format!("\"{}\"", s.escape_default()), - EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s)), + EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(s)), HtmlStr(ref s) => format!("<{}>", s), } } @@ -529,7 +529,7 @@ impl<'a> LabelText<'a> { EscStr(s) => s, LabelStr(s) => { if s.contains('\\') { - (&*s).escape_default().to_string().into() + s.escape_default().to_string().into() } else { s } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 44335b7f42e..c89e7eb75f8 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -39,6 +39,7 @@ macro_rules! arena_types { [] param: rustc_hir::Param<'tcx>, [] pat: rustc_hir::Pat<'tcx>, [] path: rustc_hir::Path<'tcx>, + [] use_path: rustc_hir::UsePath<'tcx>, [] path_segment: rustc_hir::PathSegment<'tcx>, [] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>, [] qpath: rustc_hir::QPath<'tcx>, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 81aedcce877..636e6e1b48d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -183,14 +183,17 @@ impl Lifetime { /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. #[derive(Debug, HashStable_Generic)] -pub struct Path<'hir> { +pub struct Path<'hir, R = Res> { pub span: Span, /// The resolution for the path. - pub res: Res, + pub res: R, /// The segments in the path: the things separated by `::`. pub segments: &'hir [PathSegment<'hir>], } +/// Up to three resolutions for type, value and macro namespaces. +pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>; + impl Path<'_> { pub fn is_global(&self) -> bool { !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot @@ -940,7 +943,10 @@ pub struct Closure<'hir> { pub bound_generic_params: &'hir [GenericParam<'hir>], pub fn_decl: &'hir FnDecl<'hir>, pub body: BodyId, + /// The span of the declaration block: 'move |...| -> ...' pub fn_decl_span: Span, + /// The span of the argument block `|...|` + pub fn_arg_span: Option<Span>, pub movability: Option<Movability>, } @@ -2431,7 +2437,7 @@ impl<'hir> Ty<'hir> { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { - final_ty = &ty; + final_ty = ty; } final_ty } @@ -3068,7 +3074,7 @@ pub enum ItemKind<'hir> { /// or just /// /// `use foo::bar::baz;` (with `as baz` implicitly on the right). - Use(&'hir Path<'hir>, UseKind), + Use(&'hir UsePath<'hir>, UseKind), /// A `static` item. Static(&'hir Ty<'hir>, Mutability, BodyId), diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 33f02a115ef..93613ef27d4 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -116,7 +116,7 @@ impl Ord for HirId { impl PartialOrd for HirId { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 957f8c1058e..938ace2c785 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -367,7 +367,7 @@ pub trait Visitor<'v>: Sized { fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) { walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, path: &'v Path<'v>, hir_id: HirId) { + fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) { walk_use(self, path, hir_id) } fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) { @@ -422,7 +422,7 @@ pub trait Visitor<'v>: Sized { fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) { walk_qpath(self, qpath, id) } - fn visit_path(&mut self, path: &'v Path<'v>, _id: HirId) { + fn visit_path(&mut self, path: &Path<'v>, _id: HirId) { walk_path(self, path) } fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) { @@ -448,7 +448,7 @@ pub trait Visitor<'v>: Sized { pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) { visitor.visit_id(param.hir_id); - visitor.visit_pat(¶m.pat); + visitor.visit_pat(param.pat); } pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { @@ -470,7 +470,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { } ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn( FnKind::ItemFn(item.ident, generics, sig.header), - &sig.decl, + sig.decl, body_id, item.span, item.hir_id(), @@ -544,7 +544,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) { walk_list!(visitor, visit_param, body.params); - visitor.visit_expr(&body.value); + visitor.visit_expr(body.value); } pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) { @@ -580,7 +580,7 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) { // dominates the local's definition. walk_list!(visitor, visit_expr, &local.init); visitor.visit_id(local.hir_id); - visitor.visit_pat(&local.pat); + visitor.visit_pat(local.pat); if let Some(els) = local.els { visitor.visit_block(els); } @@ -606,7 +606,7 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) { visitor.visit_id(arm.hir_id); - visitor.visit_pat(&arm.pat); + visitor.visit_pat(arm.pat); if let Some(ref g) = arm.guard { match g { Guard::If(ref e) => visitor.visit_expr(e), @@ -615,7 +615,7 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) { } } } - visitor.visit_expr(&arm.body); + visitor.visit_expr(arm.body); } pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { @@ -660,7 +660,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) { visitor.visit_id(field.hir_id); visitor.visit_ident(field.ident); - visitor.visit_pat(&field.pat) + visitor.visit_pat(field.pat) } pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { @@ -740,6 +740,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) body, capture_clause: _, fn_decl_span: _, + fn_arg_span: _, movability: _, }) => { walk_list!(visitor, visit_generic_param, bound_generic_params); @@ -799,7 +800,7 @@ pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) { visitor.visit_id(field.hir_id); visitor.visit_ident(field.ident); - visitor.visit_expr(&field.expr) + visitor.visit_expr(field.expr) } pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { @@ -807,10 +808,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { match typ.kind { TyKind::Slice(ref ty) => visitor.visit_ty(ty), - TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty), + TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty), TyKind::Rptr(ref lifetime, ref mutable_type) => { visitor.visit_lifetime(lifetime); - visitor.visit_ty(&mutable_type.ty) + visitor.visit_ty(mutable_type.ty) } TyKind::Never => {} TyKind::Tup(tuple_element_types) => { @@ -818,7 +819,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { } TyKind::BareFn(ref function_declaration) => { walk_list!(visitor, visit_generic_param, function_declaration.generic_params); - visitor.visit_fn_decl(&function_declaration.decl); + visitor.visit_fn_decl(function_declaration.decl); } TyKind::Path(ref qpath) => { visitor.visit_qpath(qpath, typ.hir_id, typ.span); @@ -938,9 +939,12 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' } } -pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) { +pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v UsePath<'v>, hir_id: HirId) { visitor.visit_id(hir_id); - visitor.visit_path(path, hir_id); + let UsePath { segments, ref res, span } = *path; + for &res in res { + visitor.visit_path(&Path { segments, res, span }, hir_id); + } } pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) { @@ -948,8 +952,8 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item; let hir_id = trait_item.hir_id(); visitor.visit_ident(ident); - visitor.visit_generics(&generics); - visitor.visit_defaultness(&defaultness); + visitor.visit_generics(generics); + visitor.visit_defaultness(defaultness); match *kind { TraitItemKind::Const(ref ty, default) => { visitor.visit_id(hir_id); @@ -958,13 +962,13 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { visitor.visit_id(hir_id); - visitor.visit_fn_decl(&sig.decl); + visitor.visit_fn_decl(sig.decl); for ¶m_name in param_names { visitor.visit_ident(param_name); } } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { - visitor.visit_fn(FnKind::Method(ident, sig), &sig.decl, body_id, span, hir_id); + visitor.visit_fn(FnKind::Method(ident, sig), sig.decl, body_id, span, hir_id); } TraitItemKind::Type(bounds, ref default) => { visitor.visit_id(hir_id); @@ -1006,7 +1010,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt ImplItemKind::Fn(ref sig, body_id) => { visitor.visit_fn( FnKind::Method(impl_item.ident, sig), - &sig.decl, + sig.decl, body_id, impl_item.span, impl_item.hir_id(), @@ -1039,7 +1043,7 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &' pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) { visitor.visit_id(trait_ref.hir_ref_id); - visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id) + visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id) } pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) { @@ -1071,7 +1075,7 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>( pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) { visitor.visit_id(field.hir_id); visitor.visit_ident(field.ident); - visitor.visit_ty(&field.ty); + visitor.visit_ty(field.ty); } pub fn walk_enum_def<'v, V: Visitor<'v>>( @@ -1126,7 +1130,7 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: } } -pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>) { +pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) { for segment in path.segments { visitor.visit_path_segment(segment); } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 82150310638..f204d59d005 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -347,7 +347,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert!(self_ty.is_some()); } } else { - assert!(self_ty.is_none() && parent_substs.is_empty()); + assert!(self_ty.is_none()); } let arg_count = Self::check_generic_arg_count( @@ -1821,7 +1821,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Check if we have an enum variant. let mut variant_resolution = None; - if let ty::Adt(adt_def, _) = qself_ty.kind() { + if let ty::Adt(adt_def, adt_substs) = qself_ty.kind() { if adt_def.is_enum() { let variant_def = adt_def .variants() @@ -1923,8 +1923,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else { continue; }; - // FIXME(inherent_associated_types): This does not substitute parameters. - let ty = tcx.type_of(assoc_ty_did); + let item_substs = self.create_substs_for_associated_item( + span, + assoc_ty_did, + assoc_segment, + adt_substs, + ); + let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs); return Ok((ty, DefKind::AssocTy, assoc_ty_did)); } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index ba58672e759..82a77416a19 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -173,13 +173,11 @@ fn compare_predicate_entailment<'tcx>( impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs); debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs); - let impl_m_generics = tcx.generics_of(impl_m.def_id); - let trait_m_generics = tcx.generics_of(trait_m.def_id); let impl_m_predicates = tcx.predicates_of(impl_m.def_id); let trait_m_predicates = tcx.predicates_of(trait_m.def_id); // Check region bounds. - check_region_bounds_on_impl_item(tcx, impl_m, trait_m, &trait_m_generics, &impl_m_generics)?; + check_region_bounds_on_impl_item(tcx, impl_m, trait_m, false)?; // Create obligations for each predicate declared by the impl // definition in the context of the trait's parameter @@ -338,6 +336,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( // First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later. compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?; compare_generic_param_kinds(tcx, impl_m, trait_m, true)?; + check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?; let trait_to_impl_substs = impl_trait_ref.substs; @@ -722,12 +721,14 @@ fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, trait_m: &ty::AssocItem, - trait_generics: &ty::Generics, - impl_generics: &ty::Generics, + delay: bool, ) -> Result<(), ErrorGuaranteed> { - let trait_params = trait_generics.own_counts().lifetimes; + let impl_generics = tcx.generics_of(impl_m.def_id); let impl_params = impl_generics.own_counts().lifetimes; + let trait_generics = tcx.generics_of(trait_m.def_id); + let trait_params = trait_generics.own_counts().lifetimes; + debug!( "check_region_bounds_on_impl_item: \ trait_generics={:?} \ @@ -761,12 +762,16 @@ fn check_region_bounds_on_impl_item<'tcx>( None }; - let reported = tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait { - span, - item_kind: assoc_item_kind_str(impl_m), - ident: impl_m.ident(tcx), - generics_span, - }); + let reported = tcx + .sess + .create_err(LifetimesOrBoundsMismatchOnTrait { + span, + item_kind: assoc_item_kind_str(impl_m), + ident: impl_m.ident(tcx), + generics_span, + }) + .emit_unless(delay); + return Err(reported); } @@ -1504,18 +1509,10 @@ fn compare_type_predicate_entailment<'tcx>( let trait_to_impl_substs = impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs); - let impl_ty_generics = tcx.generics_of(impl_ty.def_id); - let trait_ty_generics = tcx.generics_of(trait_ty.def_id); let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id); let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id); - check_region_bounds_on_impl_item( - tcx, - impl_ty, - trait_ty, - &trait_ty_generics, - &impl_ty_generics, - )?; + check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?; let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index ff32329e431..b315ebad468 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -241,17 +241,46 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h // scopes, meaning that temporaries cannot outlive them. // This ensures fixed size stacks. hir::ExprKind::Binary( - source_map::Spanned { node: hir::BinOpKind::And, .. }, - _, - ref r, - ) - | hir::ExprKind::Binary( - source_map::Spanned { node: hir::BinOpKind::Or, .. }, - _, + source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, + ref l, ref r, ) => { - // For shortcircuiting operators, mark the RHS as a terminating - // scope since it only executes conditionally. + // expr is a short circuiting operator (|| or &&). As its + // functionality can't be overridden by traits, it always + // processes bool sub-expressions. bools are Copy and thus we + // can drop any temporaries in evaluation (read) order + // (with the exception of potentially failing let expressions). + // We achieve this by enclosing the operands in a terminating + // scope, both the LHS and the RHS. + + // We optimize this a little in the presence of chains. + // Chains like a && b && c get lowered to AND(AND(a, b), c). + // In here, b and c are RHS, while a is the only LHS operand in + // that chain. This holds true for longer chains as well: the + // leading operand is always the only LHS operand that is not a + // binop itself. Putting a binop like AND(a, b) into a + // terminating scope is not useful, thus we only put the LHS + // into a terminating scope if it is not a binop. + + let terminate_lhs = match l.kind { + // let expressions can create temporaries that live on + hir::ExprKind::Let(_) => false, + // binops already drop their temporaries, so there is no + // need to put them into a terminating scope. + // This is purely an optimization to reduce the number of + // terminating scopes. + hir::ExprKind::Binary( + source_map::Spanned { + node: hir::BinOpKind::And | hir::BinOpKind::Or, .. + }, + .., + ) => false, + // otherwise: mark it as terminating + _ => true, + }; + if terminate_lhs { + terminating(l.hir_id.local_id); + } // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries // should live beyond the immediate expression diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 7daed74e9de..b065ace6bf5 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1544,7 +1544,7 @@ fn check_fn_or_method<'tcx>( check_where_clauses(wfcx, span, def_id); check_return_position_impl_trait_in_trait_bounds( - tcx, + wfcx, def_id, sig.output(), hir_decl.output.span(), @@ -1580,13 +1580,14 @@ fn check_fn_or_method<'tcx>( /// Basically `check_associated_type_bounds`, but separated for now and should be /// deduplicated when RPITITs get lowered into real associated items. -#[tracing::instrument(level = "trace", skip(tcx))] +#[tracing::instrument(level = "trace", skip(wfcx))] fn check_return_position_impl_trait_in_trait_bounds<'tcx>( - tcx: TyCtxt<'tcx>, + wfcx: &WfCheckingCtxt<'_, 'tcx>, fn_def_id: LocalDefId, fn_output: Ty<'tcx>, span: Span, ) { + let tcx = wfcx.tcx(); if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) && assoc_item.container == ty::AssocItemContainer::TraitContainer { @@ -1596,22 +1597,20 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>( && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder && tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id() { - // Create a new context, since we want the opaque's ParamEnv and not the parent's. let span = tcx.def_span(proj.item_def_id); - enter_wf_checking_ctxt(tcx, span, proj.item_def_id.expect_local(), |wfcx| { - let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id); - let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { - let normalized_bound = wfcx.normalize(span, None, bound); - traits::wf::predicate_obligations( - wfcx.infcx, - wfcx.param_env, - wfcx.body_id, - normalized_bound, - bound_span, - ) - }); - wfcx.register_obligations(wf_obligations); + let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id); + let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { + let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs); + let normalized_bound = wfcx.normalize(span, None, bound); + traits::wf::predicate_obligations( + wfcx.infcx, + wfcx.param_env, + wfcx.body_id, + normalized_bound, + bound_span, + ) }); + wfcx.register_obligations(wf_obligations); } } } diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index d0c31733481..5749b04783c 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -57,25 +57,6 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { .maybe_unused_extern_crates(()) .iter() .filter(|&&(def_id, _)| { - // The `def_id` here actually was calculated during resolution (at least - // at the time of this writing) and is being shipped to us via a side - // channel of the tcx. There may have been extra expansion phases, - // however, which ended up removing the `def_id` *after* expansion. - // - // As a result we need to verify that `def_id` is indeed still valid for - // our AST and actually present in the HIR map. If it's not there then - // there's safely nothing to warn about, and otherwise we carry on with - // our execution. - // - // Note that if we carry through to the `extern_mod_stmt_cnum` query - // below it'll cause a panic because `def_id` is actually bogus at this - // point in time otherwise. - if tcx.hir().find(tcx.hir().local_def_id_to_hir_id(def_id)).is_none() { - return false; - } - true - }) - .filter(|&&(def_id, _)| { tcx.extern_mod_stmt_cnum(def_id).map_or(true, |cnum| { !tcx.is_compiler_builtins(cnum) && !tcx.is_panic_runtime(cnum) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index d623e726139..b7084303aaf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -2073,6 +2073,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE; + codegen_fn_attrs.inline = InlineAttr::Never; + } + // Weak lang items have the same semantics as "std internal" symbols in the // sense that they're preserved through all our LTO passes and only // strippable by the linker. diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index c11eed7ad9e..9a7b261fffd 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -814,7 +814,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { for (i, segment) in path.segments.iter().enumerate() { let depth = path.segments.len() - i - 1; if let Some(ref args) = segment.args { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 95729822677..3791b2c8661 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1480,6 +1480,7 @@ impl<'a> State<'a> { fn_decl, body, fn_decl_span: _, + fn_arg_span: _, movability: _, def_id: _, }) => { @@ -1591,7 +1592,7 @@ impl<'a> State<'a> { self.print_ident(Ident::with_dummy_span(name)) } - pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) { + pub fn print_path<R>(&mut self, path: &hir::Path<'_, R>, colons_before_params: bool) { self.maybe_print_comment(path.span.lo()); for (i, segment) in path.segments.iter().enumerate() { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5d3419b3b6e..429cb60ba2b 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -456,10 +456,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .map(|ty| ArgKind::from_expected_ty(*ty, None)) .collect(); - let (closure_span, found_args) = match self.get_fn_like_arguments(expr_map_node) { - Some((sp, args)) => (Some(sp), args), - None => (None, Vec::new()), - }; + let (closure_span, closure_arg_span, found_args) = + match self.get_fn_like_arguments(expr_map_node) { + Some((sp, arg_sp, args)) => (Some(sp), arg_sp, args), + None => (None, None, Vec::new()), + }; let expected_span = expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id)); self.report_arg_count_mismatch( @@ -468,6 +469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_args, found_args, true, + closure_arg_span, ) .emit(); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 0c5bbb3e20b..4a112e80f1d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -528,6 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); let ty = match res { Res::Err => { + self.suggest_assoc_method_call(segs); let e = self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 86384c7b93e..3078e0cbeda 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1918,6 +1918,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { receiver: Option<&'tcx hir::Expr<'tcx>>, args: &'tcx [hir::Expr<'tcx>], ) -> bool { + // Do not call `fn_sig` on non-functions. + if !matches!( + self.tcx.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) + ) { + return false; + } + let sig = self.tcx.fn_sig(def_id).skip_binder(); let args_referencing_param: Vec<_> = sig .inputs() diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index ea141e815bf..1e9b5752130 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::{self, Span}; -use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::cell::{Cell, RefCell}; use std::ops::Deref; @@ -162,6 +162,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()), fallback_has_occurred: self.fallback_has_occurred.get(), + normalize_fn_sig: Box::new(|fn_sig| { + if fn_sig.has_escaping_bound_vars() { + return fn_sig; + } + self.probe(|_| { + let ocx = ObligationCtxt::new_in_snapshot(self); + let normalized_fn_sig = + ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig); + if ocx.select_all_or_error().is_empty() { + let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig); + if !normalized_fn_sig.needs_infer() { + return normalized_fn_sig; + } + } + fn_sig + }) + }), } } diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 869ad07c00d..b33e7b8d68c 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -1,7 +1,6 @@ use super::callee::DeferredCallResolution; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::HirIdMap; @@ -11,9 +10,7 @@ use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefIdMap; use rustc_span::{self, Span}; -use rustc_trait_selection::traits::{ - self, ObligationCause, ObligationCtxt, TraitEngine, TraitEngineExt as _, -}; +use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _}; use std::cell::RefCell; use std::ops::Deref; @@ -92,29 +89,7 @@ impl<'tcx> Inherited<'tcx> { infcx: tcx .infer_ctxt() .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)) - .with_normalize_fn_sig_for_diagnostic(Lrc::new(move |infcx, fn_sig| { - if fn_sig.has_escaping_bound_vars() { - return fn_sig; - } - infcx.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(infcx); - let normalized_fn_sig = ocx.normalize( - &ObligationCause::dummy(), - // FIXME(compiler-errors): This is probably not the right param-env... - infcx.tcx.param_env(def_id), - fn_sig, - ); - if ocx.select_all_or_error().is_empty() { - let normalized_fn_sig = - infcx.resolve_vars_if_possible(normalized_fn_sig); - if !normalized_fn_sig.needs_infer() { - return normalized_fn_sig; - } - } - fn_sig - }) - })), + .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)), def_id, typeck_results: RefCell::new(ty::TypeckResults::new(hir_owner)), } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index ebbd5eb1e64..a2ca5c3b7b7 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -20,7 +20,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; -use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable}; +use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -217,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // We probe again, taking all traits into account (not only those in scope). - let mut candidates = + let candidates = match self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::AllTraits) { // If we find a different result the caller probably forgot to import a trait. Ok(ref new_pick) if pick.differs_from(new_pick) => { @@ -236,7 +236,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(), _ => Vec::new(), }; - candidates.retain(|candidate| *candidate != self.tcx.parent(result.callee.def_id)); return Err(IllegalSizedBound(candidates, needs_mut, span)); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index c78a32c29dc..ae299cc9d13 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -9,7 +9,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def::Namespace; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -1876,6 +1875,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.tcx.erase_late_bound_regions(value) } + /// Determine if the given associated item type is relevant in the current context. + fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool { + match (self.mode, kind) { + (Mode::MethodCall, ty::AssocKind::Fn) => true, + (Mode::Path, ty::AssocKind::Const | ty::AssocKind::Fn) => true, + _ => false, + } + } + /// Finds the method with the appropriate name (or return type, as the case may be). If /// `allow_similar_names` is set, find methods with close-matching names. // The length of the returned iterator is nearly always 0 or 1 and this @@ -1888,7 +1896,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .associated_items(def_id) .in_definition_order() .filter(|x| { - if x.kind.namespace() != Namespace::ValueNS { + if !self.is_relevant_kind_for_mode(x.kind) { return false; } match lev_distance_with_substrings(name.as_str(), x.name.as_str(), max_dist) @@ -1902,10 +1910,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { self.fcx .associated_value(def_id, name) + .filter(|x| self.is_relevant_kind_for_mode(x.kind)) .map_or_else(SmallVec::new, |x| SmallVec::from_buf([x])) } } else { - self.tcx.associated_items(def_id).in_definition_order().copied().collect() + self.tcx + .associated_items(def_id) + .in_definition_order() + .filter(|x| self.is_relevant_kind_for_mode(x.kind)) + .copied() + .collect() } } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 727fab9e7aa..9ba4ddfd5cf 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -5,6 +5,7 @@ use crate::errors; use crate::FnCtxt; use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::StashKey; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, @@ -13,6 +14,8 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; +use rustc_hir::PatKind::Binding; +use rustc_hir::PathSegment; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::{ type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, @@ -35,11 +38,11 @@ use rustc_trait_selection::traits::{ FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, }; -use std::cmp::Ordering; -use std::iter; - use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope}; use super::{CandidateSource, MethodError, NoMatchData}; +use rustc_hir::intravisit::Visitor; +use std::cmp::Ordering; +use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { @@ -1462,6 +1465,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + /// For code `rect::area(...)`, + /// if `rect` is a local variable and `area` is a valid assoc method for it, + /// we try to suggest `rect.area()` + pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) { + debug!("suggest_assoc_method_call segs: {:?}", segs); + let [seg1, seg2] = segs else { return; }; + let Some(mut diag) = + self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod) + else { return }; + + let map = self.infcx.tcx.hir(); + let body = map.body(rustc_hir::BodyId { hir_id: self.body_id }); + struct LetVisitor<'a> { + result: Option<&'a hir::Expr<'a>>, + ident_name: Symbol, + } + + impl<'v> Visitor<'v> for LetVisitor<'v> { + fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { + if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind { + if let Binding(_, _, ident, ..) = pat.kind && + ident.name == self.ident_name { + self.result = *init; + } + } + hir::intravisit::walk_stmt(self, ex); + } + } + + let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name }; + visitor.visit_body(&body); + + let parent = self.tcx.hir().get_parent_node(seg1.hir_id); + if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) && + let Some(expr) = visitor.result { + let self_ty = self.node_ty(expr.hir_id); + let probe = self.lookup_probe( + seg2.ident, + self_ty, + call_expr, + ProbeScope::TraitsInScope, + ); + if probe.is_ok() { + let sm = self.infcx.tcx.sess.source_map(); + diag.span_suggestion_verbose( + sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(), + "you may have meant to call an instance method", + ".".to_string(), + Applicability::MaybeIncorrect + ); + } + } + diag.emit(); + } + /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()` fn suggest_calling_method_on_field( &self, diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 2483ab724a4..4429e4f4362 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -77,10 +77,6 @@ impl<'tcx> InferCtxt<'tcx> { err_count_on_creation: self.err_count_on_creation, in_snapshot: self.in_snapshot.clone(), universe: self.universe.clone(), - normalize_fn_sig_for_diagnostic: self - .normalize_fn_sig_for_diagnostic - .as_ref() - .map(|f| f.clone()), intercrate: self.intercrate, } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e2be8fb12d0..662136ca18d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -95,6 +95,7 @@ pub mod nice_region_error; pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>, + pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>, pub fallback_has_occurred: bool, } @@ -1007,22 +1008,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - fn normalize_fn_sig_for_diagnostic(&self, sig: ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> { - if let Some(normalize) = &self.normalize_fn_sig_for_diagnostic { - normalize(self, sig) - } else { - sig - } - } - /// Given two `fn` signatures highlight only sub-parts that are different. fn cmp_fn_sig( &self, sig1: &ty::PolyFnSig<'tcx>, sig2: &ty::PolyFnSig<'tcx>, ) -> (DiagnosticStyledString, DiagnosticStyledString) { - let sig1 = &self.normalize_fn_sig_for_diagnostic(*sig1); - let sig2 = &self.normalize_fn_sig_for_diagnostic(*sig2); + let sig1 = &(self.normalize_fn_sig)(*sig1); + let sig2 = &(self.normalize_fn_sig)(*sig2); let get_lifetimes = |sig| { use rustc_hir::def::Namespace; @@ -1262,7 +1255,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let num_display_types = consts_offset - regions_len; for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() { let i = i + regions_len; - if ta1 == ta2 { + if ta1 == ta2 && !self.tcx.sess.verbose() { values.0.push_normal("_"); values.1.push_normal("_"); } else { @@ -1278,7 +1271,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let const_arguments = sub1.consts().zip(sub2.consts()); for (i, (ca1, ca2)) in const_arguments.enumerate() { let i = i + consts_offset; - if ca1 == ca2 { + if ca1 == ca2 && !self.tcx.sess.verbose() { values.0.push_normal("_"); values.1.push_normal("_"); } else { @@ -1457,7 +1450,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2), _ => { - if t1 == t2 { + if t1 == t2 && !self.tcx.sess.verbose() { // The two types are the same, elide and don't highlight. (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_")) } else { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2bcb47cc383..2ce7cd8beba 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -80,7 +80,6 @@ pub struct InferOk<'tcx, T> { } pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>; -pub type Bound<T> = Option<T>; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result" @@ -334,9 +333,6 @@ pub struct InferCtxt<'tcx> { /// bound. universe: Cell<ty::UniverseIndex>, - normalize_fn_sig_for_diagnostic: - Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, - /// During coherence we have to assume that other crates may add /// additional impls which we currently don't know about. /// @@ -573,8 +569,6 @@ pub struct InferCtxtBuilder<'tcx> { considering_regions: bool, /// Whether we are in coherence mode. intercrate: bool, - normalize_fn_sig_for_diagnostic: - Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, } pub trait TyCtxtInferExt<'tcx> { @@ -587,7 +581,6 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { tcx: self, defining_use_anchor: DefiningAnchor::Error, considering_regions: true, - normalize_fn_sig_for_diagnostic: None, intercrate: false, } } @@ -615,14 +608,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } - pub fn with_normalize_fn_sig_for_diagnostic( - mut self, - fun: Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>, - ) -> Self { - self.normalize_fn_sig_for_diagnostic = Some(fun); - self - } - /// Given a canonical value `C` as a starting point, create an /// inference context that contains each of the bound values /// within instantiated as a fresh variable. The `f` closure is @@ -644,13 +629,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn build(&mut self) -> InferCtxt<'tcx> { - let InferCtxtBuilder { - tcx, - defining_use_anchor, - considering_regions, - ref normalize_fn_sig_for_diagnostic, - intercrate, - } = *self; + let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self; InferCtxt { tcx, defining_use_anchor, @@ -666,9 +645,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { in_snapshot: Cell::new(false), skip_leak_check: Cell::new(false), universe: Cell::new(ty::UniverseIndex::ROOT), - normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic - .as_ref() - .map(|f| f.clone()), intercrate, } } @@ -709,7 +685,12 @@ impl<'tcx> InferCtxt<'tcx> { /// Creates a `TypeErrCtxt` for emitting various inference errors. /// During typeck, use `FnCtxt::err_ctxt` instead. pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { - TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false } + TypeErrCtxt { + infcx: self, + typeck_results: None, + fallback_has_occurred: false, + normalize_fn_sig: Box::new(|fn_sig| fn_sig), + } } pub fn is_in_snapshot(&self) -> bool { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7f1d21bf1d8..6b5b5df9e2a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -207,10 +207,7 @@ pub fn register_plugins<'a>( }); } - let mut lint_store = rustc_lint::new_lint_store( - sess.opts.unstable_opts.no_interleave_lints, - sess.enable_internal_lints(), - ); + let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); register_lints(sess, &mut lint_store); let registrars = diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a03e7b0dae5..a6205f4d3a5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -666,7 +666,6 @@ fn test_unstable_options_tracking_hash() { untracked!(mir_pretty_relative_line_numbers, true); untracked!(nll_facts, true); untracked!(no_analysis, true); - untracked!(no_interleave_lints, true); untracked!(no_leak_check, true); untracked!(no_parallel_llvm, true); untracked!(parse_only, true); diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index a7a4d0ca527..215df567e0e 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -25,8 +25,6 @@ use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::Span; -use std::slice; - macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } @@ -300,20 +298,14 @@ impl LintPass for EarlyLintPassObjects<'_> { } } -macro_rules! expand_early_lint_pass_impl_methods { - ([$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { - for obj in self.lints.iter_mut() { - obj.$name(context, $($param),*); - } - })* - ) -} - macro_rules! early_lint_pass_impl { - ([], [$($methods:tt)*]) => ( + ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( impl EarlyLintPass for EarlyLintPassObjects<'_> { - expand_early_lint_pass_impl_methods!([$($methods)*]); + $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { + for obj in self.lints.iter_mut() { + obj.$name(context, $($param),*); + } + })* } ) } @@ -371,87 +363,36 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast:: } } -fn early_lint_node<'a>( - sess: &Session, - warn_about_weird_lints: bool, - lint_store: &LintStore, - registered_tools: &RegisteredTools, - buffered: LintBuffer, - pass: impl EarlyLintPass, - check_node: impl EarlyCheckNode<'a>, -) -> LintBuffer { - let mut cx = EarlyContextAndPass { - context: EarlyContext::new( - sess, - warn_about_weird_lints, - lint_store, - registered_tools, - buffered, - ), - pass, - }; - - cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); - cx.context.buffered -} - pub fn check_ast_node<'a>( sess: &Session, pre_expansion: bool, lint_store: &LintStore, registered_tools: &RegisteredTools, lint_buffer: Option<LintBuffer>, - builtin_lints: impl EarlyLintPass, + builtin_lints: impl EarlyLintPass + 'static, check_node: impl EarlyCheckNode<'a>, ) { let passes = if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect(); - let mut buffered = lint_buffer.unwrap_or_default(); - - if sess.opts.unstable_opts.no_interleave_lints { - for (i, pass) in passes.iter_mut().enumerate() { - buffered = - sess.prof.verbose_generic_activity_with_arg("run_lint", pass.name()).run(|| { - early_lint_node( - sess, - !pre_expansion && i == 0, - lint_store, - registered_tools, - buffered, - EarlyLintPassObjects { lints: slice::from_mut(pass) }, - check_node, - ) - }); - } - } else { - buffered = early_lint_node( + passes.push(Box::new(builtin_lints)); + + let mut cx = EarlyContextAndPass { + context: EarlyContext::new( sess, !pre_expansion, lint_store, registered_tools, - buffered, - builtin_lints, - check_node, - ); - - if !passes.is_empty() { - buffered = early_lint_node( - sess, - false, - lint_store, - registered_tools, - buffered, - EarlyLintPassObjects { lints: &mut passes[..] }, - check_node, - ); - } - } + lint_buffer.unwrap_or_default(), + ), + pass: EarlyLintPassObjects { lints: &mut passes[..] }, + }; + cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); // All of the buffered lints should have been emitted at this point. // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. - for (id, lints) in buffered.map { + for (id, lints) in cx.context.buffered.map { for early_lint in lints { sess.delay_span_bug( early_lint.span, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index a6c7e819482..4f92661dbd3 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { fn check_path( &mut self, cx: &LateContext<'tcx>, - path: &'tcx rustc_hir::Path<'tcx>, + path: &rustc_hir::Path<'tcx>, _: rustc_hir::HirId, ) { if let Some(segment) = path.segments.iter().nth_back(1) diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index f484e31ba15..e1aedc26d1b 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -28,7 +28,6 @@ use rustc_span::Span; use std::any::Any; use std::cell::Cell; -use std::slice; /// Extract the `LintStore` from the query context. /// This function exists because we've erased `LintStore` as `dyn Any` in the context. @@ -292,7 +291,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas hir_visit::walk_lifetime(self, lt); } - fn visit_path(&mut self, p: &'tcx hir::Path<'tcx>, id: hir::HirId) { + fn visit_path(&mut self, p: &hir::Path<'tcx>, id: hir::HirId) { lint_callback!(self, check_path, p, id); hir_visit::walk_path(self, p); } @@ -313,45 +312,42 @@ impl LintPass for LateLintPassObjects<'_, '_> { } } -macro_rules! expand_late_lint_pass_impl_methods { - ([$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) { - for obj in self.lints.iter_mut() { - obj.$name(context, $($param),*); - } - })* - ) -} - macro_rules! late_lint_pass_impl { - ([], [$hir:tt], $methods:tt) => { + ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => { impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> { - expand_late_lint_pass_impl_methods!([$hir], $methods); + $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) { + for obj in self.lints.iter_mut() { + obj.$name(context, $($param),*); + } + })* } }; } crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]); -fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( +pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( tcx: TyCtxt<'tcx>, module_def_id: LocalDefId, - pass: T, + builtin_lints: T, ) { - let effective_visibilities = &tcx.effective_visibilities(()); - let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - effective_visibilities, + effective_visibilities: &tcx.effective_visibilities(()), lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id), generics: None, only_module: true, }; + let mut passes: Vec<_> = + unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); + passes.push(Box::new(builtin_lints)); + let pass = LateLintPassObjects { lints: &mut passes[..] }; + let mut cx = LateContextAndPass { context, pass }; let (module, _span, hir_id) = tcx.hir().get_module(module_def_id); @@ -365,46 +361,29 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( } } -pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( - tcx: TyCtxt<'tcx>, - module_def_id: LocalDefId, - builtin_lints: T, -) { - if tcx.sess.opts.unstable_opts.no_interleave_lints { - // These passes runs in late_lint_crate with -Z no_interleave_lints - return; - } - - late_lint_mod_pass(tcx, module_def_id, builtin_lints); - - let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); - - if !passes.is_empty() { - late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); - } -} - -fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { - let effective_visibilities = &tcx.effective_visibilities(()); - +fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builtin_lints: T) { let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - effective_visibilities, + effective_visibilities: &tcx.effective_visibilities(()), lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, only_module: false, }; + let mut passes = + unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>(); + passes.push(Box::new(builtin_lints)); + let pass = LateLintPassObjects { lints: &mut passes[..] }; + let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| { - // since the root module isn't visited as an item (because it isn't an + // Since the root module isn't visited as an item (because it isn't an // item), warn for it here. lint_callback!(cx, check_crate,); tcx.hir().walk_toplevel_module(cx); @@ -413,41 +392,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) }) } -fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { - let mut passes = - unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>(); - - if !tcx.sess.opts.unstable_opts.no_interleave_lints { - if !passes.is_empty() { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: &mut passes[..] }); - } - - late_lint_pass_crate(tcx, builtin_lints); - } else { - for pass in &mut passes { - tcx.sess.prof.verbose_generic_activity_with_arg("run_late_lint", pass.name()).run( - || { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }, - ); - } - - let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); - - for pass in &mut passes { - tcx.sess - .prof - .verbose_generic_activity_with_arg("run_late_module_lint", pass.name()) - .run(|| { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }); - } - } -} - /// Performs lint checking on a crate. -pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( +pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>( tcx: TyCtxt<'tcx>, builtin_lints: impl FnOnce() -> T + Send, ) { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b6027476adf..10bae36e0fd 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -127,132 +127,116 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new()); } -macro_rules! pre_expansion_lint_passes { - ($macro:path, $args:tt) => { - $macro!($args, [KeywordIdents: KeywordIdents,]); - }; -} - -macro_rules! early_lint_passes { - ($macro:path, $args:tt) => { - $macro!( - $args, - [ - UnusedParens: UnusedParens, - UnusedBraces: UnusedBraces, - UnusedImportBraces: UnusedImportBraces, - UnsafeCode: UnsafeCode, - SpecialModuleName: SpecialModuleName, - AnonymousParameters: AnonymousParameters, - EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(), - NonCamelCaseTypes: NonCamelCaseTypes, - DeprecatedAttr: DeprecatedAttr::new(), - WhileTrue: WhileTrue, - NonAsciiIdents: NonAsciiIdents, - HiddenUnicodeCodepoints: HiddenUnicodeCodepoints, - IncompleteFeatures: IncompleteFeatures, - RedundantSemicolons: RedundantSemicolons, - UnusedDocComment: UnusedDocComment, - UnexpectedCfgs: UnexpectedCfgs, - ] - ); - }; -} - -macro_rules! declare_combined_early_pass { - ([$name:ident], $passes:tt) => ( - early_lint_methods!(declare_combined_early_lint_pass, [pub $name, $passes]); - ) -} - -pre_expansion_lint_passes!(declare_combined_early_pass, [BuiltinCombinedPreExpansionLintPass]); -early_lint_passes!(declare_combined_early_pass, [BuiltinCombinedEarlyLintPass]); - -macro_rules! late_lint_passes { - ($macro:path, $args:tt) => { - $macro!( - $args, - [ - // Tracks state across modules - UnnameableTestItems: UnnameableTestItems::new(), - // Tracks attributes of parents - MissingDoc: MissingDoc::new(), - // Builds a global list of all impls of `Debug`. - // FIXME: Turn the computation of types which implement Debug into a query - // and change this to a module lint pass - MissingDebugImplementations: MissingDebugImplementations::default(), - // Keeps a global list of foreign declarations. - ClashingExternDeclarations: ClashingExternDeclarations::new(), - ] - ); - }; -} - -macro_rules! late_lint_mod_passes { - ($macro:path, $args:tt) => { - $macro!( - $args, - [ - ForLoopsOverFallibles: ForLoopsOverFallibles, - DerefIntoDynSupertrait: DerefIntoDynSupertrait, - HardwiredLints: HardwiredLints, - ImproperCTypesDeclarations: ImproperCTypesDeclarations, - ImproperCTypesDefinitions: ImproperCTypesDefinitions, - VariantSizeDifferences: VariantSizeDifferences, - BoxPointers: BoxPointers, - PathStatements: PathStatements, - LetUnderscore: LetUnderscore, - // Depends on referenced function signatures in expressions - UnusedResults: UnusedResults, - NonUpperCaseGlobals: NonUpperCaseGlobals, - NonShorthandFieldPatterns: NonShorthandFieldPatterns, - UnusedAllocation: UnusedAllocation, - // Depends on types used in type definitions - MissingCopyImplementations: MissingCopyImplementations, - // Depends on referenced function signatures in expressions - MutableTransmutes: MutableTransmutes, - TypeAliasBounds: TypeAliasBounds, - TrivialConstraints: TrivialConstraints, - TypeLimits: TypeLimits::new(), - NonSnakeCase: NonSnakeCase, - InvalidNoMangleItems: InvalidNoMangleItems, - // Depends on effective visibilities - UnreachablePub: UnreachablePub, - ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, - InvalidValue: InvalidValue, - DerefNullPtr: DerefNullPtr, - // May Depend on constants elsewhere - UnusedBrokenConst: UnusedBrokenConst, - UnstableFeatures: UnstableFeatures, - ArrayIntoIter: ArrayIntoIter::default(), - DropTraitConstraints: DropTraitConstraints, - TemporaryCStringAsPtr: TemporaryCStringAsPtr, - NonPanicFmt: NonPanicFmt, - NoopMethodCall: NoopMethodCall, - EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums, - InvalidAtomicOrdering: InvalidAtomicOrdering, - NamedAsmLabels: NamedAsmLabels, - OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, - ] - ); - }; -} - -macro_rules! declare_combined_late_pass { - ([$v:vis $name:ident], $passes:tt) => ( - late_lint_methods!(declare_combined_late_lint_pass, [$v $name, $passes], ['tcx]); - ) -} +early_lint_methods!( + declare_combined_early_lint_pass, + [ + pub BuiltinCombinedPreExpansionLintPass, + [ + KeywordIdents: KeywordIdents, + ] + ] +); + +early_lint_methods!( + declare_combined_early_lint_pass, + [ + pub BuiltinCombinedEarlyLintPass, + [ + UnusedParens: UnusedParens, + UnusedBraces: UnusedBraces, + UnusedImportBraces: UnusedImportBraces, + UnsafeCode: UnsafeCode, + SpecialModuleName: SpecialModuleName, + AnonymousParameters: AnonymousParameters, + EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(), + NonCamelCaseTypes: NonCamelCaseTypes, + DeprecatedAttr: DeprecatedAttr::new(), + WhileTrue: WhileTrue, + NonAsciiIdents: NonAsciiIdents, + HiddenUnicodeCodepoints: HiddenUnicodeCodepoints, + IncompleteFeatures: IncompleteFeatures, + RedundantSemicolons: RedundantSemicolons, + UnusedDocComment: UnusedDocComment, + UnexpectedCfgs: UnexpectedCfgs, + ] + ] +); // FIXME: Make a separate lint type which do not require typeck tables -late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass]); - -late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]); - -pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintStore { +late_lint_methods!( + declare_combined_late_lint_pass, + [ + pub BuiltinCombinedLateLintPass, + [ + // Tracks state across modules + UnnameableTestItems: UnnameableTestItems::new(), + // Tracks attributes of parents + MissingDoc: MissingDoc::new(), + // Builds a global list of all impls of `Debug`. + // FIXME: Turn the computation of types which implement Debug into a query + // and change this to a module lint pass + MissingDebugImplementations: MissingDebugImplementations::default(), + // Keeps a global list of foreign declarations. + ClashingExternDeclarations: ClashingExternDeclarations::new(), + ] + ], + ['tcx] +); + +late_lint_methods!( + declare_combined_late_lint_pass, + [ + BuiltinCombinedModuleLateLintPass, + [ + ForLoopsOverFallibles: ForLoopsOverFallibles, + DerefIntoDynSupertrait: DerefIntoDynSupertrait, + HardwiredLints: HardwiredLints, + ImproperCTypesDeclarations: ImproperCTypesDeclarations, + ImproperCTypesDefinitions: ImproperCTypesDefinitions, + VariantSizeDifferences: VariantSizeDifferences, + BoxPointers: BoxPointers, + PathStatements: PathStatements, + LetUnderscore: LetUnderscore, + // Depends on referenced function signatures in expressions + UnusedResults: UnusedResults, + NonUpperCaseGlobals: NonUpperCaseGlobals, + NonShorthandFieldPatterns: NonShorthandFieldPatterns, + UnusedAllocation: UnusedAllocation, + // Depends on types used in type definitions + MissingCopyImplementations: MissingCopyImplementations, + // Depends on referenced function signatures in expressions + MutableTransmutes: MutableTransmutes, + TypeAliasBounds: TypeAliasBounds, + TrivialConstraints: TrivialConstraints, + TypeLimits: TypeLimits::new(), + NonSnakeCase: NonSnakeCase, + InvalidNoMangleItems: InvalidNoMangleItems, + // Depends on effective visibilities + UnreachablePub: UnreachablePub, + ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, + InvalidValue: InvalidValue, + DerefNullPtr: DerefNullPtr, + // May Depend on constants elsewhere + UnusedBrokenConst: UnusedBrokenConst, + UnstableFeatures: UnstableFeatures, + ArrayIntoIter: ArrayIntoIter::default(), + DropTraitConstraints: DropTraitConstraints, + TemporaryCStringAsPtr: TemporaryCStringAsPtr, + NonPanicFmt: NonPanicFmt, + NoopMethodCall: NoopMethodCall, + EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums, + InvalidAtomicOrdering: InvalidAtomicOrdering, + NamedAsmLabels: NamedAsmLabels, + OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, + ] + ], + ['tcx] +); + +pub fn new_lint_store(internal_lints: bool) -> LintStore { let mut lint_store = LintStore::new(); - register_builtins(&mut lint_store, no_interleave_lints); + register_builtins(&mut lint_store); if internal_lints { register_internals(&mut lint_store); } @@ -263,54 +247,17 @@ pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintSt /// Tell the `LintStore` about all the built-in lints (the ones /// defined in this crate and the ones defined in /// `rustc_session::lint::builtin`). -fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { +fn register_builtins(store: &mut LintStore) { macro_rules! add_lint_group { ($name:expr, $($lint:ident),*) => ( store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]); ) } - macro_rules! register_early_pass { - ($method:ident, $ty:ident, $constructor:expr) => { - store.register_lints(&$ty::get_lints()); - store.$method(|| Box::new($constructor)); - }; - } - - macro_rules! register_late_pass { - ($method:ident, $ty:ident, $constructor:expr) => { - store.register_lints(&$ty::get_lints()); - store.$method(|_| Box::new($constructor)); - }; - } - - macro_rules! register_early_passes { - ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( - $( - register_early_pass!($method, $passes, $constructor); - )* - ) - } - - macro_rules! register_late_passes { - ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( - $( - register_late_pass!($method, $passes, $constructor); - )* - ) - } - - if no_interleave_lints { - pre_expansion_lint_passes!(register_early_passes, register_pre_expansion_pass); - early_lint_passes!(register_early_passes, register_early_pass); - late_lint_passes!(register_late_passes, register_late_pass); - late_lint_mod_passes!(register_late_passes, register_late_mod_pass); - } else { - store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); - store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); - store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints()); - store.register_lints(&BuiltinCombinedLateLintPass::get_lints()); - } + store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); + store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); + store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints()); + store.register_lints(&BuiltinCombinedLateLintPass::get_lints()); add_lint_group!( "nonstandard_style", diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 1c6a057d1a8..2f53986139e 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -1,7 +1,6 @@ use crate::context::{EarlyContext, LateContext}; use rustc_ast as ast; -use rustc_data_structures::sync; use rustc_hir as hir; use rustc_session::lint::builtin::HardwiredLints; use rustc_session::lint::LintPass; @@ -44,7 +43,7 @@ macro_rules! late_lint_methods { fn check_struct_def(a: &$hir hir::VariantData<$hir>); fn check_field_def(a: &$hir hir::FieldDef<$hir>); fn check_variant(a: &$hir hir::Variant<$hir>); - fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId); + fn check_path(a: &hir::Path<$hir>, b: hir::HirId); fn check_attribute(a: &$hir ast::Attribute); /// Called when entering a syntax node that can have lint attributes such @@ -66,16 +65,10 @@ macro_rules! late_lint_methods { // FIXME: eliminate the duplication with `Visitor`. But this also // contains a few lint-specific methods with no equivalent in `Visitor`. -macro_rules! expand_lint_pass_methods { - ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})* - ) -} - macro_rules! declare_late_lint_pass { - ([], [$hir:tt], [$($methods:tt)*]) => ( + ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( pub trait LateLintPass<$hir>: LintPass { - expand_lint_pass_methods!(&LateContext<$hir>, [$($methods)*]); + $(#[inline(always)] fn $name(&mut self, _: &LateContext<$hir>, $(_: $arg),*) {})* } ) } @@ -175,16 +168,10 @@ macro_rules! early_lint_methods { ) } -macro_rules! expand_early_lint_pass_methods { - ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})* - ) -} - macro_rules! declare_early_lint_pass { - ([], [$($methods:tt)*]) => ( + ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( pub trait EarlyLintPass: LintPass { - expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]); + $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})* } ) } @@ -243,5 +230,5 @@ macro_rules! declare_combined_early_lint_pass { } /// A lint pass boxed up as a trait object. -pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + 'static>; -pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + sync::Send + 'tcx>; +pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>; +pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>; diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 88ad4c67d93..a7836ea8e7a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1264,7 +1264,7 @@ impl UnusedImportBraces { // Trigger the lint if the nested item is a non-self single item let node_name = match items[0].0.kind { - ast::UseTreeKind::Simple(rename, ..) => { + ast::UseTreeKind::Simple(rename) => { let orig_ident = items[0].0.prefix.segments.last().unwrap().ident; if orig_ident.name == kw::SelfLower { return; diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index d35e4191cc0..79f06ac146c 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -222,6 +222,7 @@ fn main() { .file("llvm-wrapper/RustWrapper.cpp") .file("llvm-wrapper/ArchiveWrapper.cpp") .file("llvm-wrapper/CoverageMappingWrapper.cpp") + .file("llvm-wrapper/SymbolWrapper.cpp") .file("llvm-wrapper/Linker.cpp") .cpp(true) .cpp_link_stdlib(None) // we handle this below diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 216c35d6da0..792d921c6a4 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1967,3 +1967,7 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) { #endif return -1; } + +extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) { + return identify_magic(StringRef(ptr, len)) == file_magic::bitcode; +} diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp new file mode 100644 index 00000000000..974207e918c --- /dev/null +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -0,0 +1,96 @@ +// Derived from code in LLVM, which is: +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Derived from: +// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h +// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp + +#include "llvm/IR/LLVMContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/ADT/Optional.h" + +using namespace llvm; +using namespace llvm::sys; +using namespace llvm::object; + +static bool isArchiveSymbol(const object::BasicSymbolRef &S) { + Expected<uint32_t> SymFlagsOrErr = S.getFlags(); + if (!SymFlagsOrErr) + // FIXME: Actually report errors helpfully. + report_fatal_error(SymFlagsOrErr.takeError()); + if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific) + return false; + if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global)) + return false; + if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined) + return false; + return true; +} + +typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *); +typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *); + +// Note: This is implemented in C++ instead of using the C api from Rust as IRObjectFile doesn't +// implement getSymbolName, only printSymbolName, which is inaccessible from the C api. +extern "C" void *LLVMRustGetSymbols( + char *BufPtr, size_t BufLen, void *State, LLVMRustGetSymbolsCallback Callback, + LLVMRustGetSymbolsErrorCallback ErrorCallback) { + std::unique_ptr<MemoryBuffer> Buf = + MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), + false); + SmallString<0> SymNameBuf; + raw_svector_ostream SymName(SymNameBuf); + + // In the scenario when LLVMContext is populated SymbolicFile will contain a + // reference to it, thus SymbolicFile should be destroyed first. + LLVMContext Context; + std::unique_ptr<object::SymbolicFile> Obj; + + const file_magic Type = identify_magic(Buf->getBuffer()); + if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) { + return 0; + } + + if (Type == file_magic::bitcode) { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile( + Buf->getMemBufferRef(), file_magic::bitcode, &Context); + if (!ObjOrErr) { + Error E = ObjOrErr.takeError(); + SmallString<0> ErrorBuf; + raw_svector_ostream Error(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); + } + Obj = std::move(*ObjOrErr); + } else { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef()); + if (!ObjOrErr) { + Error E = ObjOrErr.takeError(); + SmallString<0> ErrorBuf; + raw_svector_ostream Error(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); + } + Obj = std::move(*ObjOrErr); + } + + + for (const object::BasicSymbolRef &S : Obj->symbols()) { + if (!isArchiveSymbol(S)) + continue; + if (Error E = S.printName(SymName)) { + SmallString<0> ErrorBuf; + raw_svector_ostream Error(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); + } + SymName << '\0'; + if (void *E = Callback(State, SymNameBuf.str().data())) { + return E; + } + SymNameBuf.clear(); + } + return 0; +} diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index be9821c00f5..684835d8c5c 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -29,8 +29,8 @@ impl<'a> DiagnosticDerive<'a> { let DiagnosticDerive { mut structure, mut builder } = self; let implementation = builder.each_variant(&mut structure, |mut builder, variant| { - let preamble = builder.preamble(&variant); - let body = builder.body(&variant); + let preamble = builder.preamble(variant); + let body = builder.body(variant); let diag = &builder.parent.diag; let DiagnosticDeriveKind::Diagnostic { handler } = &builder.parent.kind else { @@ -39,7 +39,7 @@ impl<'a> DiagnosticDerive<'a> { let init = match builder.slug.value_ref() { None => { span_err(builder.span, "diagnostic slug not specified") - .help(&format!( + .help(format!( "specify the slug as the first argument to the `#[diag(...)]` \ attribute, such as `#[diag(hir_analysis_example_error)]`", )) @@ -48,10 +48,10 @@ impl<'a> DiagnosticDerive<'a> { } Some(slug) if let Some( Mismatch { slug_name, crate_name, slug_prefix }) = Mismatch::check(slug) => { span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match") - .note(&format!( + .note(format!( "slug is `{slug_name}` but the crate name is `{crate_name}`" )) - .help(&format!( + .help(format!( "expected a slug starting with `{slug_prefix}_...`" )) .emit(); @@ -113,8 +113,8 @@ impl<'a> LintDiagnosticDerive<'a> { let LintDiagnosticDerive { mut structure, mut builder } = self; let implementation = builder.each_variant(&mut structure, |mut builder, variant| { - let preamble = builder.preamble(&variant); - let body = builder.body(&variant); + let preamble = builder.preamble(variant); + let body = builder.body(variant); let diag = &builder.parent.diag; let formatting_init = &builder.formatting_init; @@ -128,28 +128,28 @@ impl<'a> LintDiagnosticDerive<'a> { let msg = builder.each_variant(&mut structure, |mut builder, variant| { // Collect the slug by generating the preamble. - let _ = builder.preamble(&variant); + let _ = builder.preamble(variant); match builder.slug.value_ref() { None => { span_err(builder.span, "diagnostic slug not specified") - .help(&format!( + .help(format!( "specify the slug as the first argument to the attribute, such as \ `#[diag(compiletest_example)]`", )) .emit(); - return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + DiagnosticDeriveError::ErrorHandled.to_compile_error() } Some(slug) if let Some( Mismatch { slug_name, crate_name, slug_prefix }) = Mismatch::check(slug) => { span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match") - .note(&format!( + .note(format!( "slug is `{slug_name}` but the crate name is `{crate_name}`" )) - .help(&format!( + .help(format!( "expected a slug starting with `{slug_prefix}_...`" )) .emit(); - return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + DiagnosticDeriveError::ErrorHandled.to_compile_error() } Some(slug) => { quote! { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 3ea83fd09c7..9f2ac5112f1 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -100,7 +100,7 @@ impl DiagnosticDeriveBuilder { _ => variant.ast().ident.span().unwrap(), }; let builder = DiagnosticDeriveVariantBuilder { - parent: &self, + parent: self, span, field_map: build_field_mapping(variant), formatting_init: TokenStream::new(), @@ -211,7 +211,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { nested_iter.next(); } Some(NestedMeta::Meta(Meta::NameValue { .. })) => {} - Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| diag + Some(nested_attr) => throw_invalid_nested_attr!(attr, nested_attr, |diag| diag .help("a diagnostic slug is required as the first argument")), None => throw_invalid_attr!(attr, &meta, |diag| diag .help("a diagnostic slug is required as the first argument")), @@ -227,13 +227,13 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { .. })) => (value, path), NestedMeta::Meta(Meta::Path(_)) => { - invalid_nested_attr(attr, &nested_attr) + invalid_nested_attr(attr, nested_attr) .help("diagnostic slug must be the first argument") .emit(); continue; } _ => { - invalid_nested_attr(attr, &nested_attr).emit(); + invalid_nested_attr(attr, nested_attr).emit(); continue; } }; @@ -251,7 +251,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }); } - _ => invalid_nested_attr(attr, &nested_attr) + _ => invalid_nested_attr(attr, nested_attr) .help("only `code` is a valid nested attributes following the slug") .emit(), } @@ -427,9 +427,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) } SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { - if type_matches_path(&info.ty, &["rustc_span", "Span"]) { + if type_matches_path(info.ty, &["rustc_span", "Span"]) { Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) - } else if type_is_unit(&info.ty) { + } else if type_is_unit(info.ty) { Ok(self.add_subdiagnostic(&fn_ident, slug)) } else { report_type_error(attr, "`Span` or `()`")? diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index fa0ca5a5242..446aebe4f83 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -409,7 +409,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut code = None; for nested_attr in list.nested.iter() { let NestedMeta::Meta(ref meta) = nested_attr else { - throw_invalid_nested_attr!(attr, &nested_attr); + throw_invalid_nested_attr!(attr, nested_attr); }; let span = meta.span().unwrap(); @@ -427,7 +427,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { ); code.set_once((code_field, formatting_init), span); } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + _ => throw_invalid_nested_attr!(attr, nested_attr, |diag| { diag.help("`code` is the only valid nested attribute") }), } diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index dff088b9bdf..da90233523c 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -80,7 +80,7 @@ fn report_error_if_not_applied_to_ty( path: &[&str], ty_name: &str, ) -> Result<(), DiagnosticDeriveError> { - if !type_matches_path(&info.ty, path) { + if !type_matches_path(info.ty, path) { report_type_error(attr, ty_name)?; } @@ -105,8 +105,8 @@ pub(crate) fn report_error_if_not_applied_to_span( attr: &Attribute, info: &FieldInfo<'_>, ) -> Result<(), DiagnosticDeriveError> { - if !type_matches_path(&info.ty, &["rustc_span", "Span"]) - && !type_matches_path(&info.ty, &["rustc_errors", "MultiSpan"]) + if !type_matches_path(info.ty, &["rustc_span", "Span"]) + && !type_matches_path(info.ty, &["rustc_errors", "MultiSpan"]) { report_type_error(attr, "`Span` or `MultiSpan`")?; } @@ -686,7 +686,7 @@ impl SubdiagnosticKind { let meta = match nested_attr { NestedMeta::Meta(ref meta) => meta, NestedMeta::Lit(_) => { - invalid_nested_attr(attr, &nested_attr).emit(); + invalid_nested_attr(attr, nested_attr).emit(); continue; } }; @@ -698,7 +698,7 @@ impl SubdiagnosticKind { let string_value = match meta { Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value), - Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + Meta::Path(_) => throw_invalid_nested_attr!(attr, nested_attr, |diag| { diag.help("a diagnostic slug must be the first argument to the attribute") }), _ => None, @@ -720,7 +720,7 @@ impl SubdiagnosticKind { | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, ) => { let Some(value) = string_value else { - invalid_nested_attr(attr, &nested_attr).emit(); + invalid_nested_attr(attr, nested_attr).emit(); continue; }; @@ -736,7 +736,7 @@ impl SubdiagnosticKind { | SubdiagnosticKind::MultipartSuggestion { .. }, ) => { let Some(value) = string_value else { - invalid_nested_attr(attr, &nested_attr).emit(); + invalid_nested_attr(attr, nested_attr).emit(); continue; }; @@ -752,19 +752,19 @@ impl SubdiagnosticKind { // Invalid nested attribute (_, SubdiagnosticKind::Suggestion { .. }) => { - invalid_nested_attr(attr, &nested_attr) + invalid_nested_attr(attr, nested_attr) .help( "only `style`, `code` and `applicability` are valid nested attributes", ) .emit(); } (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { - invalid_nested_attr(attr, &nested_attr) + invalid_nested_attr(attr, nested_attr) .help("only `style` and `applicability` are valid nested attributes") .emit() } _ => { - invalid_nested_attr(attr, &nested_attr).emit(); + invalid_nested_attr(attr, nested_attr).emit(); } } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4617c17b153..1bd8f953508 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1022,7 +1022,7 @@ impl<'hir> Map<'hir> { .. }) => { // Ensure that the returned span has the item's SyntaxContext. - fn_decl_span.find_ancestor_in_same_ctxt(*span).unwrap_or(*span) + fn_decl_span.find_ancestor_inside(*span).unwrap_or(*span) } _ => self.span_with_body(hir_id), }; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 20dde64e51b..a513444e1e0 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -100,13 +100,9 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { /// pass will be named after the type, and it will consist of a main /// loop that goes over each available MIR and applies `run_pass`. pub trait MirPass<'tcx> { - fn name(&self) -> Cow<'_, str> { + fn name(&self) -> &str { let name = std::any::type_name::<Self>(); - if let Some(tail) = name.rfind(':') { - Cow::from(&name[tail + 1..]) - } else { - Cow::from(name) - } + if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name } } /// Returns `true` if this pass is enabled with the current combination of compiler flags. @@ -182,35 +178,6 @@ impl RuntimePhase { } } -impl Display for MirPhase { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - MirPhase::Built => write!(f, "built"), - MirPhase::Analysis(p) => write!(f, "analysis-{}", p), - MirPhase::Runtime(p) => write!(f, "runtime-{}", p), - } - } -} - -impl Display for AnalysisPhase { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - AnalysisPhase::Initial => write!(f, "initial"), - AnalysisPhase::PostCleanup => write!(f, "post_cleanup"), - } - } -} - -impl Display for RuntimePhase { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - RuntimePhase::Initial => write!(f, "initial"), - RuntimePhase::PostCleanup => write!(f, "post_cleanup"), - RuntimePhase::Optimized => write!(f, "optimized"), - } - } -} - /// Where a specific `mir::Body` comes from. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] @@ -368,7 +335,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Built, - pass_count: 1, + pass_count: 0, source, basic_blocks: BasicBlocks::new(basic_blocks), source_scopes, @@ -403,7 +370,7 @@ impl<'tcx> Body<'tcx> { pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self { let mut body = Body { phase: MirPhase::Built, - pass_count: 1, + pass_count: 0, source: MirSource::item(CRATE_DEF_ID.to_def_id()), basic_blocks: BasicBlocks::new(basic_blocks), source_scopes: IndexVec::new(), diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 1cac656674d..2a4ff4b8810 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -16,7 +16,6 @@ use rustc_middle::mir::interpret::{ Pointer, Provenance, }; use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::MirSource; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_target::abi::Size; @@ -74,7 +73,7 @@ pub enum PassWhere { #[inline] pub fn dump_mir<'tcx, F>( tcx: TyCtxt<'tcx>, - pass_num: Option<&dyn Display>, + pass_num: bool, pass_name: &str, disambiguator: &dyn Display, body: &Body<'tcx>, @@ -111,7 +110,7 @@ pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> fn dump_matched_mir_node<'tcx, F>( tcx: TyCtxt<'tcx>, - pass_num: Option<&dyn Display>, + pass_num: bool, pass_name: &str, disambiguator: &dyn Display, body: &Body<'tcx>, @@ -120,8 +119,7 @@ fn dump_matched_mir_node<'tcx, F>( F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { let _: io::Result<()> = try { - let mut file = - create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body.source)?; + let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body)?; // see notes on #41697 above let def_path = ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); @@ -143,16 +141,14 @@ fn dump_matched_mir_node<'tcx, F>( if tcx.sess.opts.unstable_opts.dump_mir_graphviz { let _: io::Result<()> = try { - let mut file = - create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, body.source)?; + let mut file = create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, body)?; write_mir_fn_graphviz(tcx, body, false, &mut file)?; }; } if let Some(spanview) = tcx.sess.opts.unstable_opts.dump_mir_spanview { let _: io::Result<()> = try { - let file_basename = - dump_file_basename(tcx, pass_num, pass_name, disambiguator, body.source); + let file_basename = dump_file_basename(tcx, pass_num, pass_name, disambiguator, body); let mut file = create_dump_file_with_basename(tcx, &file_basename, "html")?; if body.source.def_id().is_local() { write_mir_fn_spanview(tcx, body, spanview, &file_basename, &mut file)?; @@ -165,11 +161,12 @@ fn dump_matched_mir_node<'tcx, F>( /// where we should dump a MIR representation output files. fn dump_file_basename<'tcx>( tcx: TyCtxt<'tcx>, - pass_num: Option<&dyn Display>, + pass_num: bool, pass_name: &str, disambiguator: &dyn Display, - source: MirSource<'tcx>, + body: &Body<'tcx>, ) -> String { + let source = body.source; let promotion_id = match source.promoted { Some(id) => format!("-{:?}", id), None => String::new(), @@ -178,9 +175,10 @@ fn dump_file_basename<'tcx>( let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number { String::new() } else { - match pass_num { - None => ".-------".to_string(), - Some(pass_num) => format!(".{}", pass_num), + if pass_num { + format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count) + } else { + ".-------".to_string() } }; @@ -250,14 +248,14 @@ fn create_dump_file_with_basename( pub fn create_dump_file<'tcx>( tcx: TyCtxt<'tcx>, extension: &str, - pass_num: Option<&dyn Display>, + pass_num: bool, pass_name: &str, disambiguator: &dyn Display, - source: MirSource<'tcx>, + body: &Body<'tcx>, ) -> io::Result<io::BufWriter<fs::File>> { create_dump_file_with_basename( tcx, - &dump_file_basename(tcx, pass_num, pass_name, disambiguator, source), + &dump_file_basename(tcx, pass_num, pass_name, disambiguator, body), extension, ) } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f2030b91b9b..7d2a6bda569 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -89,6 +89,19 @@ pub enum MirPhase { Runtime(RuntimePhase), } +impl MirPhase { + pub fn name(&self) -> &'static str { + match *self { + MirPhase::Built => "built", + MirPhase::Analysis(AnalysisPhase::Initial) => "analysis", + MirPhase::Analysis(AnalysisPhase::PostCleanup) => "analysis-post-cleanup", + MirPhase::Runtime(RuntimePhase::Initial) => "runtime", + MirPhase::Runtime(RuntimePhase::PostCleanup) => "runtime-post-cleanup", + MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized", + } + } +} + /// See [`MirPhase::Analysis`]. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(HashStable)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e1220320eea..d6dea0e9f30 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1109,6 +1109,7 @@ rustc_queries! { desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } separate_provide_extern + feedable } /// Gets the span for the identifier of the definition. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a9a7a2c8b01..c5683a9db94 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1507,7 +1507,9 @@ impl<'tcx> TyCtxt<'tcx> { self.def_path(def_id).to_string_no_crate_verbose() ) } +} +impl<'tcx> TyCtxtAt<'tcx> { /// Create a new definition within the incr. comp. engine. pub fn create_def( self, @@ -1536,9 +1538,13 @@ impl<'tcx> TyCtxt<'tcx> { // - this write will have happened before these queries are called. let def_id = self.definitions.write().create_def(parent, data); - TyCtxtFeed { tcx: self, def_id } + let feed = TyCtxtFeed { tcx: self.tcx, def_id }; + feed.def_span(self.span); + feed } +} +impl<'tcx> TyCtxt<'tcx> { pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx { // Create a dependency to the red node to be sure we re-execute this when the amount of // definitions change. diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 47c1379b308..a7fd1754960 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -344,12 +344,10 @@ macro_rules! define_feedable { match cached { Ok(old) => { - assert_eq!( - value, old, - "Trying to feed an already recorded value for query {} key={key:?}", + bug!( + "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}", stringify!($name), ); - return old; } Err(()) => (), } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index f4562cdfb88..70b98e59a8b 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -32,13 +32,23 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> { } impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> { - fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self { + fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self { let err = tcx.ty_error(); - // FIXME(compiler-errors): It would be nice if we could get the - // query key, so we could at least generate a fn signature that - // has the right arity. + + let arity = if let Some(frame) = stack.get(0) + && frame.query.name == "fn_sig" + && let Some(def_id) = frame.query.def_id + && let Some(node) = tcx.hir().get_if_local(def_id) + && let Some(sig) = node.fn_sig() + { + sig.decl.inputs.len() + sig.decl.implicit_self.has_implicit_self() as usize + } else { + tcx.sess.abort_if_errors(); + unreachable!() + }; + let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig( - [].into_iter(), + std::iter::repeat(err).take(arity), err, false, rustc_hir::Unsafety::Normal, diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 2412824efeb..eb021f47757 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -57,7 +57,7 @@ pub(super) fn build_custom_mir<'tcx>( is_polymorphic: false, tainted_by_errors: None, injection_phase: None, - pass_count: 1, + pass_count: 0, }; body.local_decls.push(LocalDecl::new(return_ty, return_ty_span)); diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index bc75645e7c9..6ddbe69e17e 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -294,14 +294,7 @@ where None if tcx.sess.opts.unstable_opts.dump_mir_dataflow && dump_enabled(tcx, A::NAME, def_id) => { - create_dump_file( - tcx, - ".dot", - None, - A::NAME, - &pass_name.unwrap_or("-----"), - body.source, - )? + create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? } _ => return Ok(()), diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 0f8679b0bd6..d6a298fade4 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -638,7 +638,7 @@ pub(super) fn dump_coverage_spanview<'tcx>( let def_id = mir_source.def_id(); let span_viewables = span_viewables(tcx, mir_body, basic_coverage_blocks, &coverage_spans); - let mut file = create_dump_file(tcx, "html", None, pass_name, &0, mir_source) + let mut file = create_dump_file(tcx, "html", false, pass_name, &0, mir_body) .expect("Unexpected error creating MIR spanview HTML file"); let crate_name = tcx.crate_name(def_id.krate); let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate(); @@ -739,7 +739,7 @@ pub(super) fn dump_coverage_graphviz<'tcx>( .join("\n ") )); } - let mut file = create_dump_file(tcx, "dot", None, pass_name, &0, mir_source) + let mut file = create_dump_file(tcx, "dot", false, pass_name, &0, mir_body) .expect("Unexpected error creating BasicCoverageBlock graphviz DOT file"); graphviz_writer .write_graphviz(tcx, &mut file) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 8cd44ab82cc..97485c4f57b 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -787,7 +787,7 @@ fn dest_prop_mir_dump<'body, 'tcx>( round: usize, ) { let mut reachable = None; - dump_mir(tcx, None, "DestinationPropagation-dataflow", &round, body, |pass_where, w| { + dump_mir(tcx, false, "DestinationPropagation-dataflow", &round, body, |pass_where, w| { let reachable = reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body)); match pass_where { diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 6b995141a2b..778ae63c5a4 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -1,6 +1,5 @@ //! This pass just dumps MIR at a specified point. -use std::borrow::Cow; use std::fs::File; use std::io; @@ -13,8 +12,8 @@ use rustc_session::config::{OutputFilenames, OutputType}; pub struct Marker(pub &'static str); impl<'tcx> MirPass<'tcx> for Marker { - fn name(&self) -> Cow<'_, str> { - Cow::Borrowed(self.0) + fn name(&self) -> &str { + self.0 } fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index ffe4d43bc88..8922298ecaf 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1000,7 +1000,7 @@ fn create_generator_drop_shim<'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(tcx, &mut body); - dump_mir(tcx, None, "generator_drop", &0, &body, |_, _| Ok(())); + dump_mir(tcx, false, "generator_drop", &0, &body, |_, _| Ok(())); body } @@ -1171,7 +1171,7 @@ fn create_generator_resume_function<'tcx>( // unrelated code from the drop part of the function simplify::remove_dead_blocks(tcx, body); - dump_mir(tcx, None, "generator_resume", &0, body, |_, _| Ok(())); + dump_mir(tcx, false, "generator_resume", &0, body, |_, _| Ok(())); } fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { @@ -1394,14 +1394,14 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // This is expanded to a drop ladder in `elaborate_generator_drops`. let drop_clean = insert_clean_drop(body); - dump_mir(tcx, None, "generator_pre-elab", &0, body, |_, _| Ok(())); + dump_mir(tcx, false, "generator_pre-elab", &0, body, |_, _| Ok(())); // Expand `drop(generator_struct)` to a drop ladder which destroys upvars. // If any upvars are moved out of, drop elaboration will handle upvar destruction. // However we need to also elaborate the code generated by `insert_clean_drop`. elaborate_generator_drops(tcx, body); - dump_mir(tcx, None, "generator_post-transform", &0, body, |_, _| Ok(())); + dump_mir(tcx, false, "generator_post-transform", &0, body, |_, _| Ok(())); // Create a copy of our MIR and use it to create the drop shim for the generator let drop_shim = create_generator_drop_shim(tcx, &transform, gen_ty, body, drop_clean); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9174f04887e..bf670c5c26a 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -363,10 +363,6 @@ impl<'tcx> Inliner<'tcx> { return Err("C variadic"); } - if callee_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { - return Err("naked"); - } - if callee_attrs.flags.contains(CodegenFnAttrFlags::COLD) { return Err("cold"); } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 27dbc3e22c9..e1b65823a5a 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -1,5 +1,3 @@ -use std::borrow::Cow; - use rustc_middle::mir::{self, Body, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -8,13 +6,9 @@ use crate::{validate, MirPass}; /// Just like `MirPass`, except it cannot mutate `Body`. pub trait MirLint<'tcx> { - fn name(&self) -> Cow<'_, str> { + fn name(&self) -> &str { let name = std::any::type_name::<Self>(); - if let Some(tail) = name.rfind(':') { - Cow::from(&name[tail + 1..]) - } else { - Cow::from(name) - } + if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name } } fn is_enabled(&self, _sess: &Session) -> bool { @@ -32,7 +26,7 @@ impl<'tcx, T> MirPass<'tcx> for Lint<T> where T: MirLint<'tcx>, { - fn name(&self) -> Cow<'_, str> { + fn name(&self) -> &str { self.0.name() } @@ -55,7 +49,7 @@ impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel<T> where T: MirPass<'tcx>, { - fn name(&self) -> Cow<'_, str> { + fn name(&self) -> &str { self.1.name() } @@ -146,10 +140,11 @@ fn run_passes_inner<'tcx>( } body.phase = new_phase; + body.pass_count = 0; dump_mir_for_phase_change(tcx, body); if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) { - validate_body(tcx, body, format!("after phase change to {}", new_phase)); + validate_body(tcx, body, format!("after phase change to {}", new_phase.name())); } body.pass_count = 1; @@ -166,11 +161,9 @@ pub fn dump_mir_for_pass<'tcx>( pass_name: &str, is_after: bool, ) { - let phase_index = body.phase.phase_index(); - mir::dump_mir( tcx, - Some(&format_args!("{:03}-{:03}", phase_index, body.pass_count)), + true, pass_name, if is_after { &"after" } else { &"before" }, body, @@ -179,14 +172,6 @@ pub fn dump_mir_for_pass<'tcx>( } pub fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { - let phase_index = body.phase.phase_index(); - - mir::dump_mir( - tcx, - Some(&format_args!("{:03}-000", phase_index)), - &format!("{}", body.phase), - &"after", - body, - |_, _| Ok(()), - ) + assert_eq!(body.pass_count, 0); + mir::dump_mir(tcx, true, body.phase.name(), &"after", body, |_, _| Ok(())) } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 57d372fda56..475e2ec9a1d 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -35,7 +35,6 @@ use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Vis use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use smallvec::SmallVec; -use std::borrow::Cow; use std::convert::TryInto; pub struct SimplifyCfg { @@ -57,8 +56,8 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } impl<'tcx> MirPass<'tcx> for SimplifyCfg { - fn name(&self) -> Cow<'_, str> { - Cow::Borrowed(&self.label) + fn name(&self) -> &str { + &self.label } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 3bbae5b8976..405ebce4d22 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -2,8 +2,6 @@ use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use std::borrow::Cow; - /// A pass that replaces a branch with a goto when its condition is known. pub struct SimplifyConstCondition { label: String, @@ -16,8 +14,8 @@ impl SimplifyConstCondition { } impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { - fn name(&self) -> Cow<'_, str> { - Cow::Borrowed(&self.label) + fn name(&self) -> &str { + &self.label } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e0443a697b5..fe3cfde2e63 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2060,7 +2060,7 @@ impl<'a> Parser<'a> { }; let capture_clause = self.parse_capture_clause()?; - let fn_decl = self.parse_fn_block_decl()?; + let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?; let decl_hi = self.prev_token.span; let mut body = match fn_decl.output { FnRetTy::Default(_) => { @@ -2101,6 +2101,7 @@ impl<'a> Parser<'a> { fn_decl, body, fn_decl_span: lo.to(decl_hi), + fn_arg_span, })), ); @@ -2129,7 +2130,9 @@ impl<'a> Parser<'a> { } /// Parses the `|arg, arg|` header of a closure. - fn parse_fn_block_decl(&mut self) -> PResult<'a, P<FnDecl>> { + fn parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)> { + let arg_start = self.token.span.lo(); + let inputs = if self.eat(&token::OrOr) { Vec::new() } else { @@ -2145,10 +2148,11 @@ impl<'a> Parser<'a> { self.expect_or()?; args }; + let arg_span = self.prev_token.span.with_lo(arg_start); let output = self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?; - Ok(P(FnDecl { inputs, output })) + Ok((P(FnDecl { inputs, output }), arg_span)) } /// Parses a parameter in a closure header (e.g., `|arg, arg|`). diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 767fb9378be..84c63219920 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1012,7 +1012,7 @@ impl<'a> Parser<'a> { prefix.span = lo.to(self.prev_token.span); } - UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID) + UseTreeKind::Simple(self.parse_rename()?) } }; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index ff1ddfd97df..42197e63797 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -72,14 +72,22 @@ impl<'a> Parser<'a> { Ok(Some(if self.token.is_keyword(kw::Let) { self.parse_local_mk(lo, attrs, capture_semi, force_collect)? - } else if self.is_kw_followed_by_ident(kw::Mut) { - self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::MissingLet)? - } else if self.is_kw_followed_by_ident(kw::Auto) { + } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() { + self.recover_stmt_local_after_let(lo, attrs, InvalidVariableDeclarationSub::MissingLet)? + } else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() { self.bump(); // `auto` - self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotAuto)? - } else if self.is_kw_followed_by_ident(sym::var) { + self.recover_stmt_local_after_let( + lo, + attrs, + InvalidVariableDeclarationSub::UseLetNotAuto, + )? + } else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() { self.bump(); // `var` - self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotVar)? + self.recover_stmt_local_after_let( + lo, + attrs, + InvalidVariableDeclarationSub::UseLetNotVar, + )? } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something @@ -213,13 +221,21 @@ impl<'a> Parser<'a> { } } - fn recover_stmt_local( + fn recover_stmt_local_after_let( &mut self, lo: Span, attrs: AttrWrapper, subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub, ) -> PResult<'a, Stmt> { - let stmt = self.recover_local_after_let(lo, attrs)?; + let stmt = + self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| { + let local = this.parse_local(attrs)?; + // FIXME - maybe capture semicolon in recovery? + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), + TrailingToken::None, + )) + })?; self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) }); Ok(stmt) } @@ -243,17 +259,6 @@ impl<'a> Parser<'a> { }) } - fn recover_local_after_let(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> { - self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { - let local = this.parse_local(attrs)?; - // FIXME - maybe capture semicolon in recovery? - Ok(( - this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), - TrailingToken::None, - )) - }) - } - /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> { let lo = self.prev_token.span; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 5d0224c35f3..da023fcf4c3 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -433,7 +433,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.in_pat = false; } - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { self.handle_res(path.res); intravisit::walk_path(self, path); } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 140f02c046a..a7854cd4998 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -369,7 +369,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, p: &'v hir::Path<'v>, hir_id: hir::HirId) { + fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: hir::HirId) { // This is `visit_use`, but the type is `Path` so record it that way. self.record("Path", Id::None, p); hir_visit::walk_use(self, p, hir_id) @@ -442,7 +442,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_lifetime(self, lifetime) } - fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'v>, _id: hir::HirId) { self.record("Path", Id::None, path); hir_visit::walk_path(self, path) } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 88bd655d8d3..da715523474 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -787,7 +787,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { intravisit::walk_item(self, item); } - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { let method_span = path.segments.last().map(|s| s.ident.span); let item_is_allowed = self.tcx.check_stability_allow_unstable( @@ -880,7 +880,7 @@ struct CheckTraitImplStable<'tcx> { } impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _id: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { if let Some(stab) = self.tcx.lookup_stability(def_id) { self.fully_stable &= stab.level.is_stable(); diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index 9e41efce9ce..605cf0a93b8 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -66,7 +66,7 @@ impl CaptureCollector<'_, '_> { } impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> { - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { if let Res::Local(var_id) = path.res { self.visit_local_use(var_id, path.span); } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index e44857a0238..30d28ff3455 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -532,7 +532,8 @@ impl<K: DepKind> DepGraph<K> { let mut edges = SmallVec::new(); K::read_deps(|task_deps| match task_deps { TaskDepsRef::Allow(deps) => edges.extend(deps.lock().reads.iter().copied()), - TaskDepsRef::Ignore | TaskDepsRef::Forbid => { + TaskDepsRef::Ignore => {} // During HIR lowering, we have no dependencies. + TaskDepsRef::Forbid => { panic!("Cannot summarize when dependencies are not recorded.") } }); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 91ac442431d..9c90d67aadf 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -445,19 +445,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot }; match use_tree.kind { - ast::UseTreeKind::Simple(rename, id1, id2) => { + ast::UseTreeKind::Simple(rename) => { let mut ident = use_tree.ident(); let mut module_path = prefix; let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; self.r.visibilities.insert(self.r.local_def_id(id), vis); - if id1 != ast::DUMMY_NODE_ID { - self.r.visibilities.insert(self.r.local_def_id(id1), vis); - } - if id2 != ast::DUMMY_NODE_ID { - self.r.visibilities.insert(self.r.local_def_id(id2), vis); - } if nested { // Correctly handle `self` @@ -565,7 +559,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { type_ns_only, nested, id, - additional_ids: (id1, id2), }; self.add_import(module_path, kind, use_tree.span, item, root_span, item.id, vis); @@ -621,11 +614,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let new_span = prefix[prefix.len() - 1].ident.span; let tree = ast::UseTree { prefix: ast::Path::from_ident(Ident::new(kw::SelfLower, new_span)), - kind: ast::UseTreeKind::Simple( - Some(Ident::new(kw::Underscore, new_span)), - ast::DUMMY_NODE_ID, - ast::DUMMY_NODE_ID, - ), + kind: ast::UseTreeKind::Simple(Some(Ident::new(kw::Underscore, new_span))), span: use_tree.span, }; self.build_reduced_graph_for_use_tree( diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index bf2428e1731..2764a6c28a5 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -158,14 +158,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { self.create_def(id, DefPathData::Use, use_tree.span); - match use_tree.kind { - UseTreeKind::Simple(_, id1, id2) => { - self.create_def(id1, DefPathData::Use, use_tree.prefix.span); - self.create_def(id2, DefPathData::Use, use_tree.prefix.span); - } - UseTreeKind::Glob => (), - UseTreeKind::Nested(..) => {} - } visit::walk_use_tree(self, use_tree, id); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bc3a710e84b..f6b6cf3a94c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1840,13 +1840,16 @@ impl<'a> Resolver<'a> { (format!("use of undeclared type `{}`", ident), suggestion) } else { - let suggestion = if ident.name == sym::alloc { - Some(( + let mut suggestion = None; + if ident.name == sym::alloc { + suggestion = Some(( vec![], String::from("add `extern crate alloc` to use the `alloc` crate"), Applicability::MaybeIncorrect, )) - } else { + } + + suggestion = suggestion.or_else(|| { self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map( |sugg| { ( @@ -1856,7 +1859,7 @@ impl<'a> Resolver<'a> { ) }, ) - }; + }); (format!("use of undeclared crate or module `{}`", ident), suggestion) } } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 3aa8d52db03..85399385d1f 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -1,4 +1,4 @@ -use crate::{ImportKind, NameBinding, NameBindingKind, Resolver, ResolverTree}; +use crate::{NameBinding, NameBindingKind, Resolver, ResolverTree}; use rustc_ast::ast; use rustc_ast::visit; use rustc_ast::visit::Visitor; @@ -104,28 +104,11 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { for (binding, eff_vis) in visitor.import_effective_visibilities.iter() { let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; if let Some(node_id) = import.id() { - let mut update = |node_id| { - r.effective_visibilities.update_eff_vis( - r.local_def_id(node_id), - eff_vis, - ResolverTree(&r.definitions, &r.crate_loader), - ) - }; - update(node_id); - if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { - // In theory all the single import IDs have individual visibilities and - // effective visibilities, but in practice these IDs go straight to HIR - // where all their few uses assume that their (effective) visibility - // applies to the whole syntactic `use` item. So they all get the same - // value which is the maximum of all bindings. Maybe HIR for imports - // shouldn't use three IDs at all. - if id1 != ast::DUMMY_NODE_ID { - update(id1); - } - if id2 != ast::DUMMY_NODE_ID { - update(id2); - } - } + r.effective_visibilities.update_eff_vis( + r.local_def_id(node_id), + eff_vis, + ResolverTree(&r.definitions, &r.crate_loader), + ) } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 2366b94732e..b100a8c17cf 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -4,7 +4,10 @@ use crate::diagnostics::{import_candidates, Suggestion}; use crate::Determinacy::{self, *}; use crate::Namespace::*; use crate::{module_to_string, names_to_string, ImportSuggestion}; -use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; +use crate::{ + AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, ModuleKind, ResolutionError, + Resolver, Segment, +}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; use crate::{NameBinding, NameBindingKind, PathResult}; @@ -56,9 +59,6 @@ pub enum ImportKind<'a> { /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree` /// for `a` in this field. id: NodeId, - /// Additional `NodeId`s allocated to a `ast::UseTree` for automatically generated `use` statement - /// (eg. implicit struct constructors) - additional_ids: (NodeId, NodeId), }, Glob { is_prelude: bool, @@ -88,7 +88,6 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { ref type_ns_only, ref nested, ref id, - ref additional_ids, // Ignore the following to avoid an infinite loop while printing. source_bindings: _, target_bindings: _, @@ -99,7 +98,6 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { .field("type_ns_only", type_ns_only) .field("nested", nested) .field("id", id) - .field("additional_ids", additional_ids) .finish_non_exhaustive(), Glob { ref is_prelude, ref max_vis, ref id } => f .debug_struct("Glob") @@ -796,7 +794,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { match binding { Ok(binding) => { // Consistency checks, analogous to `finalize_macro_resolutions`. - let initial_res = source_bindings[ns].get().map(|initial_binding| { + let initial_binding = source_bindings[ns].get().map(|initial_binding| { all_ns_err = false; if let Some(target_binding) = target_bindings[ns].get() { if target.name == kw::Underscore @@ -810,12 +808,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ); } } - initial_binding.res() + initial_binding }); let res = binding.res(); - if let Ok(initial_res) = initial_res { + if let Ok(initial_binding) = initial_binding { + let initial_res = initial_binding.res(); if res != initial_res && this.ambiguity_errors.is_empty() { - span_bug!(import.span, "inconsistent resolution for an import"); + this.ambiguity_errors.push(AmbiguityError { + kind: AmbiguityKind::Import, + ident, + b1: initial_binding, + b2: binding, + misc1: AmbiguityErrorMisc::None, + misc2: AmbiguityErrorMisc::None, + }); } } else if res != Res::Err && this.ambiguity_errors.is_empty() diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2d2408c061e..51a53f7b37c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3365,13 +3365,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Before we start looking for candidates, we have to get our hands // on the type user is trying to perform invocation on; basically: // we're transforming `HashMap::new` into just `HashMap`. - let path = match path.split_last() { + let prefix_path = match path.split_last() { Some((_, path)) if !path.is_empty() => path, _ => return Some(parent_err), }; let (mut err, candidates) = - this.smart_resolve_report_errors(path, path_span, PathSource::Type, None); + this.smart_resolve_report_errors(prefix_path, path_span, PathSource::Type, None); // There are two different error messages user might receive at // this point: @@ -3415,11 +3415,23 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if this.should_report_errs() { if candidates.is_empty() { - // When there is no suggested imports, we can just emit the error - // and suggestions immediately. Note that we bypass the usually error - // reporting routine (ie via `self.r.report_error`) because we need - // to post-process the `ResolutionError` above. - err.emit(); + if path.len() == 2 && prefix_path.len() == 1 { + // Delay to check whether methond name is an associated function or not + // ``` + // let foo = Foo {}; + // foo::bar(); // possibly suggest to foo.bar(); + //``` + err.stash( + prefix_path[0].ident.span, + rustc_errors::StashKey::CallAssocMethod, + ); + } else { + // When there is no suggested imports, we can just emit the error + // and suggestions immediately. Note that we bypass the usually error + // reporting routine (ie via `self.r.report_error`) because we need + // to post-process the `ResolutionError` above. + err.emit(); + } } else { // If there are suggested imports, the error reporting is delayed this.r.use_injections.push(UseError { @@ -3428,7 +3440,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { def_id, instead: false, suggestion: None, - path: path.into(), + path: prefix_path.into(), is_call: source.is_call(), }); } diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index fae20c2ba5f..b4528853825 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -185,13 +185,13 @@ impl<'tcx> DumpVisitor<'tcx> { } } - fn write_sub_paths(&mut self, path: &'tcx hir::Path<'tcx>) { + fn write_sub_paths<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) { self.write_segments(path.segments) } // As write_sub_paths, but does not process the last ident in the path (assuming it // will be processed elsewhere). See note on write_sub_paths about global. - fn write_sub_paths_truncated(&mut self, path: &'tcx hir::Path<'tcx>) { + fn write_sub_paths_truncated<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) { if let [segments @ .., _] = path.segments { self.write_segments(segments) } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 4fa0c14715e..f05eb2b7432 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -594,7 +594,9 @@ impl<'tcx> SaveContext<'tcx> { match self.tcx.hir().get(hir_id) { Node::TraitRef(tr) => tr.path.res, - Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => path.res, + Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => { + path.res.get(0).copied().unwrap_or(Res::Err) + } Node::PathSegment(seg) => { if seg.res != Res::Err { seg.res diff --git a/compiler/rustc_session/src/cgu_reuse_tracker.rs b/compiler/rustc_session/src/cgu_reuse_tracker.rs index 2336d99363f..8703e575465 100644 --- a/compiler/rustc_session/src/cgu_reuse_tracker.rs +++ b/compiler/rustc_session/src/cgu_reuse_tracker.rs @@ -121,7 +121,7 @@ impl CguReuseTracker { let at_least = if at_least { 1 } else { 0 }; IncorrectCguReuseType { span: error_span.0, - cgu_user_name: &cgu_user_name, + cgu_user_name, actual_reuse, expected_reuse, at_least, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 927810351e9..d8c4b0845d0 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -622,7 +622,7 @@ impl OutputFilenames { /// should be placed on disk. pub fn output_path(&self, flavor: OutputType) -> PathBuf { let extension = flavor.extension(); - self.with_directory_and_extension(&self.out_directory, &extension) + self.with_directory_and_extension(&self.out_directory, extension) } /// Gets the path where a compilation artifact of the given type for the @@ -659,7 +659,7 @@ impl OutputFilenames { let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); - self.with_directory_and_extension(&temps_directory, &extension) + self.with_directory_and_extension(temps_directory, &extension) } pub fn with_extension(&self, extension: &str) -> PathBuf { @@ -1159,7 +1159,7 @@ impl CrateCheckConfig { values_target_family .extend(target.options.families.iter().map(|family| Symbol::intern(family))); values_target_arch.insert(Symbol::intern(&target.arch)); - values_target_endian.insert(Symbol::intern(&target.options.endian.as_str())); + values_target_endian.insert(Symbol::intern(target.options.endian.as_str())); values_target_env.insert(Symbol::intern(&target.options.env)); values_target_abi.insert(Symbol::intern(&target.options.abi)); values_target_vendor.insert(Symbol::intern(&target.options.vendor)); @@ -1846,7 +1846,7 @@ pub fn parse_target_triple( match matches.opt_str("target") { Some(target) if target.ends_with(".json") => { let path = Path::new(&target); - TargetTriple::from_path(&path).unwrap_or_else(|_| { + TargetTriple::from_path(path).unwrap_or_else(|_| { early_error(error_format, &format!("target file {path:?} does not exist")) }) } @@ -1992,7 +1992,7 @@ fn parse_native_lib_modifiers( ) -> (NativeLibKind, Option<bool>) { let mut verbatim = None; for modifier in modifiers.split(',') { - let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { + let (modifier, value) = match modifier.strip_prefix(['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => early_error( error_format, @@ -2421,7 +2421,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let mut search_paths = vec![]; for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt(&s, error_format)); + search_paths.push(SearchPath::from_cli_opt(s, error_format)); } let libs = parse_libs(matches, error_format); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 9aa8a06c6d3..8cb9e1a6f1a 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -317,7 +317,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: LitError::InvalidIntSuffix => { let suf = suffix.expect("suffix error with no suffix"); let suf = suf.as_str(); - if looks_like_width_suffix(&['i', 'u'], &suf) { + if looks_like_width_suffix(&['i', 'u'], suf) { // If it looks like a width, try to be helpful. sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }); } else if let Some(fixed) = fix_base_capitalisation(suf) { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f9ee202466f..01a9361e786 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1414,8 +1414,6 @@ options! { "run all passes except codegen; no output"), no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED], "omit DWARF address ranges that give faster lookups"), - no_interleave_lints: bool = (false, parse_no_flag, [UNTRACKED], - "execute lints separately; allows benchmarking individual lints"), no_leak_check: bool = (false, parse_no_flag, [UNTRACKED], "disable the 'leak check' for subtyping; unsound, but useful for tests"), no_link: bool = (false, parse_no_flag, [TRACKED], diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index 47aa4dfba42..d3c2c5113bc 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -247,7 +247,7 @@ fn analyze_source_file_generic( // The slow path: // This is either ASCII control character "DEL" or the beginning of // a multibyte char. Just decode to `char`. - let c = (&src[i..]).chars().next().unwrap(); + let c = src[i..].chars().next().unwrap(); char_len = c.len_utf8(); let pos = BytePos::from_usize(i) + output_offset; diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs index fdabf404a37..886112769a9 100644 --- a/compiler/rustc_span/src/caching_source_map_view.rs +++ b/compiler/rustc_span/src/caching_source_map_view.rs @@ -165,7 +165,7 @@ impl<'sm> CachingSourceMapView<'sm> { Some(new_file_and_idx) } else { let file = &self.line_cache[oldest].file; - if !file_contains(&file, span_data.hi) { + if !file_contains(file, span_data.hi) { return None; } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 99a8b03fa39..038699154c7 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -381,7 +381,7 @@ impl HygieneData { } pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T { - with_session_globals(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut())) + with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut())) } #[inline] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 1065cd384a9..cef4c6f79ce 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -238,7 +238,7 @@ impl RealFileName { pub fn remapped_path_if_available(&self) -> &Path { match self { RealFileName::LocalPath(p) - | RealFileName::Remapped { local_path: _, virtual_name: p } => &p, + | RealFileName::Remapped { local_path: _, virtual_name: p } => p, } } diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index b3de6741594..f0e91e5a6a9 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -166,5 +166,5 @@ impl SpanInterner { // If an interner exists, return it. Otherwise, prepare a fresh one. #[inline] fn with_span_interner<T, F: FnOnce(&mut SpanInterner) -> T>(f: F) -> T { - crate::with_session_globals(|session_globals| f(&mut *session_globals.span_interner.lock())) + crate::with_session_globals(|session_globals| f(&mut session_globals.span_interner.lock())) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 739716cfce3..9e446c96db3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1488,6 +1488,7 @@ symbols! { ty, type_alias_enum_variants, type_alias_impl_trait, + type_ascribe, type_ascription, type_changing_struct_update, type_id, @@ -1876,7 +1877,7 @@ impl<S: Encoder> Encodable<S> for Symbol { impl<D: Decoder> Decodable<D> for Symbol { #[inline] default fn decode(d: &mut D) -> Symbol { - Symbol::intern(&d.read_str()) + Symbol::intern(d.read_str()) } } diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index ec8f20fe692..c8b6ac5ae25 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -78,7 +78,7 @@ fn arg_scalar_pair<C>( where C: HasDataLayout, { - data = arg_scalar(cx, &scalar1, offset, data); + data = arg_scalar(cx, scalar1, offset, data); match (scalar1.primitive(), scalar2.primitive()) { (abi::F32, _) => offset += Reg::f32().size, (_, abi::F64) => offset += Reg::f64().size, @@ -90,7 +90,7 @@ where if (offset.bytes() % 4) != 0 && scalar2.primitive().is_float() { offset += Size::from_bytes(4 - (offset.bytes() % 4)); } - data = arg_scalar(cx, &scalar2, offset, data); + data = arg_scalar(cx, scalar2, offset, data); return data; } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 0f6bbc32317..e72cab629ff 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; +use super::apple_base::{macos_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { @@ -10,8 +10,6 @@ pub fn target() -> Target { // FIXME: The leak sanitizer currently fails the tests, see #88132. base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; - base.link_env_remove.to_mut().extend(macos_link_env_remove()); - Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work diff --git a/compiler/rustc_target/src/spec/apple/tests.rs b/compiler/rustc_target/src/spec/apple/tests.rs index d062b36742d..3c90a5e7e93 100644 --- a/compiler/rustc_target/src/spec/apple/tests.rs +++ b/compiler/rustc_target/src/spec/apple/tests.rs @@ -1,6 +1,6 @@ use crate::spec::{ - aarch64_apple_ios_sim, aarch64_apple_watchos_sim, x86_64_apple_ios, x86_64_apple_tvos, - x86_64_apple_watchos_sim, + aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_watchos_sim, i686_apple_darwin, + x86_64_apple_darwin, x86_64_apple_ios, x86_64_apple_tvos, x86_64_apple_watchos_sim, }; #[test] @@ -18,3 +18,18 @@ fn simulator_targets_set_abi() { assert_eq!(target.abi, "sim") } } + +#[test] +fn macos_link_environment_unmodified() { + let all_macos_targets = [ + aarch64_apple_darwin::target(), + i686_apple_darwin::target(), + x86_64_apple_darwin::target(), + ]; + + for target in all_macos_targets { + // macOS targets should only remove information for cross-compiling, but never + // for the host. + assert_eq!(target.link_env_remove, crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET"]); + } +} diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 23c826cb1bd..7f8160b5dec 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -72,16 +72,6 @@ impl Arch { Arm64_sim => "apple-a12", } } - - fn link_env_remove(self) -> StaticCow<[StaticCow<str>]> { - match self { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim - | Arm64_sim => { - cvs!["MACOSX_DEPLOYMENT_TARGET"] - } - X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], - } - } } fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { @@ -140,7 +130,7 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { abi: abi.into(), os: os.into(), cpu: arch.target_cpu().into(), - link_env_remove: arch.link_env_remove(), + link_env_remove: link_env_remove(arch, os), vendor: "apple".into(), linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No), // macOS has -dead_strip, which doesn't rely on function_sections @@ -211,20 +201,38 @@ pub fn macos_llvm_target(arch: Arch) -> String { format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor) } -pub fn macos_link_env_remove() -> Vec<StaticCow<str>> { - let mut env_remove = Vec::with_capacity(2); - // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which - // may occur when we're linking a custom build script while targeting iOS for example. - if let Ok(sdkroot) = env::var("SDKROOT") { - if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") { - env_remove.push("SDKROOT".into()) +fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> { + // Apple platforms only officially support macOS as a host for any compilation. + // + // If building for macOS, we go ahead and remove any erronous environment state + // that's only applicable to cross-OS compilation. Always leave anything for the + // host OS alone though. + if os == "macos" { + let mut env_remove = Vec::with_capacity(2); + // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which + // may occur when we're linking a custom build script while targeting iOS for example. + if let Ok(sdkroot) = env::var("SDKROOT") { + if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") + { + env_remove.push("SDKROOT".into()) + } + } + // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at + // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", + // although this is apparently ignored when using the linker at "/usr/bin/ld". + env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into()); + env_remove.into() + } else { + // Otherwise if cross-compiling for a different OS/SDK, remove any part + // of the linking environment that's wrong and reversed. + match arch { + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim + | Arm64_sim => { + cvs!["MACOSX_DEPLOYMENT_TARGET"] + } + X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], } } - // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at - // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", - // although this is apparently ignored when using the linker at "/usr/bin/ld". - env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into()); - env_remove } fn ios_deployment_target() -> (u32, u32) { diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 8b968af5ecc..ad22467ba9c 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; +use super::apple_base::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { @@ -7,7 +7,6 @@ pub fn target() -> Target { let mut base = opts("macos", arch); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - base.link_env_remove.to_mut().extend(macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.frame_pointer = FramePointer::Always; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 78315afa759..d05b8aa4200 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2658,7 +2658,7 @@ impl Target { // Additionally look in the sysroot under `lib/rustlib/<triple>/target.json` // as a fallback. - let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple); + let rustlib_path = crate::target_rustlib_path(sysroot, target_triple); let p = PathBuf::from_iter([ Path::new(sysroot), Path::new(&rustlib_path), diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index c053031612c..9a3e7a80500 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; +use super::apple_base::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; @@ -8,7 +8,6 @@ pub fn target() -> Target { base.max_atomic_width = Some(128); // core2 supports cmpxchg16b base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); - base.link_env_remove.to_mut().extend(macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 99724fb28db..899e30275a0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -11,8 +11,8 @@ use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::util::impl_subject_and_oblig; use crate::traits::SkipLeakCheck; use crate::traits::{ - self, Normalized, Obligation, ObligationCause, ObligationCtxt, PredicateObligation, - PredicateObligations, SelectionContext, + self, Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations, + SelectionContext, }; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; @@ -30,6 +30,8 @@ use std::fmt::Debug; use std::iter; use std::ops::ControlFlow; +use super::NormalizeExt; + /// Whether we do the orphan check relative to this crate or /// to some remote crate. #[derive(Copy, Clone, Debug)] @@ -128,8 +130,8 @@ fn with_fresh_ty_vars<'cx, 'tcx>( predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates, }; - let Normalized { value: mut header, obligations } = - traits::normalize(selcx, param_env, ObligationCause::dummy(), header); + let InferOk { value: mut header, obligations } = + selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header); header.predicates.extend(obligations.into_iter().map(|o| o.predicate)); header diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 64d01ddb09a..c028e89e4ea 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -112,6 +112,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.register_infer_ok_obligations(infer_ok) } + /// Makes `expected <: actual`. + pub fn eq_exp<T>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + a_is_expected: bool, + a: T, + b: T, + ) -> Result<(), TypeError<'tcx>> + where + T: ToTrace<'tcx>, + { + self.infcx + .at(cause, param_env) + .eq_exp(a_is_expected, a, b) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + pub fn eq<T: ToTrace<'tcx>>( &self, cause: &ObligationCause<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 888f0f7c5b2..3379279dd15 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -71,7 +71,7 @@ pub trait InferCtxtExt<'tcx> { /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to /// `report_arg_count_mismatch`. - fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)>; + fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)>; /// Reports an error when the number of arguments needed by a /// trait match doesn't match the number that the expression @@ -83,6 +83,7 @@ pub trait InferCtxtExt<'tcx> { expected_args: Vec<ArgKind>, found_args: Vec<ArgKind>, is_closure: bool, + closure_pipe_span: Option<Span>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` @@ -135,15 +136,16 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to /// `report_arg_count_mismatch`. - fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)> { + fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)> { let sm = self.tcx.sess.source_map(); let hir = self.tcx.hir(); Some(match node { Node::Expr(&hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }), + kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }), .. }) => ( fn_decl_span, + fn_arg_span, hir.body(body) .params .iter() @@ -174,6 +176,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { kind: hir::TraitItemKind::Fn(ref sig, _), .. }) => ( sig.span, + None, sig.decl .inputs .iter() @@ -188,7 +191,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { ), Node::Ctor(ref variant_data) => { let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id)); - (span, vec![ArgKind::empty(); variant_data.fields().len()]) + (span, None, vec![ArgKind::empty(); variant_data.fields().len()]) } _ => panic!("non-FnLike node found: {:?}", node), }) @@ -204,6 +207,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { expected_args: Vec<ArgKind>, found_args: Vec<ArgKind>, is_closure: bool, + closure_arg_span: Option<Span>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let kind = if is_closure { "closure" } else { "function" }; @@ -241,24 +245,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { if let Some(found_span) = found_span { err.span_label(found_span, format!("takes {}", found_str)); - // move |_| { ... } - // ^^^^^^^^-- def_span - // - // move |_| { ... } - // ^^^^^-- prefix - let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span); - // move |_| { ... } - // ^^^-- pipe_span - let pipe_span = - if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span }; - // Suggest to take and ignore the arguments with expected_args_length `_`s if // found arguments is empty (assume the user just wants to ignore args in this case). // For example, if `expected_args_length` is 2, suggest `|_, _|`. if found_args.is_empty() && is_closure { let underscores = vec!["_"; expected_args.len()].join(", "); err.span_suggestion_verbose( - pipe_span, + closure_arg_span.unwrap_or(found_span), &format!( "consider changing the closure to take and ignore the expected argument{}", pluralize!(expected_args.len()) @@ -1252,13 +1245,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligation.cause.code(), ) } else { - let (closure_span, found) = found_did + let (closure_span, closure_arg_span, found) = found_did .and_then(|did| { let node = self.tcx.hir().get_if_local(did)?; - let (found_span, found) = self.get_fn_like_arguments(node)?; - Some((Some(found_span), found)) + let (found_span, closure_arg_span, found) = + self.get_fn_like_arguments(node)?; + Some((Some(found_span), closure_arg_span, found)) }) - .unwrap_or((found_span, found)); + .unwrap_or((found_span, None, found)); self.report_arg_count_mismatch( span, @@ -1266,6 +1260,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { expected, found, found_trait_ty.is_closure(), + closure_arg_span, ) } } @@ -1577,32 +1572,26 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } self.probe(|_| { - let mut err = error.err; - let mut values = None; + let ocx = ObligationCtxt::new_in_snapshot(self); // try to find the mismatched types to report the error with. // // this can fail if the problem was higher-ranked, in which // cause I have no idea for a good error message. let bound_predicate = predicate.kind(); - if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = + let (values, err) = if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = bound_predicate.skip_binder() { - let mut selcx = SelectionContext::new(self); let data = self.replace_bound_vars_with_fresh_vars( obligation.cause.span, infer::LateBoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); - let mut obligations = vec![]; - // FIXME(normalization): Change this to use `At::normalize` - let normalized_ty = super::normalize_projection_type( - &mut selcx, + let normalized_ty = ocx.normalize( + &obligation.cause, obligation.param_env, - data.projection_ty, - obligation.cause.clone(), - 0, - &mut obligations, + self.tcx + .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs), ); debug!(?obligation.cause, ?obligation.param_env); @@ -1618,19 +1607,34 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::OpaqueType ); - if let Err(new_err) = self.at(&obligation.cause, obligation.param_env).eq_exp( + let expected_ty = data.term.ty().unwrap(); + + // constrain inference variables a bit more to nested obligations from normalize so + // we can have more helpful errors. + ocx.select_where_possible(); + + if let Err(new_err) = ocx.eq_exp( + &obligation.cause, + obligation.param_env, is_normalized_ty_expected, normalized_ty, - data.term, + expected_ty, ) { - values = Some((data, is_normalized_ty_expected, normalized_ty, data.term)); - err = new_err; + (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err) + } else { + (None, error.err) } - } + } else { + (None, error.err) + }; let msg = values .and_then(|(predicate, _, normalized_ty, expected_ty)| { - self.maybe_detailed_projection_msg(predicate, normalized_ty, expected_ty) + self.maybe_detailed_projection_msg( + predicate, + normalized_ty.into(), + expected_ty.into(), + ) }) .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate)); let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); @@ -1672,11 +1676,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &mut diag, &obligation.cause, secondary_span, - values.map(|(_, is_normalized_ty_expected, normalized_ty, term)| { + values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| { infer::ValuePairs::Terms(ExpectedFound::new( is_normalized_ty_expected, - normalized_ty, - term, + normalized_ty.into(), + expected_ty.into(), )) }), err, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 371367f0deb..c6818a4e57d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -56,7 +56,6 @@ pub use self::object_safety::astconv_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::ObjectSafetyViolation; -pub(crate) use self::project::{normalize, normalize_to}; pub use self::project::{normalize_projection_type, NormalizeExt}; pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 113803cd179..051660be9c4 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -50,6 +50,10 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>> pub(super) struct InProgress; pub trait NormalizeExt<'tcx> { + /// Normalize a value using the `AssocTypeNormalizer`. + /// + /// This normalization should be used when the type contains inference variables or the + /// projection may be fallible. fn normalize<T: TypeFoldable<'tcx>>(&self, t: T) -> InferOk<'tcx, T>; } @@ -57,7 +61,7 @@ impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { fn normalize<T: TypeFoldable<'tcx>>(&self, value: T) -> InferOk<'tcx, T> { let mut selcx = SelectionContext::new(self.infcx); let Normalized { value, obligations } = - normalize(&mut selcx, self.param_env, self.cause.clone(), value); + normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); InferOk { value, obligations } } } @@ -303,37 +307,6 @@ fn project_and_unify_type<'cx, 'tcx>( } } -/// Normalizes any associated type projections in `value`, replacing -/// them with a fully resolved type where possible. The return value -/// combines the normalized result and any additional obligations that -/// were incurred as result. -pub(crate) fn normalize<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - value: T, -) -> Normalized<'tcx, T> -where - T: TypeFoldable<'tcx>, -{ - let mut obligations = Vec::new(); - let value = normalize_to(selcx, param_env, cause, value, &mut obligations); - Normalized { value, obligations } -} - -pub(crate) fn normalize_to<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - value: T, - obligations: &mut Vec<PredicateObligation<'tcx>>, -) -> T -where - T: TypeFoldable<'tcx>, -{ - normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations) -} - /// As `normalize`, but with a custom depth. pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>( selcx: &'a mut SelectionContext<'b, 'tcx>, @@ -2324,10 +2297,11 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( }, )); - let ty = super::normalize_to( + let ty = normalize_with_depth_to( selcx, obligation.param_env, cause.clone(), + obligation.recursion_depth + 1, tcx.bound_trait_impl_trait_tys(impl_fn_def_id) .map_bound(|tys| { tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id]) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 1aed6630870..f899321fc01 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -23,6 +23,13 @@ use super::NoSolution; pub use rustc_middle::traits::query::NormalizationResult; pub trait QueryNormalizeExt<'tcx> { + /// Normalize a value using the `QueryNormalizer`. + /// + /// This normalization should *only* be used when the projection does not + /// have possible ambiguity or may not be well-formed. + /// + /// After codegen, when lifetimes do not matter, it is preferable to instead + /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution> where T: TypeFoldable<'tcx>; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index fe5135661b5..e4b70f0d2ff 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -203,7 +203,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // type/region parameters. let self_ty = obligation.self_ty().skip_binder(); match self_ty.kind() { - ty::Generator(..) => { + // async constructs get lowered to a special kind of generator that + // should *not* `impl Generator`. + ty::Generator(did, ..) if !self.tcx().generator_is_async(*did) => { debug!(?self_ty, ?obligation, "assemble_generator_candidates",); candidates.vec.push(GeneratorCandidate); @@ -223,6 +225,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) { let self_ty = obligation.self_ty().skip_binder(); if let ty::Generator(did, ..) = self_ty.kind() { + // async constructs get lowered to a special kind of generator that + // should directly `impl Future`. if self.tcx().generator_is_async(*did) { debug!(?self_ty, ?obligation, "assemble_future_candidates",); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 515f3a34988..8835f2cc1b9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -371,23 +371,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !candidate_set.ambiguous && no_candidates_apply { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; - let self_ty = trait_ref.self_ty(); - let (trait_desc, self_desc) = with_no_trimmed_paths!({ - let trait_desc = trait_ref.print_only_trait_path().to_string(); - let self_desc = if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) + if !trait_ref.references_error() { + let self_ty = trait_ref.self_ty(); + let (trait_desc, self_desc) = with_no_trimmed_paths!({ + let trait_desc = trait_ref.print_only_trait_path().to_string(); + let self_desc = if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }; + (trait_desc, self_desc) + }); + let cause = if let Conflict::Upstream = conflict { + IntercrateAmbiguityCause::UpstreamCrateUpdate { + trait_desc, + self_desc, + } } else { - None + IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } }; - (trait_desc, self_desc) - }); - let cause = if let Conflict::Upstream = conflict { - IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc } - } else { - IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } - }; - debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); + debug!(?cause, "evaluate_stack: pushing cause"); + self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); + } } } } |
