diff options
371 files changed, 4451 insertions, 2554 deletions
diff --git a/.gitattributes b/.gitattributes index a7de7ce8559..2c5c37007d5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,7 +3,7 @@ * text=auto eol=lf *.cpp rust *.h rust -*.rs rust +*.rs rust diff=rust *.fixed linguist-language=Rust src/etc/installer/gfx/* binary *.woff binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c45832e8153..84e39a4189e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,6 +154,11 @@ jobs: strategy: matrix: include: + - name: aarch64-gnu + os: + - self-hosted + - ARM64 + - linux - name: arm-android os: ubuntu-latest-xl env: {} @@ -178,9 +183,6 @@ jobs: - name: dist-i586-gnu-i586-i686-musl os: ubuntu-latest-xl env: {} - - name: dist-i686-freebsd - os: ubuntu-latest-xl - env: {} - name: dist-i686-linux os: ubuntu-latest-xl env: {} @@ -497,116 +499,6 @@ jobs: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" - auto-fallible: - name: auto-fallible - env: - CI_JOB_NAME: "${{ matrix.name }}" - SCCACHE_BUCKET: rust-lang-gha-caches - DEPLOY_BUCKET: rust-lang-gha - TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" - TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF - CACHE_DOMAIN: ci-caches-gha.rust-lang.org - if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - strategy: - fail-fast: false - matrix: - include: - - name: aarch64-gnu - os: - - self-hosted - - ARM64 - - linux - timeout-minutes: 600 - runs-on: "${{ matrix.os }}" - steps: - - name: disable git crlf conversion - run: git config --global core.autocrlf false - - name: checkout the source code - uses: actions/checkout@v2 - with: - fetch-depth: 2 - - name: configure the PR in which the error message will be posted - run: "echo \"[CI_PR_NUMBER=$num]\"" - env: - num: "${{ github.event.number }}" - if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'" - - name: add extra environment variables - run: src/ci/scripts/setup-environment.sh - env: - EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" - if: success() && !env.SKIP_JOB - - name: decide whether to skip this job - run: src/ci/scripts/should-skip-this.sh - if: success() && !env.SKIP_JOB - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" - - name: collect CPU statistics - run: src/ci/scripts/collect-cpu-stats.sh - if: success() && !env.SKIP_JOB - - name: show the current environment - run: src/ci/scripts/dump-environment.sh - if: success() && !env.SKIP_JOB - - name: install awscli - run: src/ci/scripts/install-awscli.sh - if: success() && !env.SKIP_JOB - - name: install sccache - run: src/ci/scripts/install-sccache.sh - if: success() && !env.SKIP_JOB - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - if: success() && !env.SKIP_JOB - - name: install clang - run: src/ci/scripts/install-clang.sh - if: success() && !env.SKIP_JOB - - name: install WIX - run: src/ci/scripts/install-wix.sh - if: success() && !env.SKIP_JOB - - name: ensure the build happens on a partition with enough space - run: src/ci/scripts/symlink-build-dir.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: install MSYS2 - run: src/ci/scripts/install-msys2.sh - if: success() && !env.SKIP_JOB - - name: install MinGW - run: src/ci/scripts/install-mingw.sh - if: success() && !env.SKIP_JOB - - name: install ninja - run: src/ci/scripts/install-ninja.sh - if: success() && !env.SKIP_JOB - - name: enable ipv6 on Docker - run: src/ci/scripts/enable-docker-ipv6.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: checkout submodules - run: src/ci/scripts/checkout-submodules.sh - if: success() && !env.SKIP_JOB - - name: ensure line endings are correct - run: src/ci/scripts/verify-line-endings.sh - if: success() && !env.SKIP_JOB - - name: run the build - run: src/ci/scripts/run-build-from-ci.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" - TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" - if: success() && !env.SKIP_JOB - - name: upload artifacts to S3 - run: src/ci/scripts/upload-artifacts.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" - if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" try: name: try env: diff --git a/Cargo.lock b/Cargo.lock index 30b7628120b..45a19fd7963 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -460,9 +460,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.32.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d072b2ba723f0bada7c515d8b3725224bc4f5052d2a92dcbeb0b118ff37084a" +checksum = "9f88ce4deae1dace71e49b7611cfae2d5489de3530d6daba5758043c47ac3a10" dependencies = [ "proc-macro2", "quote", @@ -472,9 +472,9 @@ dependencies = [ [[package]] name = "chalk-engine" -version = "0.32.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb5475f6083d6d6c509e1c335c4f69ad04144ac090faa1afb134a53c3695841" +checksum = "0e34c9b1b10616782143d7f49490f91ae94afaf2202de3ab0b2835e78b4f0ccc" dependencies = [ "chalk-derive", "chalk-ir", @@ -485,9 +485,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.32.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60cdb0e18c5455cb6a85e8464aad3622b70476018edfa8845691df66f7e9a05" +checksum = "63362c629c2014ab639b04029070763fb8224df136d1363d30e9ece4c8877da3" dependencies = [ "chalk-derive", "lazy_static", @@ -495,9 +495,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.32.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "981534d499a8476ecc0b520be4d3864757f96211826a75360fbf2cb6fae362ab" +checksum = "cac338a67af52a7f50bb2f8232e730a3518ce432dbe303246acfe525ddd838c7" dependencies = [ "chalk-derive", "chalk-ir", diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 5c0c8df2e02..2ff65737444 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -66,7 +66,7 @@ impl NestedMetaItem { self.meta_item().and_then(|meta_item| meta_item.ident()) } pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(Ident::invalid()).name + self.ident().unwrap_or_else(Ident::invalid).name } /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a @@ -139,7 +139,7 @@ impl Attribute { } } pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(Ident::invalid()).name + self.ident().unwrap_or_else(Ident::invalid).name } pub fn value_str(&self) -> Option<Symbol> { @@ -183,7 +183,7 @@ impl MetaItem { if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None } } pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(Ident::invalid()).name + self.ident().unwrap_or_else(Ident::invalid).name } // Example: diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 91ba069cf60..2697b017572 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -210,11 +210,8 @@ pub trait MutVisitor: Sized { noop_visit_local(l, self); } - fn visit_mac(&mut self, _mac: &mut MacCall) { - panic!("visit_mac disabled by default"); - // N.B., see note about macros above. If you really want a visitor that - // works on macros, use this definition in your trait impl: - // mut_visit::noop_visit_mac(_mac, self); + fn visit_mac_call(&mut self, mac: &mut MacCall) { + noop_visit_mac(mac, self); } fn visit_macro_def(&mut self, def: &mut MacroDef) { @@ -494,7 +491,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) { vis.visit_id(id); visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } - TyKind::MacCall(mac) => vis.visit_mac(mac), + TyKind::MacCall(mac) => vis.visit_mac_call(mac), } vis.visit_span(span); visit_lazy_tts(tokens, vis); @@ -962,7 +959,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) { vis.visit_generics(generics); visit_bounds(bounds, vis); } - ItemKind::MacCall(m) => vis.visit_mac(m), + ItemKind::MacCall(m) => vis.visit_mac_call(m), ItemKind::MacroDef(def) => vis.visit_macro_def(def), } } @@ -991,7 +988,7 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>( visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); } - AssocItemKind::MacCall(mac) => visitor.visit_mac(mac), + AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac), } visitor.visit_span(span); visit_lazy_tts(tokens, visitor); @@ -1081,7 +1078,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>( visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); } - ForeignItemKind::MacCall(mac) => visitor.visit_mac(mac), + ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac), } visitor.visit_span(span); visit_lazy_tts(tokens, visitor); @@ -1121,7 +1118,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) { visit_vec(elems, |elem| vis.visit_pat(elem)) } PatKind::Paren(inner) => vis.visit_pat(inner), - PatKind::MacCall(mac) => vis.visit_mac(mac), + PatKind::MacCall(mac) => vis.visit_mac_call(mac), } vis.visit_span(span); visit_lazy_tts(tokens, vis); @@ -1287,7 +1284,7 @@ pub fn noop_visit_expr<T: MutVisitor>( } visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr)); } - ExprKind::MacCall(mac) => vis.visit_mac(mac), + ExprKind::MacCall(mac) => vis.visit_mac_call(mac), ExprKind::Struct(path, fields, expr) => { vis.visit_path(path); fields.flat_map_in_place(|field| vis.flat_map_field(field)); @@ -1350,7 +1347,7 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>( StmtKind::Empty => smallvec![StmtKind::Empty], StmtKind::MacCall(mut mac) => { let MacCallStmt { mac: mac_, style: _, attrs } = mac.deref_mut(); - vis.visit_mac(mac_); + vis.visit_mac_call(mac_); visit_thin_attrs(attrs, vis); smallvec![StmtKind::MacCall(mac)] } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 6f65c0a1efc..72e901fb90f 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -176,13 +176,8 @@ pub trait Visitor<'ast>: Sized { fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) { walk_lifetime(self, lifetime) } - fn visit_mac(&mut self, _mac: &'ast MacCall) { - panic!("visit_mac disabled by default"); - // N.B., see note about macros above. - // if you really want a visitor that - // works on macros, use this - // definition in your trait impl: - // visit::walk_mac(self, _mac) + fn visit_mac_call(&mut self, mac: &'ast MacCall) { + walk_mac(self, mac) } fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) { // Nothing to do @@ -346,7 +341,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); } - ItemKind::MacCall(ref mac) => visitor.visit_mac(mac), + ItemKind::MacCall(ref mac) => visitor.visit_mac_call(mac), ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), } walk_list!(visitor, visit_attribute, &item.attrs); @@ -414,7 +409,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { } TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} - TyKind::MacCall(ref mac) => visitor.visit_mac(mac), + TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac), TyKind::Never | TyKind::CVarArgs => {} } } @@ -532,7 +527,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => { walk_list!(visitor, visit_pat, elems); } - PatKind::MacCall(ref mac) => visitor.visit_mac(mac), + PatKind::MacCall(ref mac) => visitor.visit_mac_call(mac), } } @@ -557,7 +552,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI walk_list!(visitor, visit_ty, ty); } ForeignItemKind::MacCall(mac) => { - visitor.visit_mac(mac); + visitor.visit_mac_call(mac); } } } @@ -662,7 +657,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, walk_list!(visitor, visit_ty, ty); } AssocItemKind::MacCall(mac) => { - visitor.visit_mac(mac); + visitor.visit_mac_call(mac); } } } @@ -692,7 +687,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { StmtKind::Empty => {} StmtKind::MacCall(ref mac) => { let MacCallStmt { ref mac, style: _, ref attrs } = **mac; - visitor.visit_mac(mac); + visitor.visit_mac_call(mac); for attr in attrs.iter() { visitor.visit_attribute(attr); } @@ -823,7 +818,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Ret(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } - ExprKind::MacCall(ref mac) => visitor.visit_mac(mac), + ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac), ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression), ExprKind::InlineAsm(ref ia) => { for (op, _) in &ia.operands { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a6ac056b93b..1f2aba2b27e 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -9,6 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; +use rustc_session::parse::feature_err; use rustc_span::hygiene::ForLoopLoc; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -146,7 +147,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) } ExprKind::Assign(ref el, ref er, span) => { - hir::ExprKind::Assign(self.lower_expr(el), self.lower_expr(er), span) + self.lower_expr_assign(el, er, span, e.span) } ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp( self.lower_binop(op), @@ -840,6 +841,134 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } + /// Destructure the LHS of complex assignments. + /// For instance, lower `(a, b) = t` to `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`. + fn lower_expr_assign( + &mut self, + lhs: &Expr, + rhs: &Expr, + eq_sign_span: Span, + whole_span: Span, + ) -> hir::ExprKind<'hir> { + // Return early in case of an ordinary assignment. + fn is_ordinary(lhs: &Expr) -> bool { + match &lhs.kind { + ExprKind::Tup(..) => false, + ExprKind::Paren(e) => { + match e.kind { + // We special-case `(..)` for consistency with patterns. + ExprKind::Range(None, None, RangeLimits::HalfOpen) => false, + _ => is_ordinary(e), + } + } + _ => true, + } + } + if is_ordinary(lhs) { + return hir::ExprKind::Assign(self.lower_expr(lhs), self.lower_expr(rhs), eq_sign_span); + } + if !self.sess.features_untracked().destructuring_assignment { + feature_err( + &self.sess.parse_sess, + sym::destructuring_assignment, + eq_sign_span, + "destructuring assignments are unstable", + ) + .span_label(lhs.span, "cannot assign to this expression") + .emit(); + } + + let mut assignments = vec![]; + + // The LHS becomes a pattern: `(lhs1, lhs2)`. + let pat = self.destructure_assign(lhs, eq_sign_span, &mut assignments); + let rhs = self.lower_expr(rhs); + + // Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`. + let destructure_let = self.stmt_let_pat( + ThinVec::new(), + whole_span, + Some(rhs), + pat, + hir::LocalSource::AssignDesugar(eq_sign_span), + ); + + // `a = lhs1; b = lhs2;`. + let stmts = self + .arena + .alloc_from_iter(std::iter::once(destructure_let).chain(assignments.into_iter())); + + // Wrap everything in a block. + hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None) + } + + /// Convert the LHS of a destructuring assignment to a pattern. + /// Each sub-assignment is recorded in `assignments`. + fn destructure_assign( + &mut self, + lhs: &Expr, + eq_sign_span: Span, + assignments: &mut Vec<hir::Stmt<'hir>>, + ) -> &'hir hir::Pat<'hir> { + match &lhs.kind { + // Tuples. + ExprKind::Tup(elements) => { + let (pats, rest) = + self.destructure_sequence(elements, "tuple", eq_sign_span, assignments); + let tuple_pat = hir::PatKind::Tuple(pats, rest.map(|r| r.0)); + return self.pat_without_dbm(lhs.span, tuple_pat); + } + ExprKind::Paren(e) => { + // We special-case `(..)` for consistency with patterns. + if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { + let tuple_pat = hir::PatKind::Tuple(&[], Some(0)); + return self.pat_without_dbm(lhs.span, tuple_pat); + } else { + return self.destructure_assign(e, eq_sign_span, assignments); + } + } + _ => {} + } + // Treat all other cases as normal lvalue. + let ident = Ident::new(sym::lhs, lhs.span); + let (pat, binding) = self.pat_ident(lhs.span, ident); + let ident = self.expr_ident(lhs.span, ident, binding); + let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, eq_sign_span); + let expr = self.expr(lhs.span, assign, ThinVec::new()); + assignments.push(self.stmt_expr(lhs.span, expr)); + pat + } + + /// Destructure a sequence of expressions occurring on the LHS of an assignment. + /// Such a sequence occurs in a tuple (struct)/slice. + /// Return a sequence of corresponding patterns, and the index and the span of `..` if it + /// exists. + /// Each sub-assignment is recorded in `assignments`. + fn destructure_sequence( + &mut self, + elements: &[AstP<Expr>], + ctx: &str, + eq_sign_span: Span, + assignments: &mut Vec<hir::Stmt<'hir>>, + ) -> (&'hir [&'hir hir::Pat<'hir>], Option<(usize, Span)>) { + let mut rest = None; + let elements = + self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| { + // Check for `..` pattern. + if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { + if let Some((_, prev_span)) = rest { + self.ban_extra_rest_pat(e.span, prev_span, ctx); + } else { + rest = Some((i, e.span)); + } + None + } else { + Some(self.destructure_assign(e, eq_sign_span, assignments)) + } + })); + (elements, rest) + } + /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`. fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { let e1 = self.lower_expr_mut(e1); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9a5fd2307d5..549b66e2d36 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2534,6 +2534,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir_id, kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None), span, + default_binding_modes: true, }), hir_id, ) @@ -2544,7 +2545,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn pat(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> { - self.arena.alloc(hir::Pat { hir_id: self.next_id(), kind, span }) + self.arena.alloc(hir::Pat { + hir_id: self.next_id(), + kind, + span, + default_binding_modes: true, + }) + } + + fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> { + self.arena.alloc(hir::Pat { + hir_id: self.next_id(), + kind, + span, + default_binding_modes: false, + }) } fn ty_path( diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index a1cbcde1f42..e4e7b24d29e 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -273,11 +273,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Construct a `Pat` with the `HirId` of `p.id` lowered. fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> { - self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span }) + self.arena.alloc(hir::Pat { + hir_id: self.lower_node_id(p.id), + kind, + span: p.span, + default_binding_modes: true, + }) } /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern. - fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) { + crate fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) { self.diagnostic() .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx)) .span_label(sp, &format!("can only be used once per {} pattern", ctx)) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d6585bcc425..bb1d2967d6a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -796,7 +796,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_expr(&mut self, expr: &'a Expr) { match &expr.kind { - ExprKind::LlvmInlineAsm(..) if !self.session.target.options.allow_asm => { + ExprKind::LlvmInlineAsm(..) if !self.session.target.allow_asm => { struct_span_err!( self.session, expr.span, diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs index 706dca2b7f4..6efc78c8842 100644 --- a/compiler/rustc_ast_passes/src/node_count.rs +++ b/compiler/rustc_ast_passes/src/node_count.rs @@ -114,9 +114,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_lifetime(self, lifetime) } - fn visit_mac(&mut self, _mac: &MacCall) { + fn visit_mac_call(&mut self, mac: &MacCall) { self.count += 1; - walk_mac(self, _mac) + walk_mac(self, mac) } fn visit_path(&mut self, path: &Path, _id: NodeId) { self.count += 1; diff --git a/compiler/rustc_ast_passes/src/show_span.rs b/compiler/rustc_ast_passes/src/show_span.rs index 053aba86222..6cef26a13e6 100644 --- a/compiler/rustc_ast_passes/src/show_span.rs +++ b/compiler/rustc_ast_passes/src/show_span.rs @@ -54,10 +54,6 @@ impl<'a> Visitor<'a> for ShowSpanVisitor<'a> { } visit::walk_ty(self, t); } - - fn visit_mac(&mut self, mac: &'a ast::MacCall) { - visit::walk_mac(self, mac); - } } pub fn run(span_diagnostic: &rustc_errors::Handler, mode: &str, krate: &ast::Crate) { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 2e52d2a3923..0642edff6b6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -358,7 +358,7 @@ fn find_type_parameters( visit::walk_ty(self, ty) } - fn visit_mac(&mut self, mac: &ast::MacCall) { + fn visit_mac_call(&mut self, mac: &ast::MacCall) { self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros"); } } diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index c6ab3faf568..4e91436199a 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -344,10 +344,6 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { visit::walk_item(self, item); self.in_root = prev_in_root; } - - fn visit_mac(&mut self, mac: &'a ast::MacCall) { - visit::walk_mac(self, mac) - } } // Creates a new module which looks like: diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index da74f0aeaa1..9976140d6bd 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -37,7 +37,7 @@ struct TestCtxt<'a> { pub fn inject(sess: &Session, resolver: &mut dyn ResolverExpand, krate: &mut ast::Crate) { let span_diagnostic = sess.diagnostic(); let panic_strategy = sess.panic_strategy(); - let platform_panic_strategy = sess.target.options.panic_strategy; + let platform_panic_strategy = sess.target.panic_strategy; // Check for #![reexport_test_harness_main = "some_name"] which gives the // main test function the name `some_name` without hygiene. This needs to be @@ -130,10 +130,6 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { } smallvec![P(item)] } - - fn visit_mac(&mut self, _mac: &mut ast::MacCall) { - // Do nothing. - } } // Beware, this is duplicated in librustc_passes/entry.rs (with @@ -201,10 +197,6 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { smallvec![item] } - - fn visit_mac(&mut self, _mac: &mut ast::MacCall) { - // Do nothing. - } } /// Crawl over the crate, inserting test reexports and the test main function @@ -290,7 +282,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> { let mut test_runner = cx .test_runner .clone() - .unwrap_or(ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)])); + .unwrap_or_else(|| ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)])); test_runner.span = sp; diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index 9a970efbcfd..daf9fa6158f 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -63,9 +63,9 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { sess, dst: output.to_path_buf(), lib_search_paths: archive_search_paths(sess), - use_gnu_style_archive: sess.target.options.archive_format == "gnu", + use_gnu_style_archive: sess.target.archive_format == "gnu", // FIXME fix builtin ranlib on macOS - no_builtin_ranlib: sess.target.options.is_like_osx, + no_builtin_ranlib: sess.target.is_like_osx, src_archives, entries, diff --git a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs index 71ef4d22673..cd01acc9a83 100644 --- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs @@ -27,8 +27,8 @@ impl rustc_driver::Callbacks for CraneliftPassesCallbacks { config.opts.cg.panic = Some(PanicStrategy::Abort); config.opts.debugging_opts.panic_abort_tests = true; config.opts.maybe_sysroot = Some( - config.opts.maybe_sysroot.clone().unwrap_or( - std::env::current_exe() + config.opts.maybe_sysroot.clone().unwrap_or_else( + || std::env::current_exe() .unwrap() .parent() .unwrap() diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index eda77bf19d3..466758f2f86 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -361,13 +361,11 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> { where T: TypeFoldable<'tcx> + Copy, { - if let Some(substs) = self.instance.substs_for_mir_body() { - self.tcx - .subst_and_normalize_erasing_regions(substs, ty::ParamEnv::reveal_all(), value) - } else { - self.tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), *value) - } + self.instance.subst_mir_and_normalize_erasing_regions( + self.tcx, + ty::ParamEnv::reveal_all(), + value + ) } pub(crate) fn clif_type(&self, ty: Ty<'tcx>) -> Option<Type> { diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index cbf9522b1d7..85e8158af27 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -50,7 +50,7 @@ impl<'tcx> DebugContext<'tcx> { // TODO: this should be configurable // macOS doesn't seem to support DWARF > 3 // 5 version is required for md5 file hash - version: if tcx.sess.target.options.is_like_osx { + version: if tcx.sess.target.is_like_osx { 3 } else { // FIXME change to version 5 once the gdb and lldb shipping with the latest debian diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index ff0b994c9a9..c0245aa1e02 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -320,8 +320,8 @@ fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { } if cfg!(not(feature = "inline_asm")) - || tcx.sess.target.options.is_like_osx - || tcx.sess.target.options.is_like_windows + || tcx.sess.target.is_like_osx + || tcx.sess.target.is_like_windows { if global_asm.contains("__rust_probestack") { return; diff --git a/compiler/rustc_codegen_cranelift/src/metadata.rs b/compiler/rustc_codegen_cranelift/src/metadata.rs index cda2a187ff9..2e3b9fb8364 100644 --- a/compiler/rustc_codegen_cranelift/src/metadata.rs +++ b/compiler/rustc_codegen_cranelift/src/metadata.rs @@ -101,7 +101,7 @@ pub(crate) fn write_metadata<P: WriteMetadata>( product.add_rustc_section( rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx), compressed, - tcx.sess.target.options.is_like_osx, + tcx.sess.target.is_like_osx, ); metadata diff --git a/compiler/rustc_codegen_cranelift/src/toolchain.rs b/compiler/rustc_codegen_cranelift/src/toolchain.rs index 463afaf7cc5..735c59d70c1 100644 --- a/compiler/rustc_codegen_cranelift/src/toolchain.rs +++ b/compiler/rustc_codegen_cranelift/src/toolchain.rs @@ -91,7 +91,7 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { } else if stem == "link" || stem == "lld-link" { LinkerFlavor::Msvc } else if stem == "lld" || stem == "rust-lld" { - LinkerFlavor::Lld(sess.target.options.lld_flavor) + LinkerFlavor::Lld(sess.target.lld_flavor) } else { // fall back to the value in the target spec sess.target.linker_flavor @@ -115,7 +115,7 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { if let Some(ret) = infer_from( sess, - sess.target.options.linker.clone().map(PathBuf::from), + sess.target.linker.clone().map(PathBuf::from), Some(sess.target.linker_flavor), ) { return ret; diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index f7d82ff78fa..a5ea0b2a74c 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -57,7 +57,7 @@ pub(crate) unsafe fn codegen( let name = format!("__rust_{}", method.name); let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty); - if tcx.sess.target.options.default_hidden_visibility { + if tcx.sess.target.default_hidden_visibility { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); } if tcx.sess.must_emit_unwind_tables() { @@ -98,7 +98,7 @@ pub(crate) unsafe fn codegen( // -> ! DIFlagNoReturn llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn); - if tcx.sess.target.options.default_hidden_visibility { + if tcx.sess.target.default_hidden_visibility { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); } if tcx.sess.must_emit_unwind_tables() { diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index d4872aedd70..87bcce07b34 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -90,8 +90,7 @@ fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // The function name varies on platforms. // See test/CodeGen/mcount.c in clang. - let mcount_name = - CString::new(cx.sess().target.options.target_mcount.as_str().as_bytes()).unwrap(); + let mcount_name = CString::new(cx.sess().target.mcount.as_str().as_bytes()).unwrap(); llvm::AddFunctionAttrStringValue( llfn, @@ -105,7 +104,7 @@ fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Only use stack probes if the target specification indicates that we // should be using stack probes - if !cx.sess().target.options.stack_probes { + if !cx.sess().target.stack_probes { return; } @@ -174,7 +173,6 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> { .split(',') .filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s))); sess.target - .options .features .split(',') .chain(cmdline) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 595655b2ca2..4e7213853b0 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -206,7 +206,7 @@ impl<'a> LlvmArchiveBuilder<'a> { } fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> { - let kind = &*self.config.sess.target.options.archive_format; + let kind = &*self.config.sess.target.archive_format; kind.parse().map_err(|_| kind) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index f13c2d312df..e6acb6860be 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -129,13 +129,13 @@ pub fn target_machine_factory( let use_softfp = sess.opts.cg.soft_float; let ffunction_sections = - sess.opts.debugging_opts.function_sections.unwrap_or(sess.target.options.function_sections); + sess.opts.debugging_opts.function_sections.unwrap_or(sess.target.function_sections); let fdata_sections = ffunction_sections; let code_model = to_llvm_code_model(sess.code_model()); let features = attributes::llvm_target_features(sess).collect::<Vec<_>>(); - let mut singlethread = sess.target.options.singlethread; + let mut singlethread = sess.target.singlethread; // On the wasm target once the `atomics` feature is enabled that means that // we're no longer single-threaded, or otherwise we don't want LLVM to @@ -151,22 +151,16 @@ pub fn target_machine_factory( let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); let features = features.join(","); let features = CString::new(features).unwrap(); - let abi = SmallCStr::new(&sess.target.options.llvm_abiname); - let trap_unreachable = sess.target.options.trap_unreachable; + let abi = SmallCStr::new(&sess.target.llvm_abiname); + let trap_unreachable = sess.target.trap_unreachable; let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes; let asm_comments = sess.asm_comments(); - let relax_elf_relocations = sess - .opts - .debugging_opts - .relax_elf_relocations - .unwrap_or(sess.target.options.relax_elf_relocations); - - let use_init_array = !sess - .opts - .debugging_opts - .use_ctors_section - .unwrap_or(sess.target.options.use_ctors_section); + let relax_elf_relocations = + sess.opts.debugging_opts.relax_elf_relocations.unwrap_or(sess.target.relax_elf_relocations); + + let use_init_array = + !sess.opts.debugging_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section); Arc::new(move || { let tm = unsafe { diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index e2003472d12..367c1f4811c 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -176,7 +176,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value // should use dllimport for functions. if cx.use_dll_storage_attrs && tcx.is_dllimport_foreign_item(instance_def_id) - && tcx.sess.target.target_env != "gnu" + && tcx.sess.target.env != "gnu" { unsafe { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 90a51f75e0e..14dd245625d 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -91,7 +91,7 @@ fn set_global_alignment(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Alig // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, // which can force it to be smaller. Rust doesn't support this yet. - if let Some(min) = cx.sess().target.options.min_global_align { + if let Some(min) = cx.sess().target.min_global_align { match Align::from_bits(min) { Ok(min) => align = align.max(min), Err(err) => { @@ -283,7 +283,7 @@ impl CodegenCx<'ll, 'tcx> { // argument validation. debug_assert!( !(self.tcx.sess.opts.cg.linker_plugin_lto.enabled() - && self.tcx.sess.target.options.is_like_windows + && self.tcx.sess.target.is_like_windows && self.tcx.sess.opts.cg.prefer_dynamic) ); @@ -435,7 +435,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // will use load-unaligned instructions instead, and thus avoiding the crash. // // We could remove this hack whenever we decide to drop macOS 10.10 support. - if self.tcx.sess.target.options.is_like_osx { + if self.tcx.sess.target.is_like_osx { // The `inspect` method is okay here because we checked relocations, and // because we are doing this access to inspect the final interpreter state // (not as part of the interpreter execution). diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 253e02bd082..b6e922ca545 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -129,7 +129,7 @@ pub unsafe fn create_module( } // Ensure the data-layout values hardcoded remain the defaults. - if sess.target.options.is_builtin { + if sess.target.is_builtin { let tm = crate::back::write::create_informational_target_machine(tcx.sess); llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm); llvm::LLVMRustDisposeTargetMachine(tm); @@ -190,7 +190,7 @@ pub unsafe fn create_module( } // Control Flow Guard is currently only supported by the MSVC linker on Windows. - if sess.target.options.is_like_msvc { + if sess.target.is_like_msvc { match sess.opts.cg.control_flow_guard { CFGuard::Disabled => {} CFGuard::NoChecks => { @@ -265,7 +265,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { // linker will take care of everything. Fixing this problem will likely // require adding a few attributes to Rust itself (feature gated at the // start) and then strongly recommending static linkage on Windows! - let use_dll_storage_attrs = tcx.sess.target.options.is_like_windows; + let use_dll_storage_attrs = tcx.sess.target.is_like_windows; let check_overflow = tcx.sess.overflow_checks(); @@ -839,7 +839,7 @@ impl CodegenCx<'b, 'tcx> { return eh_catch_typeinfo; } let tcx = self.tcx; - assert!(self.sess().target.options.is_like_emscripten); + assert!(self.sess().target.is_like_emscripten); let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() { Some(def_id) => self.get_static(def_id), _ => { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 79721ff7e2d..38f50a6d621 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -67,5 +67,5 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { !omit_gdb_pretty_printer_section && cx.sess().opts.debuginfo != DebugInfo::None - && cx.sess().target.options.emit_debug_gdb_scripts + && cx.sess().target.emit_debug_gdb_scripts } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 454d43fd4e7..27b81ebcff6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -870,7 +870,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { // When targeting MSVC, emit MSVC style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let msvc_like_names = cx.tcx.sess.target.options.is_like_msvc; + let msvc_like_names = cx.tcx.sess.target.is_like_msvc; let (name, encoding) = match t.kind() { ty::Never => ("!", DW_ATE_unsigned), @@ -981,7 +981,7 @@ pub fn compile_unit_metadata( // if multiple object files with the same `DW_AT_name` are linked together. // As a workaround we generate unique names for each object file. Those do // not correspond to an actual source file but that should be harmless. - if tcx.sess.target.options.is_like_osx { + if tcx.sess.target.is_like_osx { name_in_debuginfo.push("@"); name_in_debuginfo.push(codegen_unit_name); } @@ -1397,7 +1397,7 @@ fn prepare_union_metadata( /// on MSVC we have to use the fallback mode, because LLVM doesn't /// lower variant parts to PDB. fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { - cx.sess().target.options.is_like_msvc + cx.sess().target.is_like_msvc } // FIXME(eddyb) maybe precompute this? Right now it's computed once diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 6bb93857d71..5065ff01aed 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -122,12 +122,12 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { // for macOS to understand. For more info see #11352 // This can be overridden using --llvm-opts -dwarf-version,N. // Android has the same issue (#22398) - if let Some(version) = cx.sess().target.options.dwarf_version { + if let Some(version) = cx.sess().target.dwarf_version { llvm::LLVMRustAddModuleFlag(cx.llmod, "Dwarf Version\0".as_ptr().cast(), version) } // Indicate that we want CodeView debug information on MSVC - if cx.sess().target.options.is_like_msvc { + if cx.sess().target.is_like_msvc { llvm::LLVMRustAddModuleFlag(cx.llmod, "CodeView\0".as_ptr().cast(), 1) } @@ -251,7 +251,7 @@ impl CodegenCx<'ll, '_> { // For MSVC, omit the column number. // Otherwise, emit it. This mimics clang behaviour. // See discussion in https://github.com/rust-lang/rust/issues/42921 - if self.sess().target.options.is_like_msvc { + if self.sess().target.is_like_msvc { DebugLoc { file, line, col: None } } else { DebugLoc { file, line, col } @@ -387,7 +387,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { }); // Arguments types - if cx.sess().target.options.is_like_msvc { + if cx.sess().target.is_like_msvc { // FIXME(#42800): // There is a bug in MSDIA that leads to a crash when it encounters // a fixed-size array of `u8` or something zero-sized in a diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 9face778322..0591e0a5c12 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -42,7 +42,7 @@ fn declare_raw_fn( // be merged. llvm::SetUnnamedAddress(llfn, llvm::UnnamedAddr::Global); - if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.options.disable_redzone) { + if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.disable_redzone) { llvm::Attribute::NoRedZone.apply_llfn(Function, llfn); } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index e9900e8bc10..d52b3be8cd3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -367,7 +367,7 @@ fn try_intrinsic( bx.store(bx.const_i32(0), dest, ret_align); } else if wants_msvc_seh(bx.sess()) { codegen_msvc_try(bx, try_func, data, catch_func, dest); - } else if bx.sess().target.options.is_like_emscripten { + } else if bx.sess().target.is_like_emscripten { codegen_emcc_try(bx, try_func, data, catch_func, dest); } else { codegen_gnu_try(bx, try_func, data, catch_func, dest); @@ -979,12 +979,14 @@ fn generic_simd_intrinsic( // Integer vector <i{in_bitwidth} x in_len>: let (i_xn, in_elem_bitwidth) = match in_elem.kind() { - ty::Int(i) => { - (args[0].immediate(), i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits())) - } - ty::Uint(i) => { - (args[0].immediate(), i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits())) - } + ty::Int(i) => ( + args[0].immediate(), + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), + ), + ty::Uint(i) => ( + args[0].immediate(), + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), + ), _ => return_error!( "vector argument `{}`'s element type `{}`, expected integer element type", in_ty, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 9c1e1b8fac0..ab70f72dc61 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -46,7 +46,7 @@ fn require_inited() { } unsafe fn configure_llvm(sess: &Session) { - let n_args = sess.opts.cg.llvm_args.len() + sess.target.options.llvm_args.len(); + let n_args = sess.opts.cg.llvm_args.len() + sess.target.llvm_args.len(); let mut llvm_c_strs = Vec::with_capacity(n_args + 1); let mut llvm_args = Vec::with_capacity(n_args + 1); @@ -57,7 +57,7 @@ unsafe fn configure_llvm(sess: &Session) { } let cg_opts = sess.opts.cg.llvm_args.iter(); - let tg_opts = sess.target.options.llvm_args.iter(); + let tg_opts = sess.target.llvm_args.iter(); let sess_args = cg_opts.chain(tg_opts); let user_specified_args: FxHashSet<_> = @@ -84,19 +84,14 @@ unsafe fn configure_llvm(sess: &Session) { if !sess.opts.debugging_opts.no_generate_arange_section { add("-generate-arange-section", false); } - match sess - .opts - .debugging_opts - .merge_functions - .unwrap_or(sess.target.options.merge_functions) - { + match sess.opts.debugging_opts.merge_functions.unwrap_or(sess.target.merge_functions) { MergeFunctions::Disabled | MergeFunctions::Trampolines => {} MergeFunctions::Aliases => { add("-mergefunc-use-aliases", false); } } - if sess.target.target_os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind { + if sess.target.os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind { add("-enable-emscripten-cxx-exceptions", false); } @@ -215,7 +210,7 @@ fn handle_native(name: &str) -> &str { pub fn target_cpu(sess: &Session) -> &str { let name = match sess.opts.cg.target_cpu { Some(ref s) => &**s, - None => &*sess.target.options.cpu, + None => &*sess.target.cpu, }; handle_native(name) diff --git a/compiler/rustc_codegen_llvm/src/metadata.rs b/compiler/rustc_codegen_llvm/src/metadata.rs index 9036428c04b..3912d6a3a48 100644 --- a/compiler/rustc_codegen_llvm/src/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/metadata.rs @@ -104,7 +104,7 @@ pub fn metadata_section_name(target: &Target) -> &'static str { // As a result, we choose a slightly shorter name! As to why // `.note.rustc` works on MinGW, that's another good question... - if target.options.is_like_osx { "__DATA,.rustc" } else { ".rustc" } + if target.is_like_osx { "__DATA,.rustc" } else { ".rustc" } } fn read_metadata_section_name(_target: &Target) -> &'static str { diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index b6a0516b8bc..3fc56eecdd0 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -52,7 +52,7 @@ fn emit_direct_ptr_va_arg( let next = bx.inbounds_gep(addr, &[full_direct_size]); bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi); - if size.bytes() < slot_size.bytes() && &*bx.tcx().sess.target.target_endian == "big" { + if size.bytes() < slot_size.bytes() && &*bx.tcx().sess.target.endian == "big" { let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32); let adjusted = bx.inbounds_gep(addr, &[adjusted_size]); (bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align) @@ -105,7 +105,7 @@ fn emit_aapcs_va_arg( let mut end = bx.build_sibling_block("va_arg.end"); let zero = bx.const_i32(0); let offset_align = Align::from_bytes(4).unwrap(); - assert!(&*bx.tcx().sess.target.target_endian == "little"); + assert!(&*bx.tcx().sess.target.endian == "little"); let gr_type = target_ty.is_any_ptr() || target_ty.is_integral(); let (reg_off, reg_top_index, slot_size) = if gr_type { @@ -175,22 +175,22 @@ pub(super) fn emit_va_arg( let arch = &bx.cx.tcx.sess.target.arch; match &**arch { // Windows x86 - "x86" if target.options.is_like_windows => { + "x86" if target.is_like_windows => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false) } // Generic x86 "x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true), // Windows AArch64 - "aarch64" if target.options.is_like_windows => { + "aarch64" if target.is_like_windows => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } // macOS / iOS AArch64 - "aarch64" if target.options.is_like_osx => { + "aarch64" if target.is_like_osx => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true) } "aarch64" => emit_aapcs_va_arg(bx, addr, target_ty), // Windows x86_64 - "x86_64" if target.options.is_like_windows => { + "x86_64" if target.is_like_windows => { let target_ty_size = bx.cx.size_of(target_ty).bytes(); let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two(); emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index ef722ecb599..c477ac6462a 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -7,10 +7,8 @@ use std::path::{Path, PathBuf}; pub fn find_library(name: Symbol, search_paths: &[PathBuf], sess: &Session) -> PathBuf { // On Windows, static libraries sometimes show up as libfoo.a and other // times show up as foo.lib - let oslibname = format!( - "{}{}{}", - sess.target.options.staticlib_prefix, name, sess.target.options.staticlib_suffix - ); + let oslibname = + format!("{}{}{}", sess.target.staticlib_prefix, name, sess.target.staticlib_suffix); let unixlibname = format!("lib{}.a", name); for path in search_paths { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 63d0a88858e..5a627a0efa3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -151,9 +151,7 @@ fn get_linker( Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker), _ => match flavor { LinkerFlavor::Lld(f) => Command::lld(linker, f), - LinkerFlavor::Msvc - if sess.opts.cg.linker.is_none() && sess.target.options.linker.is_none() => - { + LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => { Command::new(msvc_tool.as_ref().map(|t| t.path()).unwrap_or(linker)) } _ => Command::new(linker), @@ -165,7 +163,7 @@ fn get_linker( // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). let t = &sess.target; if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link)) - && t.target_vendor == "uwp" + && t.vendor == "uwp" { if let Some(ref tool) = msvc_tool { let original_path = tool.path(); @@ -197,7 +195,7 @@ fn get_linker( // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained); let mut msvc_changed_path = false; - if sess.target.options.is_like_msvc { + if sess.target.is_like_msvc { if let Some(ref tool) = msvc_tool { cmd.args(tool.args()); for &(ref k, ref v) in tool.env() { @@ -365,7 +363,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( // After adding all files to the archive, we need to update the // symbol table of the archive. This currently dies on macOS (see // #11162), and isn't necessary there anyway - if !sess.target.options.is_like_osx { + if !sess.target.is_like_osx { ab.update_symbols(); } } @@ -476,10 +474,10 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( linker::disable_localization(&mut cmd); - for &(ref k, ref v) in &sess.target.options.link_env { + for &(ref k, ref v) in &sess.target.link_env { cmd.env(k, v); } - for k in &sess.target.options.link_env_remove { + for k in &sess.target.link_env_remove { cmd.env_remove(k); } @@ -515,7 +513,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( // if the linker doesn't support -no-pie then it should not default to // linking executables as pie. Different versions of gcc seem to use // different quotes in the error message so don't check for them. - if sess.target.options.linker_is_gnu + if sess.target.linker_is_gnu && flavor != LinkerFlavor::Ld && (out.contains("unrecognized command line option") || out.contains("unknown argument")) @@ -535,7 +533,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( // Detect '-static-pie' used with an older version of gcc or clang not supporting it. // Fallback from '-static-pie' to '-static' in that case. - if sess.target.options.linker_is_gnu + if sess.target.linker_is_gnu && flavor != LinkerFlavor::Ld && (out.contains("unrecognized command line option") || out.contains("unknown argument")) @@ -548,7 +546,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( ); // Mirror `add_(pre,post)_link_objects` to replace CRT objects. let self_contained = crt_objects_fallback(sess, crate_type); - let opts = &sess.target.options; + let opts = &sess.target; let pre_objects = if self_contained { &opts.pre_link_objects_fallback } else { @@ -670,7 +668,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( // is not a Microsoft LNK error then suggest a way to fix or // install the Visual Studio build tools. if let Some(code) = prog.status.code() { - if sess.target.options.is_like_msvc + if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc // Respect the command line override && sess.opts.cg.linker.is_none() @@ -741,7 +739,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( linker_error.emit(); - if sess.target.options.is_like_msvc && linker_not_found { + if sess.target.is_like_msvc && linker_not_found { sess.note_without_error( "the msvc targets depend on the msvc linker \ but `link.exe` was not found", @@ -758,7 +756,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( // On macOS, debuggers need this utility to get run to do some munging of // the symbols. Note, though, that if the object files are being preserved // for their debug information there's no need for us to run dsymutil. - if sess.target.options.is_like_osx + if sess.target.is_like_osx && sess.opts.debuginfo != DebugInfo::None && !preserve_objects_for_their_debuginfo(sess) { @@ -775,9 +773,7 @@ fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linke // executables only. let needs_runtime = match crate_type { CrateType::Executable => true, - CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => { - sess.target.options.is_like_osx - } + CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => sess.target.is_like_osx, CrateType::Rlib | CrateType::Staticlib => false, }; @@ -846,7 +842,7 @@ pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool // If our target enables builtin function lowering in LLVM then the // crates providing these functions don't participate in LTO (e.g. // no_builtins or compiler builtins crates). - !sess.target.options.no_builtins + !sess.target.no_builtins && (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum)) } @@ -906,7 +902,7 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { } else if stem == "link" || stem == "lld-link" { LinkerFlavor::Msvc } else if stem == "lld" || stem == "rust-lld" { - LinkerFlavor::Lld(sess.target.options.lld_flavor) + LinkerFlavor::Lld(sess.target.lld_flavor) } else { // fall back to the value in the target spec sess.target.linker_flavor @@ -926,7 +922,7 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { if let Some(ret) = infer_from( sess, - sess.target.options.linker.clone().map(PathBuf::from), + sess.target.linker.clone().map(PathBuf::from), Some(sess.target.linker_flavor), ) { return ret; @@ -962,7 +958,7 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { // Basically as a result this just means that if we're on OSX and we're // *not* running dsymutil then the object files are the only source of truth // for debug information, so we must preserve them. - if sess.target.options.is_like_osx { + if sess.target.is_like_osx { return !sess.opts.debugging_opts.run_dsymutil; } @@ -988,7 +984,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { NativeLibKind::StaticNoBundle | NativeLibKind::Dylib | NativeLibKind::Unspecified => { - if sess.target.options.is_like_msvc { + if sess.target.is_like_msvc { Some(format!("{}.lib", name)) } else { Some(format!("-l{}", name)) @@ -1070,13 +1066,13 @@ fn exec_linker( let mut args = String::new(); for arg in cmd2.take_args() { args.push_str( - &Escape { arg: arg.to_str().unwrap(), is_like_msvc: sess.target.options.is_like_msvc } + &Escape { arg: arg.to_str().unwrap(), is_like_msvc: sess.target.is_like_msvc } .to_string(), ); args.push('\n'); } let file = tmpdir.join("linker-arguments"); - let bytes = if sess.target.options.is_like_msvc { + let bytes = if sess.target.is_like_msvc { let mut out = Vec::with_capacity((1 + args.len()) * 2); // start the stream with a UTF-16 BOM for c in std::iter::once(0xFEFF).chain(args.encode_utf16()) { @@ -1192,7 +1188,7 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { }; // Adjust the output kind to target capabilities. - let opts = &sess.target.options; + let opts = &sess.target; let pic_exe_supported = opts.position_independent_executables; let static_pic_exe_supported = opts.static_position_independent_executables; let static_dylib_supported = opts.crt_static_allows_dylibs; @@ -1233,14 +1229,14 @@ fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool { return self_contained; } - match sess.target.options.crt_objects_fallback { + match sess.target.crt_objects_fallback { // FIXME: Find a better heuristic for "native musl toolchain is available", // based on host and linker path, for example. // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237). Some(CrtObjectsFallback::Musl) => sess.crt_static(Some(crate_type)), Some(CrtObjectsFallback::Mingw) => { sess.host == sess.target - && sess.target.target_vendor != "uwp" + && sess.target.vendor != "uwp" && detect_self_contained_mingw(&sess) } // FIXME: Figure out cases in which WASM needs to link with a native toolchain. @@ -1256,7 +1252,7 @@ fn add_pre_link_objects( link_output_kind: LinkOutputKind, self_contained: bool, ) { - let opts = &sess.target.options; + let opts = &sess.target; let objects = if self_contained { &opts.pre_link_objects_fallback } else { &opts.pre_link_objects }; for obj in objects.get(&link_output_kind).iter().copied().flatten() { @@ -1271,7 +1267,7 @@ fn add_post_link_objects( link_output_kind: LinkOutputKind, self_contained: bool, ) { - let opts = &sess.target.options; + let opts = &sess.target; let objects = if self_contained { &opts.post_link_objects_fallback } else { &opts.post_link_objects }; for obj in objects.get(&link_output_kind).iter().copied().flatten() { @@ -1282,7 +1278,7 @@ fn add_post_link_objects( /// Add arbitrary "pre-link" args defined by the target spec or from command line. /// FIXME: Determine where exactly these args need to be inserted. fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { - if let Some(args) = sess.target.options.pre_link_args.get(&flavor) { + if let Some(args) = sess.target.pre_link_args.get(&flavor) { cmd.args(args); } cmd.args(&sess.opts.debugging_opts.pre_link_args); @@ -1290,9 +1286,9 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) /// Add a link script embedded in the target, if applicable. fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) { - match (crate_type, &sess.target.options.link_script) { + match (crate_type, &sess.target.link_script) { (CrateType::Cdylib | CrateType::Executable, Some(script)) => { - if !sess.target.options.linker_is_gnu { + if !sess.target.linker_is_gnu { sess.fatal("can only use link script when linking with GNU-like linker"); } @@ -1335,15 +1331,15 @@ fn add_late_link_args( *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); if any_dynamic_crate { - if let Some(args) = sess.target.options.late_link_args_dynamic.get(&flavor) { + if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) { cmd.args(args); } } else { - if let Some(args) = sess.target.options.late_link_args_static.get(&flavor) { + if let Some(args) = sess.target.late_link_args_static.get(&flavor) { cmd.args(args); } } - if let Some(args) = sess.target.options.late_link_args.get(&flavor) { + if let Some(args) = sess.target.late_link_args.get(&flavor) { cmd.args(args); } } @@ -1351,7 +1347,7 @@ fn add_late_link_args( /// Add arbitrary "post-link" args defined by the target spec. /// FIXME: Determine where exactly these args need to be inserted. fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { - if let Some(args) = sess.target.options.post_link_args.get(&flavor) { + if let Some(args) = sess.target.post_link_args.get(&flavor) { cmd.args(args); } } @@ -1453,7 +1449,7 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: /// Add options making relocation sections in the produced ELF files read-only /// and suppressing lazy binding. fn add_relro_args(cmd: &mut dyn Linker, sess: &Session) { - match sess.opts.debugging_opts.relro_level.unwrap_or(sess.target.options.relro_level) { + match sess.opts.debugging_opts.relro_level.unwrap_or(sess.target.relro_level) { RelroLevel::Full => cmd.full_relro(), RelroLevel::Partial => cmd.partial_relro(), RelroLevel::Off => cmd.no_relro(), @@ -1484,9 +1480,9 @@ fn add_rpath_args( let mut rpath_config = RPathConfig { used_crates: &codegen_results.crate_info.used_crates_dynamic, out_filename: out_filename.to_path_buf(), - has_rpath: sess.target.options.has_rpath, - is_like_osx: sess.target.options.is_like_osx, - linker_is_gnu: sess.target.options.linker_is_gnu, + has_rpath: sess.target.has_rpath, + is_like_osx: sess.target.is_like_osx, + linker_is_gnu: sess.target.linker_is_gnu, get_install_prefix_lib_path: &mut get_install_prefix_lib_path, }; cmd.args(&rpath::get_rpath_flags(&mut rpath_config)); @@ -1514,7 +1510,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback); // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction // to the linker args construction. - assert!(base_cmd.get_args().is_empty() || sess.target.target_vendor == "uwp"); + assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp"); let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor, target_cpu); let link_output_kind = link_output_kind(sess, crate_type); @@ -1528,7 +1524,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( add_link_script(cmd, sess, tmpdir, crate_type); // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER - if sess.target.options.is_like_fuchsia && crate_type == CrateType::Executable { + if sess.target.is_like_fuchsia && crate_type == CrateType::Executable { let prefix = if sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::ADDRESS) { "asan/" } else { @@ -1538,7 +1534,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( } // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER - if sess.target.options.eh_frame_header { + if sess.target.eh_frame_header { cmd.add_eh_frame_header(); } @@ -1551,7 +1547,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( add_pre_link_objects(cmd, sess, link_output_kind, crt_objects_fallback); // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER - if sess.target.options.is_like_emscripten { + if sess.target.is_like_emscripten { cmd.arg("-s"); cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort { "DISABLE_EXCEPTION_CATCHING=1" @@ -1579,7 +1575,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( cmd.output_filename(out_filename); // OBJECT-FILES-NO, AUDIT-ORDER - if crate_type == CrateType::Executable && sess.target.options.is_like_windows { + if crate_type == CrateType::Executable && sess.target.is_like_windows { if let Some(ref s) = codegen_results.windows_subsystem { cmd.subsystem(s); } @@ -1623,7 +1619,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( // OBJECT-FILES-NO, AUDIT-ORDER // We want to prevent the compiler from accidentally leaking in any system libraries, // so by default we tell linkers not to link to any default libraries. - if !sess.opts.cg.default_linker_libraries && sess.target.options.no_default_libraries { + if !sess.opts.cg.default_linker_libraries && sess.target.no_default_libraries { cmd.no_default_libraries(); } @@ -1843,7 +1839,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // Converts a library file-stem into a cc -l argument fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str { - if stem.starts_with("lib") && !target.options.is_like_windows { &stem[3..] } else { stem } + if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem } } // Adds the static "rlib" versions of all crates to the command line. @@ -1938,7 +1934,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // though, so we let that object file slide. let skip_because_lto = are_upstream_rust_objects_already_included(sess) && is_rust_object - && (sess.target.options.no_builtins + && (sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum)); if skip_because_cfg_say_so || skip_because_lto { @@ -2082,9 +2078,9 @@ fn are_upstream_rust_objects_already_included(sess: &Session) -> bool { fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { let arch = &sess.target.arch; - let os = &sess.target.target_os; + let os = &sess.target.os; let llvm_target = &sess.target.llvm_target; - if sess.target.target_vendor != "apple" + if sess.target.vendor != "apple" || !matches!(os.as_str(), "ios" | "tvos") || flavor != LinkerFlavor::Gcc { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3e13a1daecd..3df956c465e 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -184,7 +184,7 @@ impl<'a> GccLinker<'a> { // * On OSX they have their own linker, not binutils' // * For WebAssembly the only functional linker is LLD, which doesn't // support hint flags - !self.sess.target.options.is_like_osx && self.sess.target.arch != "wasm32" + !self.sess.target.is_like_osx && self.sess.target.arch != "wasm32" } // Some platforms take hints about whether a library is static or dynamic. @@ -232,7 +232,7 @@ impl<'a> GccLinker<'a> { fn build_dylib(&mut self, out_filename: &Path) { // On mac we need to tell the linker to let this library be rpathed - if self.sess.target.options.is_like_osx { + if self.sess.target.is_like_osx { self.cmd.arg("-dynamiclib"); self.linker_arg("-dylib"); @@ -248,7 +248,7 @@ impl<'a> GccLinker<'a> { } } else { self.cmd.arg("-shared"); - if self.sess.target.options.is_like_windows { + if self.sess.target.is_like_windows { // The output filename already contains `dll_suffix` so // the resulting import library will have a name in the // form of libfoo.dll.a @@ -256,9 +256,9 @@ impl<'a> GccLinker<'a> { out_filename.file_name().and_then(|file| file.to_str()).map(|file| { format!( "{}{}{}", - self.sess.target.options.staticlib_prefix, + self.sess.target.staticlib_prefix, file, - self.sess.target.options.staticlib_suffix + self.sess.target.staticlib_suffix ) }); if let Some(implib_name) = implib_name { @@ -280,7 +280,7 @@ impl<'a> Linker for GccLinker<'a> { fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { match output_kind { LinkOutputKind::DynamicNoPicExe => { - if !self.is_ld && self.sess.target.options.linker_is_gnu { + if !self.is_ld && self.sess.target.linker_is_gnu { self.cmd.arg("-no-pie"); } } @@ -291,7 +291,7 @@ impl<'a> Linker for GccLinker<'a> { LinkOutputKind::StaticNoPicExe => { // `-static` works for both gcc wrapper and ld. self.cmd.arg("-static"); - if !self.is_ld && self.sess.target.options.linker_is_gnu { + if !self.is_ld && self.sess.target.linker_is_gnu { self.cmd.arg("-no-pie"); } } @@ -320,7 +320,7 @@ impl<'a> Linker for GccLinker<'a> { // any `#[link]` attributes in the `libc` crate, see #72782 for details. // FIXME: Switch to using `#[link]` attributes in the `libc` crate // similarly to other targets. - if self.sess.target.target_os == "vxworks" + if self.sess.target.os == "vxworks" && matches!( output_kind, LinkOutputKind::StaticNoPicExe @@ -386,7 +386,7 @@ impl<'a> Linker for GccLinker<'a> { fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]) { self.hint_static(); let target = &self.sess.target; - if !target.options.is_like_osx { + if !target.is_like_osx { self.linker_arg("--whole-archive").cmd.arg(format!("-l{}", lib)); self.linker_arg("--no-whole-archive"); } else { @@ -400,7 +400,7 @@ impl<'a> Linker for GccLinker<'a> { fn link_whole_rlib(&mut self, lib: &Path) { self.hint_static(); - if self.sess.target.options.is_like_osx { + if self.sess.target.is_like_osx { self.linker_arg("-force_load"); self.linker_arg(&lib); } else { @@ -424,9 +424,9 @@ impl<'a> Linker for GccLinker<'a> { // -dead_strip can't be part of the pre_link_args because it's also used // for partial linking when using multiple codegen units (-r). So we // insert it here. - if self.sess.target.options.is_like_osx { + if self.sess.target.is_like_osx { self.linker_arg("-dead_strip"); - } else if self.sess.target.options.is_like_solaris { + } else if self.sess.target.is_like_solaris { self.linker_arg("-zignore"); // If we're building a dylib, we don't use --gc-sections because LLVM @@ -440,7 +440,7 @@ impl<'a> Linker for GccLinker<'a> { } fn optimize(&mut self) { - if !self.sess.target.options.linker_is_gnu { + if !self.sess.target.linker_is_gnu { return; } @@ -454,7 +454,7 @@ impl<'a> Linker for GccLinker<'a> { } fn pgo_gen(&mut self) { - if !self.sess.target.options.linker_is_gnu { + if !self.sess.target.linker_is_gnu { return; } @@ -503,8 +503,7 @@ impl<'a> Linker for GccLinker<'a> { fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { // Symbol visibility in object files typically takes care of this. - if crate_type == CrateType::Executable - && self.sess.target.options.override_export_symbols.is_none() + if crate_type == CrateType::Executable && self.sess.target.override_export_symbols.is_none() { return; } @@ -513,7 +512,7 @@ impl<'a> Linker for GccLinker<'a> { // The object files have far more public symbols than we actually want to export, // so we hide them all here. - if !self.sess.target.options.limit_rdylib_exports { + if !self.sess.target.limit_rdylib_exports { return; } @@ -521,13 +520,13 @@ impl<'a> Linker for GccLinker<'a> { return; } - let is_windows = self.sess.target.options.is_like_windows; + let is_windows = self.sess.target.is_like_windows; let mut arg = OsString::new(); let path = tmpdir.join(if is_windows { "list.def" } else { "list" }); debug!("EXPORTED SYMBOLS:"); - if self.sess.target.options.is_like_osx { + if self.sess.target.is_like_osx { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); @@ -573,12 +572,12 @@ impl<'a> Linker for GccLinker<'a> { } } - if self.sess.target.options.is_like_osx { + if self.sess.target.is_like_osx { if !self.is_ld { arg.push("-Wl,") } arg.push("-exported_symbols_list,"); - } else if self.sess.target.options.is_like_solaris { + } else if self.sess.target.is_like_solaris { if !self.is_ld { arg.push("-Wl,") } @@ -1203,7 +1202,7 @@ impl<'a> Linker for WasmLd<'a> { } fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> { - if let Some(ref exports) = tcx.sess.target.options.override_export_symbols { + if let Some(ref exports) = tcx.sess.target.override_export_symbols { return exports.clone(); } @@ -1293,7 +1292,7 @@ impl<'a> Linker for PtxLinker<'a> { // Provide the linker with fallback to internal `target-cpu`. self.cmd.arg("--fallback-arch").arg(match self.sess.opts.cg.target_cpu { Some(ref s) => s, - None => &self.sess.target.options.cpu, + None => &self.sess.target.cpu, }); } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index dd8d751d045..9a6f8cde1b2 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -229,8 +229,7 @@ fn exported_symbols_provider_local( // needs to be exported. // However, on platforms that don't allow for Rust dylibs, having // external linkage is enough for monomorphization to be linked to. - let need_visibility = - tcx.sess.target.options.dynamic_linking && !tcx.sess.target.options.only_cdylib; + let need_visibility = tcx.sess.target.dynamic_linking && !tcx.sess.target.only_cdylib; let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 4d2cea18dcc..b34bee3358b 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -139,7 +139,7 @@ impl ModuleConfig { let emit_obj = if !should_emit_obj { EmitObj::None - } else if sess.target.options.obj_is_bitcode + } else if sess.target.obj_is_bitcode || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins) { // This case is selected if the target uses objects as bitcode, or @@ -221,11 +221,11 @@ impl ModuleConfig { false ), emit_obj, - bc_cmdline: sess.target.options.bitcode_llvm_cmdline.clone(), + bc_cmdline: sess.target.bitcode_llvm_cmdline.clone(), verify_llvm_ir: sess.verify_llvm_ir(), no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes, - no_builtins: no_builtins || sess.target.options.no_builtins, + no_builtins: no_builtins || sess.target.no_builtins, // Exclude metadata and allocator modules from time_passes output, // since they throw off the "LLVM passes" measurement. @@ -252,7 +252,7 @@ impl ModuleConfig { .opts .debugging_opts .merge_functions - .unwrap_or(sess.target.options.merge_functions) + .unwrap_or(sess.target.merge_functions) { MergeFunctions::Disabled => false, MergeFunctions::Trampolines | MergeFunctions::Aliases => { @@ -388,7 +388,7 @@ fn need_bitcode_in_object(sess: &Session) -> bool { let requested_for_rlib = sess.opts.cg.embed_bitcode && sess.crate_types().contains(&CrateType::Rlib) && sess.opts.output_types.contains_key(&OutputType::Exe); - let forced_by_target = sess.target.options.forces_embed_bitcode; + let forced_by_target = sess.target.forces_embed_bitcode; requested_for_rlib || forced_by_target } @@ -1865,11 +1865,11 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool { // something is wrong with commandline arg validation. assert!( !(tcx.sess.opts.cg.linker_plugin_lto.enabled() - && tcx.sess.target.options.is_like_windows + && tcx.sess.target.is_like_windows && tcx.sess.opts.cg.prefer_dynamic) ); - tcx.sess.target.options.is_like_windows && + tcx.sess.target.is_like_windows && tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) && // ThinLTO can't handle this workaround in all cases, so we don't // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index afb407b35be..5fe26dbf914 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -326,7 +326,7 @@ fn cast_shift_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// currently uses SEH-ish unwinding with DWARF info tables to the side (same as /// 64-bit MinGW) instead of "full SEH". pub fn wants_msvc_seh(sess: &Session) -> bool { - sess.target.options.is_like_msvc + sess.target.is_like_msvc } pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( @@ -387,7 +387,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) -> Bx::Function { // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, // depending on whether the target needs `argc` and `argv` to be passed in. - let llfty = if cx.sess().target.options.main_needs_argc_argv { + let llfty = if cx.sess().target.main_needs_argc_argv { cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()) } else { cx.type_func(&[], cx.type_int()) @@ -459,7 +459,7 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, bx: &mut Bx, ) -> (Bx::Value, Bx::Value) { - if cx.sess().target.options.main_needs_argc_argv { + if cx.sess().target.main_needs_argc_argv { // Params from native `main()` used as args for rust start function let param_argc = bx.get_param(0); let param_argv = bx.get_param(1); diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index c4c51d146a6..0b49a379070 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -33,7 +33,7 @@ pub fn push_debuginfo_type_name<'tcx>( ) { // When targeting MSVC, emit C++ style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let cpp_like_names = tcx.sess.target.options.is_like_msvc; + let cpp_like_names = tcx.sess.target.is_like_msvc; match *t.kind() { ty::Bool => output.push_str("bool"), diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 84e82e88e8e..01fd1681593 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -92,15 +92,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { T: Copy + TypeFoldable<'tcx>, { debug!("monomorphize: self.instance={:?}", self.instance); - if let Some(substs) = self.instance.substs_for_mir_body() { - self.cx.tcx().subst_and_normalize_erasing_regions( - substs, - ty::ParamEnv::reveal_all(), - &value, - ) - } else { - self.cx.tcx().normalize_erasing_regions(ty::ParamEnv::reveal_all(), *value) - } + self.instance.subst_mir_and_normalize_erasing_regions( + self.cx.tcx(), + ty::ParamEnv::reveal_all(), + value, + ) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 7ce110dcbfc..40ae0a13c72 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -502,6 +502,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => { + let ty = self.monomorphize(&ty); assert!(bx.cx().type_is_sized(ty)); let val = bx.cx().const_usize(bx.cx().layout_of(ty).size.bytes()); let tcx = self.cx.tcx(); diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 43bc0c83155..634a20bda9b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -51,11 +51,11 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } fn type_int(&self) -> Self::Type { - match &self.sess().target.target_c_int_width[..] { + match &self.sess().target.c_int_width[..] { "16" => self.type_i16(), "32" => self.type_i32(), "64" => self.type_i64(), - width => bug!("Unsupported target_c_int_width: {}", width), + width => bug!("Unsupported c_int_width: {}", width), } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index c2239a2f659..cccbdf778ed 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -545,11 +545,6 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { noop_flat_map_assoc_item(configure!(self, item), self) } - fn visit_mac(&mut self, _mac: &mut ast::MacCall) { - // Don't configure interpolated AST (cf. issue #34171). - // Interpolated AST will get configured once the surrounding tokens are parsed. - } - fn visit_pat(&mut self, pat: &mut P<ast::Pat>) { self.configure_pat(pat); noop_visit_pat(pat, self) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e06d81d49d1..1b31bd6a305 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -850,8 +850,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { visit::walk_item(self, item); } - - fn visit_mac(&mut self, _: &'ast ast::MacCall) {} } if !self.cx.ecfg.proc_macro_hygiene() { diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 629e0e702b6..dde65d998d8 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -5,7 +5,6 @@ use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, NtTT, Token}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing}; -use rustc_ast::MacCall; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{pluralize, PResult}; @@ -27,10 +26,6 @@ impl MutVisitor for Marker { fn visit_span(&mut self, span: &mut Span) { *span = span.apply_mark(self.0, self.1) } - - fn visit_mac(&mut self, mac: &mut MacCall) { - mut_visit::noop_visit_mac(mac, self) - } } /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). diff --git a/compiler/rustc_expand/src/mut_visit/tests.rs b/compiler/rustc_expand/src/mut_visit/tests.rs index 9e65fc2eca7..be0300bad98 100644 --- a/compiler/rustc_expand/src/mut_visit/tests.rs +++ b/compiler/rustc_expand/src/mut_visit/tests.rs @@ -1,7 +1,7 @@ use crate::tests::{matches_codepattern, string_to_crate}; use rustc_ast as ast; -use rustc_ast::mut_visit::{self, MutVisitor}; +use rustc_ast::mut_visit::MutVisitor; use rustc_ast_pretty::pprust; use rustc_span::symbol::Ident; use rustc_span::with_default_session_globals; @@ -21,9 +21,6 @@ impl MutVisitor for ToZzIdentMutVisitor { fn visit_ident(&mut self, ident: &mut Ident) { *ident = Ident::from_str("zz"); } - fn visit_mac(&mut self, mac: &mut ast::MacCall) { - mut_visit::noop_visit_mac(mac, self) - } } // Maybe add to `expand.rs`. diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index e413564fb3f..f0e5826f403 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -385,8 +385,4 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { |item| !matches!(item.kind, ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs), ); } - - fn visit_mac(&mut self, _mac: &mut ast::MacCall) { - // Do nothing. - } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index ad926a810e6..0df67b63eba 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -610,6 +610,12 @@ declare_features! ( /// Allows unsized fn parameters. (active, unsized_fn_params, "1.49.0", Some(48055), None), + /// Allows the use of destructuring assignments. + (active, destructuring_assignment, "1.49.0", Some(71126), None), + + /// Enables `#[cfg(panic = "...")]` config key. + (active, cfg_panic, "1.49.0", Some(77443), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 57ae534590d..5c5cf609ac3 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -33,6 +33,7 @@ const GATED_CFGS: &[GatedCfg] = &[ ), (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), (sym::version, sym::cfg_version, cfg_fn!(cfg_version)), + (sym::panic, sym::cfg_panic, cfg_fn!(cfg_panic)), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 3f109376a3e..d5ade86593e 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -409,7 +409,7 @@ impl Definitions { } pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId { - self.expansions_that_defined.get(&id).copied().unwrap_or(ExpnId::root()) + self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root) } pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b9ec18688c5..3c28b48795f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -732,6 +732,9 @@ pub struct Pat<'hir> { pub hir_id: HirId, pub kind: PatKind<'hir>, pub span: Span, + // Whether to use default binding modes. + // At present, this is false only for destructuring assignment. + pub default_binding_modes: bool, } impl Pat<'_> { @@ -1680,6 +1683,9 @@ pub enum LocalSource { AsyncFn, /// A desugared `<expr>.await`. AwaitDesugar, + /// A desugared `expr = expr`, where the LHS is a tuple, struct or array. + /// The span is that of the `=` sign. + AssignDesugar(Span), } /// Hints at the original code for a `match _ { .. }`. @@ -2677,6 +2683,9 @@ impl<'hir> Node<'hir> { Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) | Node::ForeignItem(ForeignItem { ident, .. }) + | Node::Field(StructField { ident, .. }) + | Node::Variant(Variant { ident, .. }) + | Node::MacroDef(MacroDef { ident, .. }) | Node::Item(Item { ident, .. }) => Some(*ident), _ => None, } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 7ab18e54f7e..59786059fae 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -102,43 +102,89 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { None => String::new(), }; - let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) { - (None, None) => { - let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id { + let (span_1, span_2, main_label, span_label, future_return_type) = + match (sup_is_ret_type, sub_is_ret_type) { + (None, None) => { + let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id { + ( + "this type is declared with multiple lifetimes...".to_owned(), + "...but data with one lifetime flows into the other here".to_owned(), + ) + } else { + ( + "these two types are declared with different lifetimes...".to_owned(), + format!("...but data{} flows{} here", span_label_var1, span_label_var2), + ) + }; + (ty_sup.span, ty_sub.span, main_label_1, span_label_1, None) + } + + (Some(ret_span), _) => { + let sup_future = self.future_return_type(scope_def_id_sup); + let (return_type, action) = if let Some(_) = sup_future { + ("returned future", "held across an await point") + } else { + ("return type", "returned") + }; + ( - "this type is declared with multiple lifetimes...".to_owned(), - "...but data with one lifetime flows into the other here".to_owned(), + ty_sub.span, + ret_span, + format!( + "this parameter and the {} are declared with different lifetimes...", + return_type + ), + format!("...but data{} is {} here", span_label_var1, action), + sup_future, ) - } else { + } + (_, Some(ret_span)) => { + let sub_future = self.future_return_type(scope_def_id_sub); + let (return_type, action) = if let Some(_) = sub_future { + ("returned future", "held across an await point") + } else { + ("return type", "returned") + }; + ( - "these two types are declared with different lifetimes...".to_owned(), - format!("...but data{} flows{} here", span_label_var1, span_label_var2), + ty_sup.span, + ret_span, + format!( + "this parameter and the {} are declared with different lifetimes...", + return_type + ), + format!("...but data{} is {} here", span_label_var1, action), + sub_future, ) - }; - (ty_sup.span, ty_sub.span, main_label_1, span_label_1) - } - - (Some(ret_span), _) => ( - ty_sub.span, - ret_span, - "this parameter and the return type are declared with different lifetimes..." - .to_owned(), - format!("...but data{} is returned here", span_label_var1), - ), - (_, Some(ret_span)) => ( - ty_sup.span, - ret_span, - "this parameter and the return type are declared with different lifetimes..." - .to_owned(), - format!("...but data{} is returned here", span_label_var1), - ), - }; - - struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch") - .span_label(span_1, main_label) - .span_label(span_2, String::new()) - .span_label(span, span_label) - .emit(); + } + }; + + let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); + + e.span_label(span_1, main_label); + e.span_label(span_2, String::new()); + e.span_label(span, span_label); + + if let Some(t) = future_return_type { + let snip = self + .tcx() + .sess + .source_map() + .span_to_snippet(t.span) + .ok() + .and_then(|s| match (&t.kind, s.as_str()) { + (rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()), + (_, "") => None, + _ => Some(s), + }) + .unwrap_or("{unnamed_type}".to_string()); + + e.span_label( + t.span, + &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip), + ); + } + e.emit(); Some(ErrorReported) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index c055fed43f6..ca93b2777ab 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -85,6 +85,60 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }) } + pub(super) fn future_return_type( + &self, + local_def_id: LocalDefId, + ) -> Option<&rustc_hir::Ty<'_>> { + if let Some(hir::IsAsync::Async) = self.asyncness(local_def_id) { + if let rustc_middle::ty::Opaque(def_id, _) = + self.tcx().type_of(local_def_id).fn_sig(self.tcx()).output().skip_binder().kind() + { + match self.tcx().hir().get_if_local(*def_id) { + Some(hir::Node::Item(hir::Item { + kind: + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + bounds, + origin: hir::OpaqueTyOrigin::AsyncFn, + .. + }), + .. + })) => { + for b in bounds.iter() { + if let hir::GenericBound::LangItemTrait( + hir::LangItem::Future, + _span, + _hir_id, + generic_args, + ) = b + { + for type_binding in generic_args.bindings.iter() { + if type_binding.ident.name == rustc_span::sym::Output { + if let hir::TypeBindingKind::Equality { ty } = + type_binding.kind + { + return Some(ty); + } + } + } + } + } + } + _ => {} + } + } + } + None + } + + pub(super) fn asyncness(&self, local_def_id: LocalDefId) -> Option<hir::IsAsync> { + // similar to the asyncness fn in rustc_ty::ty + let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id); + let node = self.tcx().hir().get(hir_id); + let fn_like = rustc_middle::hir::map::blocks::FnLikeNode::from_node(node)?; + + Some(fn_like.asyncness()) + } + // Here, we check for the case where the anonymous region // is in the return type. // FIXME(#42703) - Need to handle certain cases here. diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index dfc6f691457..1fc2d281e79 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -554,6 +554,8 @@ fn test_debugging_options_tracking_hash() { tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); tracked!(inline_in_all_cgus, Some(true)); + tracked!(inline_mir_threshold, 123); + tracked!(inline_mir_hint_threshold, 123); tracked!(insert_sideeffect, true); tracked!(instrument_coverage, true); tracked!(instrument_mcount, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 3ed7d20ae45..d9ec6d51cdf 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -880,12 +880,6 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { }) } } - - // in general the pretty printer processes unexpanded code, so - // we override the default `visit_mac` method which panics. - fn visit_mac(&mut self, mac: &mut ast::MacCall) { - noop_visit_mac(mac, self) - } } /// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)" diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 9aeeb627792..08c147ec3ac 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -270,15 +270,9 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> self.check_id(id); } - fn visit_mac(&mut self, mac: &'a ast::MacCall) { - // FIXME(#54110): So, this setup isn't really right. I think - // that (a) the librustc_ast visitor ought to be doing this as - // part of `walk_mac`, and (b) we should be calling - // `visit_path`, *but* that would require a `NodeId`, and I - // want to get #53686 fixed quickly. -nmatsakis - ast_visit::walk_path(self, &mac.path); - + fn visit_mac_call(&mut self, mac: &'a ast::MacCall) { run_early_pass!(self, check_mac, mac); + ast_visit::walk_mac(self, mac); } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index ff7a145c266..1d0d6980b7a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2801,6 +2801,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, IRREFUTABLE_LET_PATTERNS, BROKEN_INTRA_DOC_LINKS, + PRIVATE_INTRA_DOC_LINKS, INVALID_CODEBLOCK_ATTRIBUTES, MISSING_CRATE_LEVEL_DOCS, MISSING_DOC_CODE_EXAMPLES, diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 44f57cfbe28..c3afc9f048c 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -127,7 +127,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { if ty == CrateType::Staticlib || (ty == CrateType::Executable && sess.crt_static(Some(ty)) - && !sess.target.options.crt_static_allows_dylibs) + && !sess.target.crt_static_allows_dylibs) { for &cnum in tcx.crates().iter() { if tcx.dep_kind(cnum).macros_only() { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index d16985b9c2b..c4c025de8b3 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -373,11 +373,10 @@ impl<'a> CrateLocator<'a> { seen_paths: &mut FxHashSet<PathBuf>, ) -> Result<Option<Library>, CrateError> { // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = - format!("{}{}{}", self.target.options.dll_prefix, self.crate_name, extra_prefix); + let dylib_prefix = format!("{}{}{}", self.target.dll_prefix, self.crate_name, extra_prefix); let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix); let staticlib_prefix = - format!("{}{}{}", self.target.options.staticlib_prefix, self.crate_name, extra_prefix); + format!("{}{}{}", self.target.staticlib_prefix, self.crate_name, extra_prefix); let mut candidates: FxHashMap<_, (FxHashMap<_, _>, FxHashMap<_, _>, FxHashMap<_, _>)> = Default::default(); @@ -405,17 +404,14 @@ impl<'a> CrateLocator<'a> { (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib) } else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") { (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta) - } else if file.starts_with(&dylib_prefix) - && file.ends_with(&self.target.options.dll_suffix) - { + } else if file.starts_with(&dylib_prefix) && file.ends_with(&self.target.dll_suffix) { ( - &file - [(dylib_prefix.len())..(file.len() - self.target.options.dll_suffix.len())], + &file[(dylib_prefix.len())..(file.len() - self.target.dll_suffix.len())], CrateFlavor::Dylib, ) } else { if file.starts_with(&staticlib_prefix) - && file.ends_with(&self.target.options.staticlib_suffix) + && file.ends_with(&self.target.staticlib_suffix) { staticlibs .push(CrateMismatch { path: spf.path.clone(), got: "static".to_string() }); @@ -679,8 +675,8 @@ impl<'a> CrateLocator<'a> { }; if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) - || file.starts_with(&self.target.options.dll_prefix) - && file.ends_with(&self.target.options.dll_suffix) + || file.starts_with(&self.target.dll_prefix) + && file.ends_with(&self.target.dll_suffix) { // Make sure there's at most one rlib and at most one dylib. // Note to take care and match against the non-canonicalized name: @@ -712,8 +708,8 @@ impl<'a> CrateLocator<'a> { crate_name: self.crate_name, root: self.root.cloned(), triple: self.triple, - dll_prefix: self.target.options.dll_prefix.clone(), - dll_suffix: self.target.options.dll_suffix.clone(), + dll_prefix: self.target.dll_prefix.clone(), + dll_suffix: self.target.dll_suffix.clone(), rejected_via_hash: self.rejected_via_hash, rejected_via_triple: self.rejected_via_triple, rejected_via_kind: self.rejected_via_kind, diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 5e65f075ea4..2f7c2c2c405 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -149,7 +149,7 @@ impl Collector<'tcx> { } return; } - let is_osx = self.tcx.sess.target.options.is_like_osx; + let is_osx = self.tcx.sess.target.is_like_osx; if lib.kind == NativeLibKind::Framework && !is_osx { let msg = "native frameworks are only available on macOS targets"; match span { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c031e0e2e19..746c3b6af12 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -856,7 +856,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, index) - .unwrap_or(Lazy::empty()) + .unwrap_or_else(Lazy::empty) .decode(self) .map(|index| ty::FieldDef { did: self.local_def_id(index), @@ -888,7 +888,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, item_id) - .unwrap_or(Lazy::empty()) + .unwrap_or_else(Lazy::empty) .decode(self) .map(|index| self.get_variant(&self.kind(index), index, did, tcx.sess)) .collect() @@ -1075,7 +1075,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { // Iterate over all children. let macros_only = self.dep_kind.lock().macros_only(); - let children = self.root.tables.children.get(self, id).unwrap_or(Lazy::empty()); + let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty); for child_index in children.decode((self, sess)) { if macros_only { continue; @@ -1098,7 +1098,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, child_index) - .unwrap_or(Lazy::empty()); + .unwrap_or_else(Lazy::empty); for child_index in child_children.decode((self, sess)) { let kind = self.def_kind(child_index); callback(Export { @@ -1284,7 +1284,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> { - self.root.tables.variances.get(self, id).unwrap_or(Lazy::empty()).decode(self).collect() + self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self).collect() } fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { @@ -1323,7 +1323,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .attributes .get(self, item_id) - .unwrap_or(Lazy::empty()) + .unwrap_or_else(Lazy::empty) .decode((self, sess)) .collect::<Vec<_>>() } @@ -1333,7 +1333,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, id) - .unwrap_or(Lazy::empty()) + .unwrap_or_else(Lazy::empty) .decode(self) .map(|index| respan(self.get_span(index, sess), self.item_ident(index, sess).name)) .collect() @@ -1349,7 +1349,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .inherent_impls .get(self, id) - .unwrap_or(Lazy::empty()) + .unwrap_or_else(Lazy::empty) .decode(self) .map(|index| self.local_def_id(index)), ) diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 66532ea02f3..3250f1830de 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -26,7 +26,7 @@ rustc_index = { path = "../rustc_index" } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -chalk-ir = "0.32.0" +chalk-ir = "0.36.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "9.0.0" rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 106fa8c78fa..d86e8987195 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -478,7 +478,7 @@ impl<'hir> Map<'hir> { } pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> { - id.as_local().map(|id| self.get(self.local_def_id_to_hir_id(id))) + id.as_local().and_then(|id| self.find(self.local_def_id_to_hir_id(id))) } pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> { diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index def9e5ebb52..41342764ba7 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -48,10 +48,12 @@ fn update_limit( .unwrap_or(attr.span); let error_str = match e.kind() { - IntErrorKind::Overflow => "`limit` is too large", + IntErrorKind::PosOverflow => "`limit` is too large", IntErrorKind::Empty => "`limit` must be a non-negative integer", IntErrorKind::InvalidDigit => "not a valid integer", - IntErrorKind::Underflow => bug!("`limit` should never underflow"), + IntErrorKind::NegOverflow => { + bug!("`limit` should never negatively overflow") + } IntErrorKind::Zero => bug!("zero is a valid `limit`"), kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), }; diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 391bd8be7e4..0801188b278 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -109,24 +109,21 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { args.visit_with(visitor) } Assert { ref cond, ref msg, .. } => { - if cond.visit_with(visitor).is_break() { - use AssertKind::*; - match msg { - BoundsCheck { ref len, ref index } => { - len.visit_with(visitor)?; - index.visit_with(visitor) - } - Overflow(_, l, r) => { - l.visit_with(visitor)?; - r.visit_with(visitor) - } - OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => { - op.visit_with(visitor) - } - ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE, + cond.visit_with(visitor)?; + use AssertKind::*; + match msg { + BoundsCheck { ref len, ref index } => { + len.visit_with(visitor)?; + index.visit_with(visitor) + } + Overflow(_, l, r) => { + l.visit_with(visitor)?; + r.visit_with(visitor) + } + OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => { + op.visit_with(visitor) } - } else { - ControlFlow::CONTINUE + ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE, } } InlineAsm { ref operands, .. } => operands.visit_with(visitor), diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs index d8507d08c1b..f864ad8ebcd 100644 --- a/compiler/rustc_middle/src/traits/chalk.rs +++ b/compiler/rustc_middle/src/traits/chalk.rs @@ -102,48 +102,6 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { Some(write()) } - fn debug_application_ty( - application_ty: &chalk_ir::ApplicationTy<Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - match application_ty.name { - chalk_ir::TypeName::Ref(mutbl) => { - let data = application_ty.substitution.interned(); - match (&**data[0].interned(), &**data[1].interned()) { - ( - chalk_ir::GenericArgData::Lifetime(lifetime), - chalk_ir::GenericArgData::Ty(ty), - ) => Some(match mutbl { - chalk_ir::Mutability::Not => write!(fmt, "(&{:?} {:?})", lifetime, ty), - chalk_ir::Mutability::Mut => write!(fmt, "(&{:?} mut {:?})", lifetime, ty), - }), - _ => unreachable!(), - } - } - chalk_ir::TypeName::Array => { - let data = application_ty.substitution.interned(); - match (&**data[0].interned(), &**data[1].interned()) { - (chalk_ir::GenericArgData::Ty(ty), chalk_ir::GenericArgData::Const(len)) => { - Some(write!(fmt, "[{:?}; {:?}]", ty, len)) - } - _ => unreachable!(), - } - } - chalk_ir::TypeName::Slice => { - let data = application_ty.substitution.interned(); - let ty = match &**data[0].interned() { - chalk_ir::GenericArgData::Ty(t) => t, - _ => unreachable!(), - }; - Some(write!(fmt, "[{:?}]", ty)) - } - _ => { - let chalk_ir::ApplicationTy { name, substitution } = application_ty; - Some(write!(fmt, "{:?}{:?}", name, chalk_ir::debug::Angle(substitution.interned()))) - } - } - } - fn debug_substitution( substitution: &chalk_ir::Substitution<Self>, fmt: &mut fmt::Formatter<'_>, @@ -174,6 +132,32 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { Some(write!(fmt, "{:?}", clauses.interned())) } + fn debug_ty(ty: &chalk_ir::Ty<Self>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { + match &ty.interned().kind { + chalk_ir::TyKind::Ref(chalk_ir::Mutability::Not, lifetime, ty) => { + Some(write!(fmt, "(&{:?} {:?})", lifetime, ty)) + } + chalk_ir::TyKind::Ref(chalk_ir::Mutability::Mut, lifetime, ty) => { + Some(write!(fmt, "(&{:?} mut {:?})", lifetime, ty)) + } + chalk_ir::TyKind::Array(ty, len) => Some(write!(fmt, "[{:?}; {:?}]", ty, len)), + chalk_ir::TyKind::Slice(ty) => Some(write!(fmt, "[{:?}]", ty)), + chalk_ir::TyKind::Tuple(len, substs) => Some((|| { + write!(fmt, "(")?; + for (idx, substitution) in substs.interned().iter().enumerate() { + if idx == *len && *len != 1 { + // Don't add a trailing comma if the tuple has more than one element + write!(fmt, "{:?}", substitution)?; + } else { + write!(fmt, "{:?},", substitution)?; + } + } + write!(fmt, ")") + })()), + _ => None, + } + } + fn debug_alias( alias_ty: &chalk_ir::AliasTy<Self>, fmt: &mut fmt::Formatter<'_>, diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 126257a5b49..63e95f25bb7 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -168,7 +168,7 @@ impl ScalarInt { #[inline(always)] fn check_data(self) { // Using a block `{self.data}` here to force a copy instead of using `self.data` - // directly, because `assert_eq` takes references to its arguments and formatting + // directly, because `debug_assert_eq` takes references to its arguments and formatting // arguments and would thus borrow `self.data`. Since `Self` // is a packed struct, that would create a possibly unaligned reference, which // is UB. diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 8b3fb875070..306cebd9cb7 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -1,6 +1,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::print::{FmtPrinter, Printer}; -use crate::ty::subst::InternalSubsts; +use crate::ty::subst::{InternalSubsts, Subst}; use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; use rustc_errors::ErrorReported; use rustc_hir::def::Namespace; @@ -470,10 +470,33 @@ impl<'tcx> Instance<'tcx> { /// This function returns `Some(substs)` in the former case and `None` otherwise -- i.e., if /// this function returns `None`, then the MIR body does not require substitution during /// codegen. - pub fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> { + fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> { if self.def.has_polymorphic_mir_body() { Some(self.substs) } else { None } } + pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: &T) -> T + where + T: TypeFoldable<'tcx> + Copy, + { + if let Some(substs) = self.substs_for_mir_body() { v.subst(tcx, substs) } else { *v } + } + + pub fn subst_mir_and_normalize_erasing_regions<T>( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + v: &T, + ) -> T + where + T: TypeFoldable<'tcx> + Clone, + { + if let Some(substs) = self.substs_for_mir_body() { + tcx.subst_and_normalize_erasing_regions(substs, param_env, v) + } else { + tcx.normalize_erasing_regions(param_env, v.clone()) + } + } + /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by /// identify parameters if they are determined to be unused in `instance.def`. pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 91c3dcbfa81..1e93c3650b8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2601,15 +2601,14 @@ where }; let target = &cx.tcx().sess.target; - let target_env_gnu_like = matches!(&target.target_env[..], "gnu" | "musl"); - let win_x64_gnu = - target.target_os == "windows" && target.arch == "x86_64" && target.target_env == "gnu"; + let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl"); + let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; let linux_s390x_gnu_like = - target.target_os == "linux" && target.arch == "s390x" && target_env_gnu_like; + target.os == "linux" && target.arch == "s390x" && target_env_gnu_like; let linux_sparc64_gnu_like = - target.target_os == "linux" && target.arch == "sparc64" && target_env_gnu_like; + target.os == "linux" && target.arch == "sparc64" && target_env_gnu_like; let linux_powerpc_gnu_like = - target.target_os == "linux" && target.arch == "powerpc" && target_env_gnu_like; + target.os == "linux" && target.arch == "powerpc" && target_env_gnu_like; let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall); // Handle safe Rust thin and fat pointers. @@ -2775,7 +2774,7 @@ where // anyway, we control all calls to it in libstd. Abi::Vector { .. } if abi != SpecAbi::PlatformIntrinsic - && cx.tcx().sess.target.options.simd_types_indirect => + && cx.tcx().sess.target.simd_types_indirect => { arg.make_indirect(); return; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index aa5a696b09c..0042b4a3a42 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2795,10 +2795,50 @@ impl<'tcx> TyCtxt<'tcx> { .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value()) } + fn item_name_from_hir(self, def_id: DefId) -> Option<Ident> { + self.hir().get_if_local(def_id).and_then(|node| node.ident()) + } + + fn item_name_from_def_id(self, def_id: DefId) -> Option<Symbol> { + if def_id.index == CRATE_DEF_INDEX { + Some(self.original_crate_name(def_id.krate)) + } else { + let def_key = self.def_key(def_id); + match def_key.disambiguated_data.data { + // The name of a constructor is that of its parent. + rustc_hir::definitions::DefPathData::Ctor => self.item_name_from_def_id(DefId { + krate: def_id.krate, + index: def_key.parent.unwrap(), + }), + _ => def_key.disambiguated_data.data.get_opt_name(), + } + } + } + + /// Look up the name of an item across crates. This does not look at HIR. + /// + /// When possible, this function should be used for cross-crate lookups over + /// [`opt_item_name`] to avoid invalidating the incremental cache. If you + /// need to handle items without a name, or HIR items that will not be + /// serialized cross-crate, or if you need the span of the item, use + /// [`opt_item_name`] instead. + /// + /// [`opt_item_name`]: Self::opt_item_name + pub fn item_name(self, id: DefId) -> Symbol { + // Look at cross-crate items first to avoid invalidating the incremental cache + // unless we have to. + self.item_name_from_def_id(id).unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) + } + + /// Look up the name and span of an item or [`Node`]. + /// + /// See [`item_name`][Self::item_name] for more information. pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> { - def_id - .as_local() - .and_then(|def_id| self.hir().get(self.hir().local_def_id_to_hir_id(def_id)).ident()) + // Look at the HIR first so the span will be correct if this is a local item. + self.item_name_from_hir(def_id) + .or_else(|| self.item_name_from_def_id(def_id).map(Ident::with_dummy_span)) } pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> { @@ -2921,23 +2961,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn item_name(self, id: DefId) -> Symbol { - if id.index == CRATE_DEF_INDEX { - self.original_crate_name(id.krate) - } else { - let def_key = self.def_key(id); - match def_key.disambiguated_data.data { - // The name of a constructor is that of its parent. - rustc_hir::definitions::DefPathData::Ctor => { - self.item_name(DefId { krate: id.krate, index: def_key.parent.unwrap() }) - } - _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { - bug!("item_name: no name for {:?}", self.def_path(id)); - }), - } - } - } - /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { match instance { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8ff4adda606..1e4fd0921ee 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -63,7 +63,7 @@ thread_local! { /// Avoids running any queries during any prints that occur /// during the closure. This may alter the appearance of some /// types (e.g. forcing verbose printing for opaque types). -/// This method is used during some queries (e.g. `predicates_of` +/// This method is used during some queries (e.g. `explicit_item_bounds` /// for opaque types), to ensure that any debug printing that /// occurs during the query computation does not end up recursively /// calling the same query. diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs index 2e5a231fef0..2a90fb042dd 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs @@ -6,8 +6,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, RegionVid, Ty}; -use rustc_span::symbol::kw; -use rustc_span::{symbol::Symbol, Span, DUMMY_SP}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::{Span, DUMMY_SP}; use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt}; @@ -39,7 +39,7 @@ crate enum RegionNameSource { /// The region corresponding to a closure upvar. AnonRegionFromUpvar(Span, String), /// The region corresponding to the return type of a closure. - AnonRegionFromOutput(Span, String, String), + AnonRegionFromOutput(RegionNameHighlight, String), /// The region from a type yielded by a generator. AnonRegionFromYieldTy(Span, String), /// An anonymous region from an async fn. @@ -57,6 +57,10 @@ crate enum RegionNameHighlight { /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. CannotMatchHirTy(Span, String), + /// The anonymous region corresponds to a region where the type annotation is completely missing + /// from the code, and *even if* we print out the full name of the type, the region name won't + /// be included. This currently occurs for opaque types like `impl Future`. + Occluded(Span, String), } impl RegionName { @@ -81,13 +85,14 @@ impl RegionName { | RegionNameSource::NamedFreeRegion(span) | RegionNameSource::SynthesizedFreeEnvRegion(span, _) | RegionNameSource::AnonRegionFromUpvar(span, _) - | RegionNameSource::AnonRegionFromOutput(span, _, _) | RegionNameSource::AnonRegionFromYieldTy(span, _) | RegionNameSource::AnonRegionFromAsyncFn(span) => Some(span), - RegionNameSource::AnonRegionFromArgument(ref highlight) => match *highlight { + RegionNameSource::AnonRegionFromArgument(ref highlight) + | RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight { RegionNameHighlight::MatchedHirTy(span) | RegionNameHighlight::MatchedAdtAndSegment(span) - | RegionNameHighlight::CannotMatchHirTy(span, _) => Some(span), + | RegionNameHighlight::CannotMatchHirTy(span, _) + | RegionNameHighlight::Occluded(span, _) => Some(span), }, } } @@ -112,6 +117,7 @@ impl RegionName { diag.span_label(*span, format!("has type `{}`", type_name)); } RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::MatchedHirTy(span)) + | RegionNameSource::AnonRegionFromOutput(RegionNameHighlight::MatchedHirTy(span), _) | RegionNameSource::AnonRegionFromAsyncFn(span) => { diag.span_label( *span, @@ -120,16 +126,44 @@ impl RegionName { } RegionNameSource::AnonRegionFromArgument( RegionNameHighlight::MatchedAdtAndSegment(span), + ) + | RegionNameSource::AnonRegionFromOutput( + RegionNameHighlight::MatchedAdtAndSegment(span), + _, ) => { diag.span_label(*span, format!("let's call this `{}`", self)); } + RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::Occluded( + span, + type_name, + )) => { + diag.span_label( + *span, + format!("lifetime `{}` appears in the type {}", self, type_name), + ); + } + RegionNameSource::AnonRegionFromOutput( + RegionNameHighlight::Occluded(span, type_name), + mir_description, + ) => { + diag.span_label( + *span, + format!( + "return type{} `{}` contains a lifetime `{}`", + mir_description, type_name, self + ), + ); + } RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => { diag.span_label( *span, format!("lifetime `{}` appears in the type of `{}`", self, upvar_name), ); } - RegionNameSource::AnonRegionFromOutput(span, mir_description, type_name) => { + RegionNameSource::AnonRegionFromOutput( + RegionNameHighlight::CannotMatchHirTy(span, type_name), + mir_description, + ) => { diag.span_label(*span, format!("return type{} is {}", mir_description, type_name)); } RegionNameSource::AnonRegionFromYieldTy(span, type_name) => { @@ -349,19 +383,21 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { argument_index, ); - self.get_argument_hir_ty_for_highlighting(argument_index) + let highlight = self + .get_argument_hir_ty_for_highlighting(argument_index) .and_then(|arg_hir_ty| self.highlight_if_we_can_match_hir_ty(fr, arg_ty, arg_hir_ty)) - .or_else(|| { + .unwrap_or_else(|| { // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to // the anonymous region. If it succeeds, the `synthesize_region_name` call below // will increment the counter, "reserving" the number we just used. let counter = *self.next_region_name.try_borrow().unwrap(); self.highlight_if_we_cannot_match_hir_ty(fr, arg_ty, span, counter) - }) - .map(|highlight| RegionName { - name: self.synthesize_region_name(), - source: RegionNameSource::AnonRegionFromArgument(highlight), - }) + }); + + Some(RegionName { + name: self.synthesize_region_name(), + source: RegionNameSource::AnonRegionFromArgument(highlight), + }) } fn get_argument_hir_ty_for_highlighting( @@ -399,7 +435,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty: Ty<'tcx>, span: Span, counter: usize, - ) -> Option<RegionNameHighlight> { + ) -> RegionNameHighlight { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(needle_fr, counter); let type_name = @@ -411,9 +447,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ); if type_name.find(&format!("'{}", counter)).is_some() { // Only add a label if we can confirm that a region was labelled. - Some(RegionNameHighlight::CannotMatchHirTy(span, type_name)) + RegionNameHighlight::CannotMatchHirTy(span, type_name) } else { - None + RegionNameHighlight::Occluded(span, type_name) } } @@ -643,6 +679,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// or be early bound (named, not in argument). fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> { let tcx = self.infcx.tcx; + let hir = tcx.hir(); let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); @@ -650,42 +687,123 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { return None; } - let mut highlight = RegionHighlightMode::default(); - highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); - let type_name = - self.infcx.extract_inference_diagnostics_data(return_ty.into(), Some(highlight)).name; + let mir_hir_id = self.mir_hir_id(); - let (return_span, mir_description) = match tcx.hir().get(self.mir_hir_id()) { + let (return_span, mir_description, hir_ty) = match hir.get(mir_hir_id) { hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(_, return_ty, _, span, gen_move), - .. - }) => ( - match return_ty.output { - hir::FnRetTy::DefaultReturn(_) => tcx.sess.source_map().end_point(*span), - hir::FnRetTy::Return(_) => return_ty.output.span(), - }, - if gen_move.is_some() { " of generator" } else { " of closure" }, - ), - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(method_sig, _), + kind: hir::ExprKind::Closure(_, return_ty, body_id, span, _), .. - }) => (method_sig.decl.output.span(), ""), - _ => (self.body.span, ""), + }) => { + let (mut span, mut hir_ty) = match return_ty.output { + hir::FnRetTy::DefaultReturn(_) => { + (tcx.sess.source_map().end_point(*span), None) + } + hir::FnRetTy::Return(hir_ty) => (return_ty.output.span(), Some(hir_ty)), + }; + let mir_description = match hir.body(*body_id).generator_kind { + Some(hir::GeneratorKind::Async(gen)) => match gen { + hir::AsyncGeneratorKind::Block => " of async block", + hir::AsyncGeneratorKind::Closure => " of async closure", + hir::AsyncGeneratorKind::Fn => { + let parent_item = hir.get(hir.get_parent_item(mir_hir_id)); + let output = &parent_item + .fn_decl() + .expect("generator lowered from async fn should be in fn") + .output; + span = output.span(); + if let hir::FnRetTy::Return(ret) = output { + hir_ty = Some(self.get_future_inner_return_ty(*ret)); + } + " of async function" + } + }, + Some(hir::GeneratorKind::Gen) => " of generator", + None => " of closure", + }; + (span, mir_description, hir_ty) + } + node => match node.fn_decl() { + Some(fn_decl) => { + let hir_ty = match fn_decl.output { + hir::FnRetTy::DefaultReturn(_) => None, + hir::FnRetTy::Return(ty) => Some(ty), + }; + (fn_decl.output.span(), "", hir_ty) + } + None => (self.body.span, "", None), + }, }; + let highlight = hir_ty + .and_then(|hir_ty| self.highlight_if_we_can_match_hir_ty(fr, return_ty, hir_ty)) + .unwrap_or_else(|| { + // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to + // the anonymous region. If it succeeds, the `synthesize_region_name` call below + // will increment the counter, "reserving" the number we just used. + let counter = *self.next_region_name.try_borrow().unwrap(); + self.highlight_if_we_cannot_match_hir_ty(fr, return_ty, return_span, counter) + }); + Some(RegionName { - // This counter value will already have been used, so this function will increment it - // so the next value will be used next and return the region name that would have been - // used. name: self.synthesize_region_name(), - source: RegionNameSource::AnonRegionFromOutput( - return_span, - mir_description.to_string(), - type_name, - ), + source: RegionNameSource::AnonRegionFromOutput(highlight, mir_description.to_string()), }) } + /// From the [`hir::Ty`] of an async function's lowered return type, + /// retrieve the `hir::Ty` representing the type the user originally wrote. + /// + /// e.g. given the function: + /// + /// ``` + /// async fn foo() -> i32 {} + /// ``` + /// + /// this function, given the lowered return type of `foo`, an [`OpaqueDef`] that implements `Future<Output=i32>`, + /// returns the `i32`. + /// + /// [`OpaqueDef`]: hir::TyKind::OpaqueDef + fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { + let hir = self.infcx.tcx.hir(); + + if let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind { + let opaque_ty = hir.item(id.id); + if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { + bounds: + [hir::GenericBound::LangItemTrait( + hir::LangItem::Future, + _, + _, + hir::GenericArgs { + bindings: + [hir::TypeBinding { + ident: Ident { name: sym::Output, .. }, + kind: hir::TypeBindingKind::Equality { ty }, + .. + }], + .. + }, + )], + .. + }) = opaque_ty.kind + { + ty + } else { + span_bug!( + hir_ty.span, + "bounds from lowered return type of async fn did not match expected format: {:?}", + opaque_ty + ); + } + } else { + span_bug!( + hir_ty.span, + "lowered return type of async fn is not OpaqueDef: {:?}", + hir_ty + ); + } + } + fn give_name_if_anonymous_region_appears_in_yield_ty( &self, fr: RegionVid, diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs index ac8ab71a1dc..a5a7012852d 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs @@ -582,7 +582,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_member_constraints(infcx, &mut errors_buffer); } - let outlives_requirements = outlives_requirements.unwrap_or(vec![]); + let outlives_requirements = outlives_requirements.unwrap_or_default(); if outlives_requirements.is_empty() { (None, errors_buffer) diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir/src/dataflow/framework/engine.rs index 1b7264f86a2..3f9f558223b 100644 --- a/compiler/rustc_mir/src/dataflow/framework/engine.rs +++ b/compiler/rustc_mir/src/dataflow/framework/engine.rs @@ -208,12 +208,19 @@ where } } + // `state` is not actually used between iterations; + // this is just an optimization to avoid reallocating + // every iteration. let mut state = analysis.bottom_value(body); while let Some(bb) = dirty_queue.pop() { let bb_data = &body[bb]; - // Apply the block transfer function, using the cached one if it exists. + // Set the state to the entry state of the block. + // This is equivalent to `state = entry_sets[bb].clone()`, + // but it saves an allocation, thus improving compile times. state.clone_from(&entry_sets[bb]); + + // Apply the block transfer function, using the cached one if it exists. match &apply_trans_for_block { Some(apply) => apply(bb, &mut state), None => A::Direction::apply_effects_in_block(&analysis, &mut state, bb, bb_data), diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 8d0c8c18537..0f86a181a55 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -505,11 +505,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, value: T, ) -> T { - if let Some(substs) = frame.instance.substs_for_mir_body() { - self.tcx.subst_and_normalize_erasing_regions(substs, self.param_env, &value) - } else { - self.tcx.normalize_erasing_regions(self.param_env, value) - } + frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, &value) } /// The `substs` are assumed to already be in our interpreter "universe" (param_env). diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 417176564b9..938181abff2 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -543,11 +543,11 @@ impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> { T: TypeFoldable<'tcx>, { debug!("monomorphize: self.instance={:?}", self.instance); - if let Some(substs) = self.instance.substs_for_mir_body() { - self.tcx.subst_and_normalize_erasing_regions(substs, ty::ParamEnv::reveal_all(), &value) - } else { - self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), value) - } + self.instance.subst_mir_and_normalize_erasing_regions( + self.tcx, + ty::ParamEnv::reveal_all(), + &value, + ) } } diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs index 5083a45b539..037b80e4bf2 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs +++ b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs @@ -532,7 +532,7 @@ fn mono_item_visibility( } fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility { - if !tcx.sess.target.options.default_hidden_visibility { + if !tcx.sess.target.default_hidden_visibility { return Visibility::Default; } diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index f3d2ab9590e..7737672dbde 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -1,24 +1,20 @@ //! Inlining pass for MIR functions use rustc_attr as attr; +use rustc_hir as hir; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_span::{hygiene::ExpnKind, ExpnData, Span}; use rustc_target::spec::abi::Abi; use super::simplify::{remove_dead_blocks, CfgSimplifier}; use crate::transform::MirPass; -use std::collections::VecDeque; use std::iter; -use std::ops::RangeFrom; - -const DEFAULT_THRESHOLD: usize = 50; -const HINT_THRESHOLD: usize = 100; +use std::ops::{Range, RangeFrom}; const INSTR_COST: usize = 5; const CALL_PENALTY: usize = 25; @@ -32,140 +28,135 @@ pub struct Inline; #[derive(Copy, Clone, Debug)] struct CallSite<'tcx> { callee: Instance<'tcx>, - bb: BasicBlock, + block: BasicBlock, + target: Option<BasicBlock>, source_info: SourceInfo, } impl<'tcx> MirPass<'tcx> for Inline { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { - if tcx.sess.opts.debugging_opts.instrument_coverage { - // The current implementation of source code coverage injects code region counters - // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code- - // based function. - debug!("function inlining is disabled when compiling with `instrument_coverage`"); - } else { - Inliner { - tcx, - param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), - codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()), - } - .run_pass(body); - } + if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { + return; } + + if tcx.sess.opts.debugging_opts.instrument_coverage { + // The current implementation of source code coverage injects code region counters + // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code- + // based function. + debug!("function inlining is disabled when compiling with `instrument_coverage`"); + return; + } + + if inline(tcx, body) { + debug!("running simplify cfg on {:?}", body.source); + CfgSimplifier::new(body).simplify(); + remove_dead_blocks(body); + } + } +} + +fn inline(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { + let def_id = body.source.def_id(); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + + // Only do inlining into fn bodies. + if !tcx.hir().body_owner_kind(hir_id).is_fn_or_closure() { + return false; } + if body.source.promoted.is_some() { + return false; + } + + let mut this = Inliner { + tcx, + param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), + codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()), + hir_id, + history: Vec::new(), + changed: false, + }; + let blocks = BasicBlock::new(0)..body.basic_blocks().next_index(); + this.process_blocks(body, blocks); + this.changed } struct Inliner<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, + /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, + /// Caller HirID. + hir_id: hir::HirId, + /// Stack of inlined instances. + history: Vec<Instance<'tcx>>, + /// Indicates that the caller body has been modified. + changed: bool, } impl Inliner<'tcx> { - fn run_pass(&self, caller_body: &mut Body<'tcx>) { - // Keep a queue of callsites to try inlining on. We take - // advantage of the fact that queries detect cycles here to - // allow us to try and fetch the fully optimized MIR of a - // call; if it succeeds, we can inline it and we know that - // they do not call us. Otherwise, we just don't try to - // inline. - // - // We use a queue so that we inline "broadly" before we inline - // in depth. It is unclear if this is the best heuristic, - // really, but that's true of all the heuristics in this - // file. =) - - let mut callsites = VecDeque::new(); - - let def_id = caller_body.source.def_id(); - - // Only do inlining into fn bodies. - let self_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - if self.tcx.hir().body_owner_kind(self_hir_id).is_fn_or_closure() - && caller_body.source.promoted.is_none() - { - for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() { - if let Some(callsite) = self.get_valid_function_call(bb, bb_data, caller_body) { - callsites.push_back(callsite); - } + fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range<BasicBlock>) { + for bb in blocks { + let callsite = match self.get_valid_function_call(bb, &caller_body[bb], caller_body) { + None => continue, + Some(it) => it, + }; + + if !self.is_mir_available(&callsite.callee, caller_body) { + debug!("MIR unavailable {}", callsite.callee); + continue; } - } else { - return; - } - let mut changed = false; - while let Some(callsite) = callsites.pop_front() { - debug!("checking whether to inline callsite {:?}", callsite); + let callee_body = self.tcx.instance_mir(callsite.callee.def); + if !self.should_inline(callsite, callee_body) { + continue; + } - if let InstanceDef::Item(_) = callsite.callee.def { - if !self.tcx.is_mir_available(callsite.callee.def_id()) { - debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite,); - continue; - } + if !self.tcx.consider_optimizing(|| { + format!("Inline {:?} into {}", callee_body.span, callsite.callee) + }) { + return; } - let callee_body = if let Some(callee_def_id) = callsite.callee.def_id().as_local() { - let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id); - // Avoid a cycle here by only using `instance_mir` only if we have - // a lower `HirId` than the callee. This ensures that the callee will - // not inline us. This trick only works without incremental compilation. - // So don't do it if that is enabled. Also avoid inlining into generators, - // since their `optimized_mir` is used for layout computation, which can - // create a cycle, even when no attempt is made to inline the function - // in the other direction. - if !self.tcx.dep_graph.is_fully_enabled() - && self_hir_id < callee_hir_id - && caller_body.generator_kind.is_none() - { - self.tcx.instance_mir(callsite.callee.def) - } else { - continue; - } - } else { - // This cannot result in a cycle since the callee MIR is from another crate - // and is already optimized. - self.tcx.instance_mir(callsite.callee.def) - }; + let callee_body = callsite.callee.subst_mir_and_normalize_erasing_regions( + self.tcx, + self.param_env, + callee_body, + ); - let callee_body: &Body<'tcx> = &*callee_body; + let old_blocks = caller_body.basic_blocks().next_index(); + self.inline_call(callsite, caller_body, callee_body); + let new_blocks = old_blocks..caller_body.basic_blocks().next_index(); + self.changed = true; - let callee_body = if self.consider_optimizing(callsite, callee_body) { - self.tcx.subst_and_normalize_erasing_regions( - &callsite.callee.substs, - self.param_env, - callee_body, - ) - } else { - continue; - }; + self.history.push(callsite.callee); + self.process_blocks(caller_body, new_blocks); + self.history.pop(); + } + } - let start = caller_body.basic_blocks().len(); - debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body); - if !self.inline_call(callsite, caller_body, callee_body) { - debug!("attempting to inline callsite {:?} - failure", callsite); - continue; - } - debug!("attempting to inline callsite {:?} - success", callsite); - - // Add callsites from inlined function - for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) { - if let Some(new_callsite) = self.get_valid_function_call(bb, bb_data, caller_body) { - // Don't inline the same function multiple times. - if callsite.callee != new_callsite.callee { - callsites.push_back(new_callsite); - } - } + fn is_mir_available(&self, callee: &Instance<'tcx>, caller_body: &Body<'tcx>) -> bool { + if let InstanceDef::Item(_) = callee.def { + if !self.tcx.is_mir_available(callee.def_id()) { + return false; } - - changed = true; } - // Simplify if we inlined anything. - if changed { - debug!("running simplify cfg on {:?}", caller_body.source); - CfgSimplifier::new(caller_body).simplify(); - remove_dead_blocks(caller_body); + if let Some(callee_def_id) = callee.def_id().as_local() { + let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id); + // Avoid a cycle here by only using `instance_mir` only if we have + // a lower `HirId` than the callee. This ensures that the callee will + // not inline us. This trick only works without incremental compilation. + // So don't do it if that is enabled. Also avoid inlining into generators, + // since their `optimized_mir` is used for layout computation, which can + // create a cycle, even when no attempt is made to inline the function + // in the other direction. + !self.tcx.dep_graph.is_fully_enabled() + && self.hir_id < callee_hir_id + && caller_body.generator_kind.is_none() + } else { + // This cannot result in a cycle since the callee MIR is from another crate + // and is already optimized. + true } } @@ -182,7 +173,7 @@ impl Inliner<'tcx> { // Only consider direct calls to functions let terminator = bb_data.terminator(); - if let TerminatorKind::Call { func: ref op, .. } = terminator.kind { + if let TerminatorKind::Call { func: ref op, ref destination, .. } = terminator.kind { if let ty::FnDef(callee_def_id, substs) = *op.ty(caller_body, self.tcx).kind() { // To resolve an instance its substs have to be fully normalized, so // we do this here. @@ -196,21 +187,18 @@ impl Inliner<'tcx> { return None; } - return Some(CallSite { callee, bb, source_info: terminator.source_info }); + return Some(CallSite { + callee, + block: bb, + target: destination.map(|(_, target)| target), + source_info: terminator.source_info, + }); } } None } - fn consider_optimizing(&self, callsite: CallSite<'tcx>, callee_body: &Body<'tcx>) -> bool { - debug!("consider_optimizing({:?})", callsite); - self.should_inline(callsite, callee_body) - && self.tcx.consider_optimizing(|| { - format!("Inline {:?} into {:?}", callee_body.span, callsite) - }) - } - fn should_inline(&self, callsite: CallSite<'tcx>, callee_body: &Body<'tcx>) -> bool { debug!("should_inline({:?})", callsite); let tcx = self.tcx; @@ -262,7 +250,11 @@ impl Inliner<'tcx> { } } - let mut threshold = if hinted { HINT_THRESHOLD } else { DEFAULT_THRESHOLD }; + let mut threshold = if hinted { + self.tcx.sess.opts.debugging_opts.inline_mir_hint_threshold + } else { + self.tcx.sess.opts.debugging_opts.inline_mir_threshold + }; // Significantly lower the threshold for inlining cold functions if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { @@ -309,7 +301,7 @@ impl Inliner<'tcx> { work_list.push(target); // If the place doesn't actually need dropping, treat it like // a regular goto. - let ty = place.ty(callee_body, tcx).subst(tcx, callsite.callee.substs).ty; + let ty = callsite.callee.subst_mir(self.tcx, &place.ty(callee_body, tcx).ty); if ty.needs_drop(tcx, self.param_env) { cost += CALL_PENALTY; if let Some(unwind) = unwind { @@ -330,7 +322,18 @@ impl Inliner<'tcx> { } TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => { - if let ty::FnDef(def_id, _) = *f.literal.ty.kind() { + if let ty::FnDef(def_id, substs) = + *callsite.callee.subst_mir(self.tcx, &f.literal.ty).kind() + { + let substs = self.tcx.normalize_erasing_regions(self.param_env, substs); + if let Ok(Some(instance)) = + Instance::resolve(self.tcx, self.param_env, def_id, substs) + { + if callsite.callee == instance || self.history.contains(&instance) { + debug!("`callee is recursive - not inlining"); + return false; + } + } // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { @@ -371,8 +374,7 @@ impl Inliner<'tcx> { let ptr_size = tcx.data_layout.pointer_size.bytes(); for v in callee_body.vars_and_temps_iter() { - let v = &callee_body.local_decls[v]; - let ty = v.ty.subst(tcx, callsite.callee.substs); + let ty = callsite.callee.subst_mir(self.tcx, &callee_body.local_decls[v].ty); // Cost of the var is the size in machine-words, if we know // it. if let Some(size) = type_size_of(tcx, self.param_env, ty) { @@ -401,13 +403,10 @@ impl Inliner<'tcx> { callsite: CallSite<'tcx>, caller_body: &mut Body<'tcx>, mut callee_body: Body<'tcx>, - ) -> bool { - let terminator = caller_body[callsite.bb].terminator.take().unwrap(); + ) { + let terminator = caller_body[callsite.block].terminator.take().unwrap(); match terminator.kind { - // FIXME: Handle inlining of diverging calls - TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { - debug!("inlined {:?} into {:?}", callsite.callee, caller_body.source); - + TerminatorKind::Call { args, destination, cleanup, .. } => { // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` // Place could result in two different locations if `f` @@ -424,35 +423,31 @@ impl Inliner<'tcx> { false } - let dest = if dest_needs_borrow(destination.0) { - trace!("creating temp for return destination"); - let dest = Rvalue::Ref( - self.tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - destination.0, - ); - - let ty = dest.ty(caller_body, self.tcx); - - let temp = LocalDecl::new(ty, callsite.source_info.span); - - let tmp = caller_body.local_decls.push(temp); - let tmp = Place::from(tmp); - - let stmt = Statement { - source_info: callsite.source_info, - kind: StatementKind::Assign(box (tmp, dest)), - }; - caller_body[callsite.bb].statements.push(stmt); - self.tcx.mk_place_deref(tmp) + let dest = if let Some((destination_place, _)) = destination { + if dest_needs_borrow(destination_place) { + trace!("creating temp for return destination"); + let dest = Rvalue::Ref( + self.tcx.lifetimes.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + destination_place, + ); + let dest_ty = dest.ty(caller_body, self.tcx); + let temp = Place::from(self.new_call_temp(caller_body, &callsite, dest_ty)); + caller_body[callsite.block].statements.push(Statement { + source_info: callsite.source_info, + kind: StatementKind::Assign(box (temp, dest)), + }); + self.tcx.mk_place_deref(temp) + } else { + destination_place + } } else { - destination.0 + trace!("creating temp for return place"); + Place::from(self.new_call_temp(caller_body, &callsite, callee_body.return_ty())) }; - let return_block = destination.1; - // Copy the arguments if needed. - let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, return_block); + let args: Vec<_> = self.make_call_args(args, &callsite, caller_body); let mut integrator = Integrator { args: &args, @@ -460,7 +455,7 @@ impl Inliner<'tcx> { new_scopes: SourceScope::new(caller_body.source_scopes.len()).., new_blocks: BasicBlock::new(caller_body.basic_blocks().len()).., destination: dest, - return_block, + return_block: callsite.target, cleanup_block: cleanup, in_cleanup_block: false, tcx: self.tcx, @@ -509,7 +504,7 @@ impl Inliner<'tcx> { caller_body.var_debug_info.extend(callee_body.var_debug_info.drain(..)); caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..)); - caller_body[callsite.bb].terminator = Some(Terminator { + caller_body[callsite.block].terminator = Some(Terminator { source_info: callsite.source_info, kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) }, }); @@ -523,14 +518,8 @@ impl Inliner<'tcx> { matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _)) }), ); - - true - } - kind => { - caller_body[callsite.bb].terminator = - Some(Terminator { source_info: terminator.source_info, kind }); - false } + kind => bug!("unexpected terminator kind {:?}", kind), } } @@ -539,7 +528,6 @@ impl Inliner<'tcx> { args: Vec<Operand<'tcx>>, callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>, - return_block: BasicBlock, ) -> Vec<Local> { let tcx = self.tcx; @@ -570,18 +558,8 @@ impl Inliner<'tcx> { // `callee_body.spread_arg == None`, instead of special-casing closures. if tcx.is_closure(callsite.callee.def_id()) { let mut args = args.into_iter(); - let self_ = self.create_temp_if_necessary( - args.next().unwrap(), - callsite, - caller_body, - return_block, - ); - let tuple = self.create_temp_if_necessary( - args.next().unwrap(), - callsite, - caller_body, - return_block, - ); + let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); + let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); assert!(args.next().is_none()); let tuple = Place::from(tuple); @@ -601,13 +579,13 @@ impl Inliner<'tcx> { Operand::Move(tcx.mk_place_field(tuple, Field::new(i), ty.expect_ty())); // Spill to a local to make e.g., `tmp0`. - self.create_temp_if_necessary(tuple_field, callsite, caller_body, return_block) + self.create_temp_if_necessary(tuple_field, callsite, caller_body) }); closure_ref_arg.chain(tuple_tmp_args).collect() } else { args.into_iter() - .map(|a| self.create_temp_if_necessary(a, callsite, caller_body, return_block)) + .map(|a| self.create_temp_if_necessary(a, callsite, caller_body)) .collect() } } @@ -619,46 +597,52 @@ impl Inliner<'tcx> { arg: Operand<'tcx>, callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>, - return_block: BasicBlock, ) -> Local { - // FIXME: Analysis of the usage of the arguments to avoid - // unnecessary temporaries. - + // Reuse the operand if it is a moved temporary. if let Operand::Move(place) = &arg { if let Some(local) = place.as_local() { if caller_body.local_kind(local) == LocalKind::Temp { - // Reuse the operand if it's a temporary already return local; } } } + // Otherwise, create a temporary for the argument. trace!("creating temp for argument {:?}", arg); - // Otherwise, create a temporary for the arg - let arg = Rvalue::Use(arg); - - let ty = arg.ty(caller_body, self.tcx); - - let arg_tmp = LocalDecl::new(ty, callsite.source_info.span); - let arg_tmp = caller_body.local_decls.push(arg_tmp); - - caller_body[callsite.bb].statements.push(Statement { + let arg_ty = arg.ty(caller_body, self.tcx); + let local = self.new_call_temp(caller_body, callsite, arg_ty); + caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, - kind: StatementKind::StorageLive(arg_tmp), + kind: StatementKind::Assign(box (Place::from(local), Rvalue::Use(arg))), }); - caller_body[callsite.bb].statements.push(Statement { + local + } + + /// Introduces a new temporary into the caller body that is live for the duration of the call. + fn new_call_temp( + &self, + caller_body: &mut Body<'tcx>, + callsite: &CallSite<'tcx>, + ty: Ty<'tcx>, + ) -> Local { + let local = caller_body.local_decls.push(LocalDecl::new(ty, callsite.source_info.span)); + + caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, - kind: StatementKind::Assign(box (Place::from(arg_tmp), arg)), + kind: StatementKind::StorageLive(local), }); - caller_body[return_block].statements.insert( - 0, - Statement { - source_info: callsite.source_info, - kind: StatementKind::StorageDead(arg_tmp), - }, - ); - - arg_tmp + + if let Some(block) = callsite.target { + caller_body[block].statements.insert( + 0, + Statement { + source_info: callsite.source_info, + kind: StatementKind::StorageDead(local), + }, + ); + } + + local } } @@ -683,7 +667,7 @@ struct Integrator<'a, 'tcx> { new_scopes: RangeFrom<SourceScope>, new_blocks: RangeFrom<BasicBlock>, destination: Place<'tcx>, - return_block: BasicBlock, + return_block: Option<BasicBlock>, cleanup_block: Option<BasicBlock>, in_cleanup_block: bool, tcx: TyCtxt<'tcx>, @@ -742,6 +726,12 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { + for elem in place.projection { + // FIXME: Make sure that return place is not used in an indexing projection, since it + // won't be rebased as it is supposed to be. + assert_ne!(ProjectionElem::Index(RETURN_PLACE), elem); + } + // If this is the `RETURN_PLACE`, we need to rebase any projections onto it. let dest_proj_len = self.destination.projection.len(); if place.local == RETURN_PLACE && dest_proj_len > 0 { @@ -823,7 +813,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { } } TerminatorKind::Return => { - terminator.kind = TerminatorKind::Goto { target: self.return_block }; + terminator.kind = if let Some(tgt) = self.return_block { + TerminatorKind::Goto { target: tgt } + } else { + TerminatorKind::Unreachable + } } TerminatorKind::Resume => { if let Some(tgt) = self.cleanup_block { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 205ad850c0c..14ed93f1127 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -69,6 +69,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None), hir::LocalSource::AsyncFn => ("async fn binding", None), hir::LocalSource::AwaitDesugar => ("`await` future binding", None), + hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None), }; self.check_irrefutable(&loc.pat, msg, sp); self.check_patterns(&loc.pat); diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 196790a0ab3..ee9a6dca5ad 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,6 +1,6 @@ use super::{Parser, PathStyle}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; -use rustc_ast::mut_visit::{noop_visit_mac, noop_visit_pat, MutVisitor}; +use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::{self as ast, AttrVec, Attribute, FieldPat, MacCall, Pat, PatKind, RangeEnd}; @@ -570,10 +570,6 @@ impl<'a> Parser<'a> { fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool { struct AddMut(bool); impl MutVisitor for AddMut { - fn visit_mac(&mut self, mac: &mut MacCall) { - noop_visit_mac(mac, self); - } - fn visit_pat(&mut self, pat: &mut P<Pat>) { if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind { diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 9537321026e..1d02c9aa637 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -336,8 +336,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_lifetime(self, lifetime) } - fn visit_mac(&mut self, mac: &'v ast::MacCall) { + fn visit_mac_call(&mut self, mac: &'v ast::MacCall) { self.record("MacCall", Id::None, mac); + ast_visit::walk_mac(self, mac) } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) { diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 8650ee05d37..4273d600004 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -26,7 +26,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem if items.eh_personality().is_none() { items.missing.push(LangItem::EhPersonality); } - if tcx.sess.target.options.is_like_emscripten && items.eh_catch_typeinfo().is_none() { + if tcx.sess.target.is_like_emscripten && items.eh_catch_typeinfo().is_none() { items.missing.push(LangItem::EhCatchTypeinfo); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index b632bfbed30..87687339370 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -735,15 +735,15 @@ pub const fn default_lib_output() -> CrateType { } pub fn default_configuration(sess: &Session) -> CrateConfig { - let end = &sess.target.target_endian; + let end = &sess.target.endian; let arch = &sess.target.arch; let wordsz = sess.target.pointer_width.to_string(); - let os = &sess.target.target_os; - let env = &sess.target.target_env; - let vendor = &sess.target.target_vendor; + let os = &sess.target.os; + let env = &sess.target.env; + let vendor = &sess.target.vendor; let min_atomic_width = sess.target.min_atomic_width(); let max_atomic_width = sess.target.max_atomic_width(); - let atomic_cas = sess.target.options.atomic_cas; + let atomic_cas = sess.target.atomic_cas; let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| { sess.fatal(&err); }); @@ -752,7 +752,7 @@ pub fn default_configuration(sess: &Session) -> CrateConfig { ret.reserve(6); // the minimum number of insertions // Target bindings. ret.insert((sym::target_os, Some(Symbol::intern(os)))); - if let Some(ref fam) = sess.target.options.target_family { + if let Some(ref fam) = sess.target.os_family { ret.insert((sym::target_family, Some(Symbol::intern(fam)))); if fam == "windows" { ret.insert((sym::windows, None)); @@ -765,7 +765,7 @@ pub fn default_configuration(sess: &Session) -> CrateConfig { ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz)))); ret.insert((sym::target_env, Some(Symbol::intern(env)))); ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); - if sess.target.options.has_elf_tls { + if sess.target.has_elf_tls { ret.insert((sym::target_thread_local, None)); } for &(i, align) in &[ @@ -793,6 +793,9 @@ pub fn default_configuration(sess: &Session) -> CrateConfig { } } + let panic_strategy = sess.panic_strategy(); + ret.insert((sym::panic, Some(panic_strategy.desc_symbol()))); + for s in sess.opts.debugging_opts.sanitizer { let symbol = Symbol::intern(&s.to_string()); ret.insert((sym::sanitize, Some(symbol))); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index ceed730e25b..1cd3d11e321 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -929,6 +929,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (default: no)"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], "verify incr. comp. hashes of green query instances (default: no)"), + inline_mir_threshold: usize = (50, parse_uint, [TRACKED], + "a default MIR inlining threshold (default: 50)"), + inline_mir_hint_threshold: usize = (100, parse_uint, [TRACKED], + "inlining threshold for functions with inline hint (default: 100)"), inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED], "control whether `#[inline]` functions are in all CGUs"), input_stats: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 130c3a06122..777eea3f68d 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -150,17 +150,15 @@ pub fn filename_for_input( match crate_type { CrateType::Rlib => outputs.out_directory.join(&format!("lib{}.rlib", libname)), CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib => { - let (prefix, suffix) = - (&sess.target.options.dll_prefix, &sess.target.options.dll_suffix); + let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix); outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix)) } CrateType::Staticlib => { - let (prefix, suffix) = - (&sess.target.options.staticlib_prefix, &sess.target.options.staticlib_suffix); + let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix); outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix)) } CrateType::Executable => { - let suffix = &sess.target.options.exe_suffix; + let suffix = &sess.target.exe_suffix; let out_filename = outputs.path(OutputType::Exe); if suffix.is_empty() { out_filename } else { out_filename.with_extension(&suffix[1..]) } } @@ -177,29 +175,29 @@ pub fn filename_for_input( /// interaction with Rust code through static library is the only /// option for now pub fn default_output_for_target(sess: &Session) -> CrateType { - if !sess.target.options.executables { CrateType::Staticlib } else { CrateType::Executable } + if !sess.target.executables { CrateType::Staticlib } else { CrateType::Executable } } /// Checks if target supports crate_type as output pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool { match crate_type { CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro => { - if !sess.target.options.dynamic_linking { + if !sess.target.dynamic_linking { return true; } - if sess.crt_static(Some(crate_type)) && !sess.target.options.crt_static_allows_dylibs { + if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs { return true; } } _ => {} } - if sess.target.options.only_cdylib { + if sess.target.only_cdylib { match crate_type { CrateType::ProcMacro | CrateType::Dylib => return true, _ => {} } } - if !sess.target.options.executables && crate_type == CrateType::Executable { + if !sess.target.executables && crate_type == CrateType::Executable { return true; } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 0b7c35a8afd..98b7f03df38 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -663,7 +663,7 @@ impl Session { /// Calculates the flavor of LTO to use for this compilation. pub fn lto(&self) -> config::Lto { // If our target has codegen requirements ignore the command line - if self.target.options.requires_lto { + if self.target.requires_lto { return config::Lto::Fat; } @@ -731,7 +731,7 @@ impl Session { /// Returns the panic strategy for this compile session. If the user explicitly selected one /// using '-C panic', use that, otherwise use the panic strategy defined by the target. pub fn panic_strategy(&self) -> PanicStrategy { - self.opts.cg.panic.unwrap_or(self.target.options.panic_strategy) + self.opts.cg.panic.unwrap_or(self.target.panic_strategy) } pub fn fewer_names(&self) -> bool { let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) @@ -755,9 +755,9 @@ impl Session { /// Check whether this compile session and crate type use static crt. pub fn crt_static(&self, crate_type: Option<CrateType>) -> bool { - if !self.target.options.crt_static_respected { + if !self.target.crt_static_respected { // If the target does not opt in to crt-static support, use its default. - return self.target.options.crt_static_default; + return self.target.crt_static_default; } let requested_features = self.opts.cg.target_feature.split(','); @@ -774,20 +774,20 @@ impl Session { // We can't check `#![crate_type = "proc-macro"]` here. false } else { - self.target.options.crt_static_default + self.target.crt_static_default } } pub fn relocation_model(&self) -> RelocModel { - self.opts.cg.relocation_model.unwrap_or(self.target.options.relocation_model) + self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model) } pub fn code_model(&self) -> Option<CodeModel> { - self.opts.cg.code_model.or(self.target.options.code_model) + self.opts.cg.code_model.or(self.target.code_model) } pub fn tls_model(&self) -> TlsModel { - self.opts.debugging_opts.tls_model.unwrap_or(self.target.options.tls_model) + self.opts.debugging_opts.tls_model.unwrap_or(self.target.tls_model) } pub fn must_not_eliminate_frame_pointers(&self) -> bool { @@ -798,7 +798,7 @@ impl Session { } else if let Some(x) = self.opts.cg.force_frame_pointers { x } else { - !self.target.options.eliminate_frame_pointer + !self.target.eliminate_frame_pointer } } @@ -822,7 +822,7 @@ impl Session { // value, if it is provided, or disable them, if not. if self.panic_strategy() == PanicStrategy::Unwind { true - } else if self.target.options.requires_uwtable { + } else if self.target.requires_uwtable { true } else { self.opts.cg.force_unwind_tables.unwrap_or(false) @@ -993,7 +993,7 @@ impl Session { if let Some(n) = self.opts.cli_forced_codegen_units { return n; } - if let Some(n) = self.target.options.default_codegen_units { + if let Some(n) = self.target.default_codegen_units { return n as usize; } @@ -1078,11 +1078,11 @@ impl Session { pub fn needs_plt(&self) -> bool { // Check if the current target usually needs PLT to be enabled. // The user can use the command line flag to override it. - let needs_plt = self.target.options.needs_plt; + let needs_plt = self.target.needs_plt; let dbg_opts = &self.opts.debugging_opts; - let relro_level = dbg_opts.relro_level.unwrap_or(self.target.options.relro_level); + let relro_level = dbg_opts.relro_level.unwrap_or(self.target.relro_level); // Only enable this optimization by default if full relro is also enabled. // In this case, lazy binding was already unavailable, so nothing is lost. @@ -1106,7 +1106,7 @@ impl Session { match self.opts.cg.link_dead_code { Some(explicitly_set) => explicitly_set, None => { - self.opts.debugging_opts.instrument_coverage && !self.target.options.is_like_msvc + self.opts.debugging_opts.instrument_coverage && !self.target.is_like_msvc // Issue #76038: (rustc `-Clink-dead-code` causes MSVC linker to produce invalid // binaries when LLVM InstrProf counters are enabled). As described by this issue, // the "link dead code" option produces incorrect binaries when compiled and linked @@ -1305,9 +1305,9 @@ pub fn build_session( early_error(sopts.error_format, &format!("Error loading host specification: {}", e)) }); - let loader = file_loader.unwrap_or(Box::new(RealFileLoader)); + let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); let hash_kind = sopts.debugging_opts.src_hash_algorithm.unwrap_or_else(|| { - if target_cfg.options.is_like_msvc { + if target_cfg.is_like_msvc { SourceFileHashAlgorithm::Sha1 } else { SourceFileHashAlgorithm::Md5 @@ -1417,11 +1417,8 @@ pub fn build_session( if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None } }; - let asm_arch = if target_cfg.options.allow_asm { - InlineAsmArch::from_str(&target_cfg.arch).ok() - } else { - None - }; + let asm_arch = + if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None }; let sess = Session { target: target_cfg, @@ -1487,7 +1484,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // the `dllimport` attributes and `__imp_` symbols in that case. if sess.opts.cg.linker_plugin_lto.enabled() && sess.opts.cg.prefer_dynamic - && sess.target.options.is_like_windows + && sess.target.is_like_windows { sess.err( "Linker plugin based LTO is not supported together with \ @@ -1515,7 +1512,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { ); } - if sess.target.options.requires_uwtable && !include_uwtables { + if sess.target.requires_uwtable && !include_uwtables { sess.err( "target requires unwind tables, they cannot be disabled with \ `-C force-unwind-tables=no`.", @@ -1530,7 +1527,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // We should only display this error if we're actually going to run PGO. // If we're just supposed to print out some data, don't show the error (#61002). if sess.opts.cg.profile_generate.enabled() - && sess.target.options.is_like_msvc + && sess.target.is_like_msvc && sess.panic_strategy() == PanicStrategy::Unwind && sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1a6c45b6c80..ad58f89d87d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -326,6 +326,7 @@ symbols! { cfg_attr, cfg_attr_multi, cfg_doctest, + cfg_panic, cfg_sanitize, cfg_target_feature, cfg_target_has_atomic, @@ -434,6 +435,7 @@ symbols! { deref_mut, deref_target, derive, + destructuring_assignment, diagnostic, direct, discriminant_kind, diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 507ae10877b..429a3375cd8 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -562,7 +562,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "x86_64" => { if abi == spec::abi::Abi::SysV64 { x86_64::compute_abi_info(cx, self); - } else if abi == spec::abi::Abi::Win64 || cx.target_spec().options.is_like_windows { + } else if abi == spec::abi::Abi::Win64 || cx.target_spec().is_like_windows { x86_win64::compute_abi_info(self); } else { x86_64::compute_abi_info(cx, self); @@ -584,7 +584,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), - "wasm32" if cx.target_spec().target_os != "emscripten" => { + "wasm32" if cx.target_spec().os != "emscripten" => { wasm32_bindgen_compat::compute_abi_info(self) } "wasm32" | "asmjs" => wasm32::compute_abi_info(cx, self), diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs index b740707320f..8c2a9d09a3d 100644 --- a/compiler/rustc_target/src/abi/call/powerpc64.rs +++ b/compiler/rustc_target/src/abi/call/powerpc64.rs @@ -119,7 +119,7 @@ where Ty: TyAndLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, { - let abi = if cx.target_spec().target_env == "musl" { + let abi = if cx.target_spec().env == "musl" { ELFv2 } else { match cx.data_layout().endian { diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index 47530eeacd0..782c661c31f 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -323,7 +323,7 @@ where Ty: TyAndLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, { - let flen = match &cx.target_spec().options.llvm_abiname[..] { + let flen = match &cx.target_spec().llvm_abiname[..] { "ilp32f" | "lp64f" => 32, "ilp32d" | "lp64d" => 64, _ => 0, diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index df3dd5d9208..07bf1e94c61 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -41,10 +41,10 @@ where // http://www.angelcode.com/dev/callconv/callconv.html // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp let t = cx.target_spec(); - if t.options.abi_return_struct_as_int { + if t.abi_return_struct_as_int { // According to Clang, everyone but MSVC returns single-element // float aggregates directly in a floating-point register. - if !t.options.is_like_msvc && is_single_fp_element(cx, fn_abi.ret.layout) { + if !t.is_like_msvc && is_single_fp_element(cx, fn_abi.ret.layout) { match fn_abi.ret.layout.size.bytes() { 4 => fn_abi.ret.cast_to(Reg::f32()), 8 => fn_abi.ret.cast_to(Reg::f64()), diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index d3c31773c1e..a43080b09e9 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -156,11 +156,11 @@ impl TargetDataLayout { Endian::Little => "little", Endian::Big => "big", }; - if endian_str != target.target_endian { + if endian_str != target.endian { return Err(format!( "inconsistent target specification: \"data-layout\" claims \ architecture is {}-endian, while \"target-endian\" is `{}`", - endian_str, target.target_endian + endian_str, target.endian )); } diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 85a136b94aa..28000916e0c 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -61,7 +61,7 @@ impl ArmInlineAsmRegClass { // This uses the same logic as useR7AsFramePointer in LLVM fn frame_pointer_is_r7(mut has_feature: impl FnMut(&str) -> bool, target: &Target) -> bool { - target.options.is_like_osx || (!target.options.is_like_windows && has_feature("thumb-mode")) + target.is_like_osx || (!target.is_like_windows && has_feature("thumb-mode")) } fn frame_pointer_r11( diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 098651614d0..7de809f7622 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -19,6 +19,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), arch: arch.to_string(), - options: TargetOptions { target_mcount: "\u{1}mcount".to_string(), ..base }, + options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs index 9d9698a440d..58c72af4e76 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.max_atomic_width = Some(128); Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}_mcount".to_string(), + mcount: "\u{1}_mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs index 2dd703b66ff..7bbfc8ec0f7 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}_mcount".to_string(), + mcount: "\u{1}_mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs index 81e383ca5f1..09efbdbb293 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs @@ -10,6 +10,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { target_mcount: "__mcount".to_string(), ..base }, + options: TargetOptions { mcount: "__mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs index 1088807f2c2..d0ad45153d6 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs @@ -10,7 +10,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp pub fn target() -> Target { let opts = TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), features: "+strict-align,+neon,+fp-armv8".to_string(), diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs index 044c9fa1de8..41bd2182905 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs @@ -10,7 +10,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp pub fn target() -> Target { let opts = TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), features: "+strict-align,-neon,-fp-armv8".to_string(), diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index 1bd5eb6988c..f6fbe7cd5f6 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -1,15 +1,14 @@ use crate::spec::{LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_base::opts(); - base.target_os = "android".to_string(); + let mut base = super::linux_gnu_base::opts(); + base.os = "android".to_string(); // Many of the symbols defined in compiler-rt are also defined in libgcc. // Android's linker doesn't like that by default. base.pre_link_args .get_mut(&LinkerFlavor::Gcc) .unwrap() .push("-Wl,--allow-multiple-definition".to_string()); - base.is_like_android = true; base.dwarf_version = Some(2); base.position_independent_executables = true; base.has_elf_tls = false; diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 045d9967f30..e271a6dec40 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -17,13 +17,13 @@ pub fn opts(os: &str) -> TargetOptions { let version = macos_deployment_target(); TargetOptions { - target_os: os.to_string(), - target_vendor: "apple".to_string(), + os: os.to_string(), + vendor: "apple".to_string(), // macOS has -dead_strip, which doesn't rely on function_sections function_sections: false, dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), is_like_osx: true, dwarf_version: Some(2), has_rpath: true, diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs index dca0b1ec2e4..c41cf6e521a 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs @@ -1,7 +1,7 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.max_atomic_width = Some(64); Target { llvm_target: "arm-unknown-linux-gnueabi".to_string(), @@ -12,7 +12,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+strict-align,+v6".to_string(), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs index ee71ae61972..f2143966c1d 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs @@ -1,7 +1,7 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.max_atomic_width = Some(64); Target { llvm_target: "arm-unknown-linux-gnueabihf".to_string(), @@ -12,7 +12,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+strict-align,+v6,+vfp2,-d32".to_string(), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs index 6938a043602..53ff1001c20 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}mcount".to_string(), + mcount: "\u{1}mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs index 4adf3a33893..6d8a5f9f88b 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}mcount".to_string(), + mcount: "\u{1}mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs index 7bfa5baecb5..36856305723 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_endian: "big".to_string(), - target_vendor: String::new(), + endian: "big".to_string(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs index 7afc933a28f..2ff3c8950c4 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_endian: "big".to_string(), - target_vendor: String::new(), + endian: "big".to_string(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs index c58fa7407b4..e1ba72bf83b 100644 --- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs @@ -1,7 +1,7 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::linux_base::opts(); + let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv4t-unknown-linux-gnueabi".to_string(), pointer_width: 32, @@ -13,7 +13,7 @@ pub fn target() -> Target { // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), has_thumb_interworking: true, ..base }, diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs index 049a031398a..3ac8d53564d 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs @@ -1,7 +1,7 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::linux_base::opts(); + let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv5te-unknown-linux-gnueabi".to_string(), pointer_width: 32, @@ -13,7 +13,7 @@ pub fn target() -> Target { // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), has_thumb_interworking: true, ..base }, diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs index 77cf8bb76d3..40d405c30a2 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs @@ -16,7 +16,7 @@ pub fn target() -> Target { // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}mcount".to_string(), + mcount: "\u{1}mcount".to_string(), has_thumb_interworking: true, ..base }, diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs index 981d615f684..a149bd983b7 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs @@ -9,11 +9,11 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_env: "gnueabihf".to_string(), + env: "gnueabihf".to_string(), features: "+v6,+vfp2,-d32".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs index 8417a8f2801..6c81a458b9b 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs @@ -10,10 +10,10 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_env: "eabihf".to_string(), + env: "eabihf".to_string(), features: "+v6,+vfp2,-d32".to_string(), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "__mcount".to_string(), + mcount: "__mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_cloudabi_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_cloudabi_eabihf.rs index 921640d0aa6..d47ee541b25 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_cloudabi_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_cloudabi_eabihf.rs @@ -13,6 +13,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { target_mcount: "\u{1}mcount".to_string(), ..base }, + options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs index 88d5c86cfab..6f24c6818fc 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs @@ -9,11 +9,11 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_env: "gnueabihf".to_string(), + env: "gnueabihf".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs index 2a31bf4e332..ae6b8286f08 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs @@ -4,7 +4,7 @@ use crate::spec::{Target, TargetOptions}; // hardfloat. pub fn target() -> Target { - let base = super::linux_base::opts(); + let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabi".to_string(), pointer_width: 32, @@ -16,7 +16,7 @@ pub fn target() -> Target { cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs index d04400b79df..48c16b620fd 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs @@ -4,7 +4,7 @@ use crate::spec::{Target, TargetOptions}; // thumb-mode. See the thumbv7neon variant for enabling both. pub fn target() -> Target { - let base = super::linux_base::opts(); + let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".to_string(), pointer_width: 32, @@ -17,7 +17,7 @@ pub fn target() -> Target { cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + mcount: "\u{1}__gnu_mcount_nc".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs index ebbbd61fc11..9f9f1bd79b0 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs @@ -21,7 +21,7 @@ pub fn target() -> Target { cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}mcount".to_string(), + mcount: "\u{1}mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs index ee603aa0684..59deee30ef2 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs @@ -20,7 +20,7 @@ pub fn target() -> Target { cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}mcount".to_string(), + mcount: "\u{1}mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs index 09c531ebc8a..660525704c1 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs @@ -9,12 +9,12 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_env: "eabihf".to_string(), + env: "eabihf".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "__mcount".to_string(), + mcount: "__mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs index b6b34e27562..742b403cff9 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs @@ -10,8 +10,8 @@ // bare-metal binaries (the `gcc` linker has the advantage that it knows where C // libraries and crt*.o are but it's not much of an advantage here); LLD is also // faster -// - `target_os` set to `none`. rationale: matches `thumb` targets -// - `target_{env,vendor}` set to an empty string. rationale: matches `thumb` +// - `os` set to `none`. rationale: matches `thumb` targets +// - `env` and `vendor` are set to an empty string. rationale: matches `thumb` // targets // - `panic_strategy` set to `abort`. rationale: matches `thumb` targets // - `relocation-model` set to `static`; also no PIE, no relro and no dynamic @@ -21,7 +21,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp pub fn target() -> Target { let opts = TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs index 8b9df361844..b9cda18d6b4 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs @@ -9,7 +9,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp pub fn target() -> Target { let opts = TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs index fdd74d27619..440c2434907 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs index 7baafea90b9..c1bf332a72d 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs index 1c3f5c4f9e8..b1adefe1a51 100644 --- a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs @@ -3,7 +3,6 @@ use super::{wasm32_unknown_emscripten, LinkerFlavor, Target}; pub fn target() -> Target { let mut target = wasm32_unknown_emscripten::target(); target - .options .post_link_args .entry(LinkerFlavor::Em) .or_default() diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs index 268af87cfe9..9cc10032c71 100644 --- a/compiler/rustc_target/src/spec/avr_gnu_base.rs +++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs @@ -10,8 +10,8 @@ pub fn target(target_cpu: String) -> Target { llvm_target: "avr-unknown-unknown".to_string(), pointer_width: 16, options: TargetOptions { - target_c_int_width: "16".to_string(), - target_os: "unknown".to_string(), + c_int_width: "16".to_string(), + os: "unknown".to_string(), cpu: target_cpu.clone(), exe_suffix: ".elf".to_string(), diff --git a/compiler/rustc_target/src/spec/cloudabi_base.rs b/compiler/rustc_target/src/spec/cloudabi_base.rs index 0053adb8552..20a095742ec 100644 --- a/compiler/rustc_target/src/spec/cloudabi_base.rs +++ b/compiler/rustc_target/src/spec/cloudabi_base.rs @@ -12,9 +12,9 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "cloudabi".to_string(), + os: "cloudabi".to_string(), executables: true, - target_family: None, + os_family: None, linker_is_gnu: true, pre_link_args: args, position_independent_executables: true, diff --git a/compiler/rustc_target/src/spec/dragonfly_base.rs b/compiler/rustc_target/src/spec/dragonfly_base.rs index a182e37dd80..b96de7ab1ed 100644 --- a/compiler/rustc_target/src/spec/dragonfly_base.rs +++ b/compiler/rustc_target/src/spec/dragonfly_base.rs @@ -16,10 +16,10 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "dragonfly".to_string(), + os: "dragonfly".to_string(), dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: args, diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs index 25535117743..c70c492716b 100644 --- a/compiler/rustc_target/src/spec/freebsd_base.rs +++ b/compiler/rustc_target/src/spec/freebsd_base.rs @@ -16,10 +16,10 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "freebsd".to_string(), + os: "freebsd".to_string(), dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: args, diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs index 97998eed886..e467c7c8f21 100644 --- a/compiler/rustc_target/src/spec/fuchsia_base.rs +++ b/compiler/rustc_target/src/spec/fuchsia_base.rs @@ -20,14 +20,14 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "fuchsia".to_string(), - target_vendor: String::new(), + os: "fuchsia".to_string(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), lld_flavor: LldFlavor::Ld, dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), is_like_fuchsia: true, linker_is_gnu: true, has_rpath: false, diff --git a/compiler/rustc_target/src/spec/haiku_base.rs b/compiler/rustc_target/src/spec/haiku_base.rs index 3d9dd44e786..ec87645c4fa 100644 --- a/compiler/rustc_target/src/spec/haiku_base.rs +++ b/compiler/rustc_target/src/spec/haiku_base.rs @@ -2,11 +2,11 @@ use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { TargetOptions { - target_os: "haiku".to_string(), + os: "haiku".to_string(), dynamic_linking: true, executables: true, has_rpath: false, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), relro_level: RelroLevel::Full, linker_is_gnu: true, ..Default::default() diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs index 2953646afd0..a75158a0ea0 100644 --- a/compiler/rustc_target/src/spec/hermit_base.rs +++ b/compiler/rustc_target/src/spec/hermit_base.rs @@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "hermit".to_string(), + os: "hermit".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), executables: true, @@ -20,7 +20,7 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, static_position_independent_executables: true, relocation_model: RelocModel::Pic, - target_family: None, + os_family: None, tls_model: TlsModel::InitialExec, ..Default::default() } diff --git a/compiler/rustc_target/src/spec/hermit_kernel_base.rs b/compiler/rustc_target/src/spec/hermit_kernel_base.rs index 7d06cbd62f5..622f0d9a471 100644 --- a/compiler/rustc_target/src/spec/hermit_kernel_base.rs +++ b/compiler/rustc_target/src/spec/hermit_kernel_base.rs @@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "hermit".to_string(), + os: "hermit".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), disable_redzone: true, linker: Some("rust-lld".to_owned()), @@ -21,7 +21,7 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, static_position_independent_executables: true, relocation_model: RelocModel::Pic, - target_family: None, + os_family: None, tls_model: TlsModel::InitialExec, ..Default::default() } diff --git a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs index 664b9d5d515..4a7779a6df0 100644 --- a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs @@ -2,7 +2,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::i686_pc_windows_msvc::target(); - base.options.cpu = "pentium".to_string(); + base.cpu = "pentium".to_string(); base.llvm_target = "i586-pc-windows-msvc".to_string(); base } diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs index 3276f1d0094..7c92dda8a9d 100644 --- a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs @@ -2,7 +2,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::i686_unknown_linux_gnu::target(); - base.options.cpu = "pentium".to_string(); + base.cpu = "pentium".to_string(); base.llvm_target = "i586-unknown-linux-gnu".to_string(); base } diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs index 5fbf0487226..1fea02bbee8 100644 --- a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs @@ -2,7 +2,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::i686_unknown_linux_musl::target(); - base.options.cpu = "pentium".to_string(); + base.cpu = "pentium".to_string(); base.llvm_target = "i586-unknown-linux-musl".to_string(); base } diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index ac295aa3587..0ab40340928 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -22,6 +22,6 @@ pub fn target() -> Target { f64:32:64-f80:128-n8:16:32-S128" .to_string(), arch: "x86".to_string(), - options: TargetOptions { target_mcount: "\u{1}mcount".to_string(), ..base }, + options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs index 62b02d841c2..083c115d084 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs index 2568fabfb05..c22139b5875 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs @@ -14,6 +14,6 @@ pub fn target() -> Target { f64:32:64-f80:32-n8:16:32-S128" .to_string(), arch: "x86".to_string(), - options: TargetOptions { target_mcount: "__mcount".to_string(), ..base }, + options: TargetOptions { mcount: "__mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs index 625f7b18b25..d9b5716c041 100644 --- a/compiler/rustc_target/src/spec/illumos_base.rs +++ b/compiler/rustc_target/src/spec/illumos_base.rs @@ -16,11 +16,11 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "illumos".to_string(), + os: "illumos".to_string(), dynamic_linking: true, executables: true, has_rpath: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), is_like_solaris: true, limit_rdylib_exports: false, // Linker doesn't support this eliminate_frame_pointer: false, diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/l4re_base.rs index 6d1e610d0e9..660fae5f5c7 100644 --- a/compiler/rustc_target/src/spec/l4re_base.rs +++ b/compiler/rustc_target/src/spec/l4re_base.rs @@ -17,15 +17,15 @@ pub fn opts() -> TargetOptions { args.insert(LinkerFlavor::Gcc, vec![]); TargetOptions { - target_os: "l4re".to_string(), - target_env: "uclibc".to_string(), + os: "l4re".to_string(), + env: "uclibc".to_string(), linker_flavor: LinkerFlavor::Ld, executables: true, has_elf_tls: false, panic_strategy: PanicStrategy::Abort, linker: Some("ld".to_string()), pre_link_args: args, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/linux_base.rs index b3a850591fd..0631644ad63 100644 --- a/compiler/rustc_target/src/spec/linux_base.rs +++ b/compiler/rustc_target/src/spec/linux_base.rs @@ -19,11 +19,10 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "linux".to_string(), - target_env: "gnu".to_string(), + os: "linux".to_string(), dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: args, diff --git a/compiler/rustc_target/src/spec/linux_gnu_base.rs b/compiler/rustc_target/src/spec/linux_gnu_base.rs new file mode 100644 index 00000000000..3d940ceaf02 --- /dev/null +++ b/compiler/rustc_target/src/spec/linux_gnu_base.rs @@ -0,0 +1,5 @@ +use crate::spec::TargetOptions; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "gnu".to_string(), ..super::linux_base::opts() } +} diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs index 9c883f9a188..a5fc1649e7f 100644 --- a/compiler/rustc_target/src/spec/linux_kernel_base.rs +++ b/compiler/rustc_target/src/spec/linux_kernel_base.rs @@ -8,7 +8,7 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_env: "gnu".to_string(), + env: "gnu".to_string(), disable_redzone: true, panic_strategy: PanicStrategy::Abort, stack_probes: true, diff --git a/compiler/rustc_target/src/spec/linux_musl_base.rs b/compiler/rustc_target/src/spec/linux_musl_base.rs index 3a44d3326eb..5038a967d0a 100644 --- a/compiler/rustc_target/src/spec/linux_musl_base.rs +++ b/compiler/rustc_target/src/spec/linux_musl_base.rs @@ -4,7 +4,7 @@ use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { let mut base = super::linux_base::opts(); - base.target_env = "musl".to_string(); + base.env = "musl".to_string(); base.pre_link_objects_fallback = crt_objects::pre_musl_fallback(); base.post_link_objects_fallback = crt_objects::post_musl_fallback(); base.crt_objects_fallback = Some(CrtObjectsFallback::Musl); diff --git a/compiler/rustc_target/src/spec/linux_uclibc_base.rs b/compiler/rustc_target/src/spec/linux_uclibc_base.rs index ce7c79c1644..ef6d50656e4 100644 --- a/compiler/rustc_target/src/spec/linux_uclibc_base.rs +++ b/compiler/rustc_target/src/spec/linux_uclibc_base.rs @@ -1,5 +1,5 @@ use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { - TargetOptions { target_env: "uclibc".to_string(), ..super::linux_base::opts() } + TargetOptions { env: "uclibc".to_string(), ..super::linux_base::opts() } } diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs index f0a266a63af..daa0d9da172 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs @@ -7,14 +7,14 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { - target_endian: "big".to_string(), + endian: "big".to_string(), // NOTE(mips64r2) matches C toolchain cpu: "mips64r2".to_string(), features: "+mips64r2".to_string(), max_atomic_width: Some(64), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs index 805a965bc0f..db8d0c04e6f 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs @@ -11,10 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs index f47b058bd08..d767705b045 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs @@ -11,9 +11,9 @@ pub fn target() -> Target { cpu: "mips64r2".to_string(), features: "+mips64r2".to_string(), max_atomic_width: Some(64), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs index 5c985eb842c..766ed69df4b 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs @@ -11,6 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), - options: TargetOptions { target_mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs index 1fc66861364..a7ec1f19c9d 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs @@ -7,13 +7,13 @@ pub fn target() -> Target { data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), options: TargetOptions { - target_endian: "big".to_string(), + endian: "big".to_string(), cpu: "mips32r2".to_string(), features: "+mips32r2,+fpxx,+nooddspreg".to_string(), max_atomic_width: Some(32), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs index ed03f5d990e..1ebe577bc1c 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs @@ -11,10 +11,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs index fa1d789bfa8..2123d5e1a0f 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs @@ -7,11 +7,11 @@ pub fn target() -> Target { data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), options: TargetOptions { - target_endian: "big".to_string(), + endian: "big".to_string(), cpu: "mips32r2".to_string(), features: "+mips32r2,+soft-float".to_string(), max_atomic_width: Some(32), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), ..super::linux_uclibc_base::opts() }, diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs index 3f426e2e5fe..08c290e6ff1 100644 --- a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs +++ b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs @@ -15,8 +15,8 @@ pub fn target() -> Target { arch: "mips".to_string(), options: TargetOptions { - target_os: "psp".to_string(), - target_vendor: "sony".to_string(), + os: "psp".to_string(), + vendor: "sony".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), cpu: "mips2".to_string(), executables: true, diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs index 16fbab58140..9cb2a13c7d4 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs @@ -11,9 +11,9 @@ pub fn target() -> Target { cpu: "mips32r2".to_string(), features: "+mips32r2,+fpxx,+nooddspreg".to_string(), max_atomic_width: Some(32), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs index d1b603cd9de..3374cdd4485 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs @@ -11,6 +11,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), - options: TargetOptions { target_mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs index a09f7ad0121..0831eb7a0a7 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { cpu: "mips32r2".to_string(), features: "+mips32r2,+soft-float".to_string(), max_atomic_width: Some(32), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), ..super::linux_uclibc_base::opts() }, diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs index 60c4c3bb051..a8005927a7b 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs @@ -14,7 +14,7 @@ pub fn target() -> Target { arch: "mips".to_string(), options: TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), cpu: "mips32r2".to_string(), features: "+mips32r2,+soft-float,+noabicalls".to_string(), diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs index 417ee6e043b..11b3734a105 100644 --- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs @@ -7,13 +7,13 @@ pub fn target() -> Target { data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), options: TargetOptions { - target_endian: "big".to_string(), + endian: "big".to_string(), cpu: "mips32r6".to_string(), features: "+mips32r6".to_string(), max_atomic_width: Some(32), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs index cf273c6ab2b..06a5f40d69b 100644 --- a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs @@ -11,9 +11,9 @@ pub fn target() -> Target { cpu: "mips32r6".to_string(), features: "+mips32r6".to_string(), max_atomic_width: Some(32), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs index 1d82395f536..6282c9e1d54 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -7,14 +7,14 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { - target_endian: "big".to_string(), + endian: "big".to_string(), // NOTE(mips64r6) matches C toolchain cpu: "mips64r6".to_string(), features: "+mips64r6".to_string(), max_atomic_width: Some(64), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs index aadd36235bf..589d7acba68 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -11,9 +11,9 @@ pub fn target() -> Target { cpu: "mips64r6".to_string(), features: "+mips64r6".to_string(), max_atomic_width: Some(64), - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 895114b026e..f949bf95a50 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -37,8 +37,9 @@ use crate::spec::abi::{lookup as lookup_abi, Abi}; use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_serialize::json::{Json, ToJson}; +use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeMap; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{fmt, io}; @@ -63,6 +64,7 @@ mod hermit_kernel_base; mod illumos_base; mod l4re_base; mod linux_base; +mod linux_gnu_base; mod linux_kernel_base; mod linux_musl_base; mod linux_uclibc_base; @@ -176,6 +178,13 @@ impl PanicStrategy { PanicStrategy::Abort => "abort", } } + + pub fn desc_symbol(&self) -> Symbol { + match *self { + PanicStrategy::Unwind => sym::unwind, + PanicStrategy::Abort => sym::abort, + } + } } impl ToJson for PanicStrategy { @@ -446,7 +455,7 @@ macro_rules! supported_targets { $( $($triple)|+ => $module::target(), )+ _ => return None, }; - t.options.is_builtin = true; + t.is_builtin = true; debug!("got builtin target: {:?}", t); Some(t) } @@ -691,21 +700,25 @@ impl HasTargetSpec for Target { /// /// This has an implementation of `Default`, see each field for what the default is. In general, /// these try to take "minimal defaults" that don't assume anything about the runtime they run in. +/// +/// `TargetOptions` as a separate structure is mostly an implementation detail of `Target` +/// construction, all its fields logically belong to `Target` and available from `Target` +/// through `Deref` impls. #[derive(PartialEq, Clone, Debug)] pub struct TargetOptions { /// Whether the target is built-in or loaded from a custom target specification. pub is_builtin: bool, /// String to use as the `target_endian` `cfg` variable. Defaults to "little". - pub target_endian: String, + pub endian: String, /// Width of c_int type. Defaults to "32". - pub target_c_int_width: String, + pub c_int_width: String, /// OS name to use for conditional compilation. Defaults to "none". - pub target_os: String, + pub os: String, /// Environment name to use for conditional compilation. Defaults to "". - pub target_env: String, + pub env: String, /// Vendor name to use for conditional compilation. Defaults to "unknown". - pub target_vendor: String, + pub vendor: String, /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed /// on the command line. Defaults to `LinkerFlavor::Gcc`. pub linker_flavor: LinkerFlavor, @@ -796,7 +809,7 @@ pub struct TargetOptions { /// String to append to the name of every static library. Defaults to ".a". pub staticlib_suffix: String, /// OS family to use for conditional compilation. Valid options: "unix", "windows". - pub target_family: Option<String>, + pub os_family: Option<String>, /// Whether the target toolchain's ABI supports returning small structs as an integer. pub abi_return_struct_as_int: bool, /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS, @@ -811,9 +824,6 @@ pub struct TargetOptions { /// library naming convention. Defaults to false. pub is_like_windows: bool, pub is_like_msvc: bool, - /// Whether the target toolchain is like Android's. Only useful for compiling against Android. - /// Defaults to false. - pub is_like_android: bool, /// Whether the target toolchain is like Emscripten's. Only useful for compiling with /// Emscripten toolchain. /// Defaults to false. @@ -957,7 +967,7 @@ pub struct TargetOptions { pub merge_functions: MergeFunctions, /// Use platform dependent mcount function - pub target_mcount: String, + pub mcount: String, /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers pub llvm_abiname: String, @@ -988,11 +998,11 @@ impl Default for TargetOptions { fn default() -> TargetOptions { TargetOptions { is_builtin: false, - target_endian: "little".to_string(), - target_c_int_width: "32".to_string(), - target_os: "none".to_string(), - target_env: String::new(), - target_vendor: "unknown".to_string(), + endian: "little".to_string(), + c_int_width: "32".to_string(), + os: "none".to_string(), + env: String::new(), + vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()), lld_flavor: LldFlavor::Ld, @@ -1016,12 +1026,11 @@ impl Default for TargetOptions { exe_suffix: String::new(), staticlib_prefix: "lib".to_string(), staticlib_suffix: ".a".to_string(), - target_family: None, + os_family: None, abi_return_struct_as_int: false, is_like_osx: false, is_like_solaris: false, is_like_windows: false, - is_like_android: false, is_like_emscripten: false, is_like_msvc: false, is_like_fuchsia: false, @@ -1073,7 +1082,7 @@ impl Default for TargetOptions { limit_rdylib_exports: true, override_export_symbols: None, merge_functions: MergeFunctions::Aliases, - target_mcount: "mcount".to_string(), + mcount: "mcount".to_string(), llvm_abiname: "".to_string(), relax_elf_relocations: false, llvm_args: vec![], @@ -1094,13 +1103,18 @@ impl Deref for Target { &self.options } } +impl DerefMut for Target { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.options + } +} impl Target { /// Given a function ABI, turn it into the correct ABI for this target. pub fn adjust_abi(&self, abi: Abi) -> Abi { match abi { Abi::System => { - if self.options.is_like_windows && self.arch == "x86" { + if self.is_like_windows && self.arch == "x86" { Abi::Stdcall } else { Abi::C @@ -1110,7 +1124,7 @@ impl Target { // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions // and the individual pages for __stdcall et al. Abi::Stdcall | Abi::Fastcall | Abi::Vectorcall | Abi::Thiscall => { - if self.options.is_like_windows && self.arch != "x86" { Abi::C } else { abi } + if self.is_like_windows && self.arch != "x86" { Abi::C } else { abi } } Abi::EfiApi => { if self.arch == "x86_64" { @@ -1126,17 +1140,17 @@ impl Target { /// Minimum integer size in bits that this target can perform atomic /// operations on. pub fn min_atomic_width(&self) -> u64 { - self.options.min_atomic_width.unwrap_or(8) + self.min_atomic_width.unwrap_or(8) } /// Maximum integer size in bits that this target can perform atomic /// operations on. pub fn max_atomic_width(&self) -> u64 { - self.options.max_atomic_width.unwrap_or_else(|| self.pointer_width.into()) + self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into()) } pub fn is_abi_supported(&self, abi: Abi) -> bool { - abi.generic() || !self.options.unsupported_abis.contains(&abi) + abi.generic() || !self.unsupported_abis.contains(&abi) } /// Loads a target descriptor from a JSON object. @@ -1169,19 +1183,19 @@ impl Target { ($key_name:ident) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(s) = obj.find(&name).and_then(Json::as_string) { - base.options.$key_name = s.to_string(); + base.$key_name = s.to_string(); } } ); ($key_name:ident = $json_name:expr) => ( { let name = $json_name; if let Some(s) = obj.find(&name).and_then(Json::as_string) { - base.options.$key_name = s.to_string(); + base.$key_name = s.to_string(); } } ); ($key_name:ident, bool) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(s) = obj.find(&name).and_then(Json::as_boolean) { - base.options.$key_name = s; + base.$key_name = s; } } ); ($key_name:ident, Option<u32>) => ( { @@ -1190,20 +1204,20 @@ impl Target { if s < 1 || s > 5 { return Err("Not a valid DWARF version number".to_string()); } - base.options.$key_name = Some(s as u32); + base.$key_name = Some(s as u32); } } ); ($key_name:ident, Option<u64>) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(s) = obj.find(&name).and_then(Json::as_u64) { - base.options.$key_name = Some(s); + base.$key_name = Some(s); } } ); ($key_name:ident, MergeFunctions) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::<MergeFunctions>() { - Ok(mergefunc) => base.options.$key_name = mergefunc, + Ok(mergefunc) => base.$key_name = mergefunc, _ => return Some(Err(format!("'{}' is not a valid value for \ merge-functions. Use 'disabled', \ 'trampolines', or 'aliases'.", @@ -1216,7 +1230,7 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::<RelocModel>() { - Ok(relocation_model) => base.options.$key_name = relocation_model, + Ok(relocation_model) => base.$key_name = relocation_model, _ => return Some(Err(format!("'{}' is not a valid relocation model. \ Run `rustc --print relocation-models` to \ see the list of supported values.", s))), @@ -1228,7 +1242,7 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::<CodeModel>() { - Ok(code_model) => base.options.$key_name = Some(code_model), + Ok(code_model) => base.$key_name = Some(code_model), _ => return Some(Err(format!("'{}' is not a valid code model. \ Run `rustc --print code-models` to \ see the list of supported values.", s))), @@ -1240,7 +1254,7 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::<TlsModel>() { - Ok(tls_model) => base.options.$key_name = tls_model, + Ok(tls_model) => base.$key_name = tls_model, _ => return Some(Err(format!("'{}' is not a valid TLS model. \ Run `rustc --print tls-models` to \ see the list of supported values.", s))), @@ -1252,8 +1266,8 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s { - "unwind" => base.options.$key_name = PanicStrategy::Unwind, - "abort" => base.options.$key_name = PanicStrategy::Abort, + "unwind" => base.$key_name = PanicStrategy::Unwind, + "abort" => base.$key_name = PanicStrategy::Abort, _ => return Some(Err(format!("'{}' is not a valid value for \ panic-strategy. Use 'unwind' or 'abort'.", s))), @@ -1265,7 +1279,7 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::<RelroLevel>() { - Ok(level) => base.options.$key_name = level, + Ok(level) => base.$key_name = level, _ => return Some(Err(format!("'{}' is not a valid value for \ relro-level. Use 'full', 'partial, or 'off'.", s))), @@ -1276,7 +1290,7 @@ impl Target { ($key_name:ident, list) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(v) = obj.find(&name).and_then(Json::as_array) { - base.options.$key_name = v.iter() + base.$key_name = v.iter() .map(|a| a.as_string().unwrap().to_string()) .collect(); } @@ -1284,7 +1298,7 @@ impl Target { ($key_name:ident, opt_list) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(v) = obj.find(&name).and_then(Json::as_array) { - base.options.$key_name = Some(v.iter() + base.$key_name = Some(v.iter() .map(|a| a.as_string().unwrap().to_string()) .collect()); } @@ -1292,7 +1306,15 @@ impl Target { ($key_name:ident, optional) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(o) = obj.find(&name[..]) { - base.options.$key_name = o + base.$key_name = o + .as_string() + .map(|s| s.to_string() ); + } + } ); + ($key_name:ident = $json_name:expr, optional) => ( { + let name = $json_name; + if let Some(o) = obj.find(&name[..]) { + base.$key_name = o .as_string() .map(|s| s.to_string() ); } @@ -1301,7 +1323,7 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { if let Some(flavor) = LldFlavor::from_str(&s) { - base.options.$key_name = flavor; + base.$key_name = flavor; } else { return Some(Err(format!( "'{}' is not a valid value for lld-flavor. \ @@ -1315,7 +1337,7 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match LinkerFlavor::from_str(s) { - Some(linker_flavor) => base.options.$key_name = linker_flavor, + Some(linker_flavor) => base.$key_name = linker_flavor, _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \ Use {}", s, LinkerFlavor::one_of()))), } @@ -1326,7 +1348,7 @@ impl Target { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::<CrtObjectsFallback>() { - Ok(fallback) => base.options.$key_name = Some(fallback), + Ok(fallback) => base.$key_name = Some(fallback), _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \ Use 'musl', 'mingw' or 'wasm'", s))), } @@ -1358,7 +1380,7 @@ impl Target { args.insert(kind, v); } - base.options.$key_name = args; + base.$key_name = args; } } ); ($key_name:ident, link_args) => ( { @@ -1385,7 +1407,7 @@ impl Target { args.insert(flavor, v); } - base.options.$key_name = args; + base.$key_name = args; } } ); ($key_name:ident, env) => ( { @@ -1397,7 +1419,7 @@ impl Target { if p.len() == 2 { let k = p[0].to_string(); let v = p[1].to_string(); - base.options.$key_name.push((k, v)); + base.$key_name.push((k, v)); } } } @@ -1406,11 +1428,11 @@ impl Target { } key!(is_builtin, bool); - key!(target_endian); - key!(target_c_int_width); - key!(target_os = "os"); - key!(target_env = "env"); - key!(target_vendor = "vendor"); + key!(endian = "target_endian"); + key!(c_int_width = "target_c_int_width"); + key!(os); + key!(env); + key!(vendor); key!(linker_flavor, LinkerFlavor)?; key!(linker, optional); key!(lld_flavor, LldFlavor)?; @@ -1444,14 +1466,13 @@ impl Target { key!(exe_suffix); key!(staticlib_prefix); key!(staticlib_suffix); - key!(target_family, optional); + key!(os_family = "target_family", optional); key!(abi_return_struct_as_int, bool); key!(is_like_osx, bool); key!(is_like_solaris, bool); key!(is_like_windows, bool); key!(is_like_msvc, bool); key!(is_like_emscripten, bool); - key!(is_like_android, bool); key!(is_like_fuchsia, bool); key!(dwarf_version, Option<u32>); key!(linker_is_gnu, bool); @@ -1490,7 +1511,7 @@ impl Target { key!(limit_rdylib_exports, bool); key!(override_export_symbols, opt_list); key!(merge_functions, MergeFunctions)?; - key!(target_mcount); + key!(mcount = "target_mcount"); key!(llvm_abiname); key!(relax_elf_relocations, bool); key!(llvm_args, list); @@ -1513,7 +1534,7 @@ impl Target { )); } - base.options.unsupported_abis.push(abi) + base.unsupported_abis.push(abi) } None => { return Err(format!( @@ -1602,21 +1623,20 @@ impl ToJson for Target { macro_rules! target_option_val { ($attr:ident) => {{ let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != self.options.$attr { - d.insert(name, self.options.$attr.to_json()); + if default.$attr != self.$attr { + d.insert(name, self.$attr.to_json()); } }}; ($attr:ident, $key_name:expr) => {{ let name = $key_name; - if default.$attr != self.options.$attr { - d.insert(name.to_string(), self.options.$attr.to_json()); + if default.$attr != self.$attr { + d.insert(name.to_string(), self.$attr.to_json()); } }}; (link_args - $attr:ident) => {{ let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != self.options.$attr { + if default.$attr != self.$attr { let obj = self - .options .$attr .iter() .map(|(k, v)| (k.desc().to_owned(), v.clone())) @@ -1626,9 +1646,8 @@ impl ToJson for Target { }}; (env - $attr:ident) => {{ let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != self.options.$attr { + if default.$attr != self.$attr { let obj = self - .options .$attr .iter() .map(|&(ref k, ref v)| k.clone() + "=" + &v) @@ -1644,11 +1663,11 @@ impl ToJson for Target { target_val!(data_layout); target_option_val!(is_builtin); - target_option_val!(target_endian); - target_option_val!(target_c_int_width); - target_option_val!(target_os, "os"); - target_option_val!(target_env, "env"); - target_option_val!(target_vendor, "vendor"); + target_option_val!(endian, "target_endian"); + target_option_val!(c_int_width, "target_c_int_width"); + target_option_val!(os); + target_option_val!(env); + target_option_val!(vendor); target_option_val!(linker_flavor); target_option_val!(linker); target_option_val!(lld_flavor); @@ -1682,14 +1701,13 @@ impl ToJson for Target { target_option_val!(exe_suffix); target_option_val!(staticlib_prefix); target_option_val!(staticlib_suffix); - target_option_val!(target_family); + target_option_val!(os_family, "target_family"); target_option_val!(abi_return_struct_as_int); target_option_val!(is_like_osx); target_option_val!(is_like_solaris); target_option_val!(is_like_windows); target_option_val!(is_like_msvc); target_option_val!(is_like_emscripten); - target_option_val!(is_like_android); target_option_val!(is_like_fuchsia); target_option_val!(dwarf_version); target_option_val!(linker_is_gnu); @@ -1728,7 +1746,7 @@ impl ToJson for Target { target_option_val!(limit_rdylib_exports); target_option_val!(override_export_symbols); target_option_val!(merge_functions); - target_option_val!(target_mcount); + target_option_val!(mcount, "target_mcount"); target_option_val!(llvm_abiname); target_option_val!(relax_elf_relocations); target_option_val!(llvm_args); @@ -1736,11 +1754,10 @@ impl ToJson for Target { target_option_val!(eh_frame_header); target_option_val!(has_thumb_interworking); - if default.unsupported_abis != self.options.unsupported_abis { + if default.unsupported_abis != self.unsupported_abis { d.insert( "unsupported-abis".to_string(), - self.options - .unsupported_abis + self.unsupported_abis .iter() .map(|&name| Abi::name(name).to_json()) .collect::<Vec<_>>() diff --git a/compiler/rustc_target/src/spec/msp430_none_elf.rs b/compiler/rustc_target/src/spec/msp430_none_elf.rs index 48b6d1be9ce..ef966cb702e 100644 --- a/compiler/rustc_target/src/spec/msp430_none_elf.rs +++ b/compiler/rustc_target/src/spec/msp430_none_elf.rs @@ -8,8 +8,8 @@ pub fn target() -> Target { arch: "msp430".to_string(), options: TargetOptions { - target_c_int_width: "16".to_string(), - target_vendor: String::new(), + c_int_width: "16".to_string(), + vendor: String::new(), executables: true, // The LLVM backend currently can't generate object files. To diff --git a/compiler/rustc_target/src/spec/netbsd_base.rs b/compiler/rustc_target/src/spec/netbsd_base.rs index 437b50b6f11..a77d60bd9d7 100644 --- a/compiler/rustc_target/src/spec/netbsd_base.rs +++ b/compiler/rustc_target/src/spec/netbsd_base.rs @@ -14,10 +14,10 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "netbsd".to_string(), + os: "netbsd".to_string(), dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), linker_is_gnu: true, no_default_libraries: false, has_rpath: true, diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs index f759724445e..3c9c7d578fb 100644 --- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs @@ -9,8 +9,8 @@ pub fn target() -> Target { pointer_width: 64, options: TargetOptions { - target_os: "cuda".to_string(), - target_vendor: "nvidia".to_string(), + os: "cuda".to_string(), + vendor: "nvidia".to_string(), linker_flavor: LinkerFlavor::PtxLinker, // The linker can be installed from `crates.io`. linker: Some("rust-ptx-linker".to_string()), diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/openbsd_base.rs index 5e83e79d9ed..2b40a1ed945 100644 --- a/compiler/rustc_target/src/spec/openbsd_base.rs +++ b/compiler/rustc_target/src/spec/openbsd_base.rs @@ -16,10 +16,10 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "openbsd".to_string(), + os: "openbsd".to_string(), dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, abi_return_struct_as_int: true, diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs index 3d20f15b391..626865aa242 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs @@ -11,10 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs index e52643eb893..03322818d33 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); @@ -15,10 +15,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs index 315192929ac..231539756f3 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs @@ -11,10 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs index a31256761a4..1c83e3e64d4 100644 --- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs @@ -11,6 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { target_endian: "big".to_string(), ..base }, + options: TargetOptions { endian: "big".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs index 4cf296c3fa7..07e0bf81bc7 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64le".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); @@ -11,6 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { target_mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs index 41756028cbe..41c78a5f276 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs @@ -11,6 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { target_mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs index f3ec02c10d2..3a9271247b0 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); base.max_atomic_width = Some(32); @@ -10,10 +10,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs index 4e3ffca0a08..105a0b21aaf 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string()); base.max_atomic_width = Some(32); @@ -10,10 +10,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs index 1d5c19b5420..49d32944789 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs @@ -10,10 +10,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "_mcount".to_string(), - ..base - }, + options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs index 4d7eb8d0100..387d6cdc456 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "__mcount".to_string(), + endian: "big".to_string(), + mcount: "__mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs index dc6a4e28a3d..20ffa07b997 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs @@ -12,7 +12,7 @@ pub fn target() -> Target { data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), options: TargetOptions { - target_endian: "big".to_string(), + endian: "big".to_string(), features: "+secure-plt".to_string(), ..base }, diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs index 1ce3fa21918..0e713fccd23 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs @@ -12,7 +12,7 @@ pub fn target() -> Target { data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), options: TargetOptions { - target_endian: "big".to_string(), + endian: "big".to_string(), // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2 features: "+secure-plt,+msync".to_string(), ..base diff --git a/compiler/rustc_target/src/spec/redox_base.rs b/compiler/rustc_target/src/spec/redox_base.rs index 04409a1cd04..5ef705878a8 100644 --- a/compiler/rustc_target/src/spec/redox_base.rs +++ b/compiler/rustc_target/src/spec/redox_base.rs @@ -19,11 +19,11 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "redox".to_string(), - target_env: "relibc".to_string(), + os: "redox".to_string(), + env: "relibc".to_string(), dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: args, diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs index f9405d9dfb6..cf5e0201d08 100644 --- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".to_string(), llvm_abiname: "ilp32d".to_string(), max_atomic_width: Some(32), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs index 3b7ff47a540..84f28413fcb 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".to_string(), llvm_abiname: "lp64d".to_string(), max_atomic_width: Some(64), - ..super::linux_base::opts() + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs index 69b880cdb81..d6e8e6ee220 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::spec::Target; pub fn target() -> Target { - let mut base = super::linux_base::opts(); - base.target_endian = "big".to_string(); + let mut base = super::linux_gnu_base::opts(); + base.endian = "big".to_string(); // z10 is the oldest CPU supported by LLVM base.cpu = "z10".to_string(); // FIXME: The data_layout string below and the ABI implementation in diff --git a/compiler/rustc_target/src/spec/solaris_base.rs b/compiler/rustc_target/src/spec/solaris_base.rs index 1454d83e936..33e0cf8e967 100644 --- a/compiler/rustc_target/src/spec/solaris_base.rs +++ b/compiler/rustc_target/src/spec/solaris_base.rs @@ -2,12 +2,12 @@ use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { TargetOptions { - target_os: "solaris".to_string(), - target_vendor: "sun".to_string(), + os: "solaris".to_string(), + vendor: "sun".to_string(), dynamic_linking: true, executables: true, has_rpath: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), is_like_solaris: true, limit_rdylib_exports: false, // Linker doesn't support this eh_frame_header: false, diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs index f02b01a514b..e9b5520ac3d 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::spec::Target; pub fn target() -> Target { - let mut base = super::linux_base::opts(); - base.target_endian = "big".to_string(); + let mut base = super::linux_gnu_base::opts(); + base.endian = "big".to_string(); base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs index de35bb8fe14..c8e90f832d0 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { data_layout: "E-m:e-i64:64-n32:64-S128".to_string(), arch: "sparc64".to_string(), options: TargetOptions { - target_endian: "big".to_string(), - target_mcount: "__mcount".to_string(), + endian: "big".to_string(), + mcount: "__mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs index 301c91e432c..630ce6123f9 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs @@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::openbsd_base::opts(); - base.target_endian = "big".to_string(); + base.endian = "big".to_string(); base.cpu = "v9".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs index 071175819f4..aae186b2293 100644 --- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); - base.target_endian = "big".to_string(); + let mut base = super::linux_gnu_base::opts(); + base.endian = "big".to_string(); base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string()); diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs index e8c30dcbf85..5f99e0b14f9 100644 --- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs @@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::solaris_base::opts(); - base.target_endian = "big".to_string(); + base.endian = "big".to_string(); base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); // llvm calls this "v9" base.cpu = "v9".to_string(); diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index d06ab368e1c..f348df7d5a7 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -14,27 +14,27 @@ impl Target { assert_eq!( self.linker_flavor == LinkerFlavor::Msvc || self.linker_flavor == LinkerFlavor::Lld(LldFlavor::Link), - self.options.lld_flavor == LldFlavor::Link, + self.lld_flavor == LldFlavor::Link, ); for args in &[ - &self.options.pre_link_args, - &self.options.late_link_args, - &self.options.late_link_args_dynamic, - &self.options.late_link_args_static, - &self.options.post_link_args, + &self.pre_link_args, + &self.late_link_args, + &self.late_link_args_dynamic, + &self.late_link_args_static, + &self.post_link_args, ] { assert_eq!( args.get(&LinkerFlavor::Msvc), args.get(&LinkerFlavor::Lld(LldFlavor::Link)), ); if args.contains_key(&LinkerFlavor::Msvc) { - assert_eq!(self.options.lld_flavor, LldFlavor::Link); + assert_eq!(self.lld_flavor, LldFlavor::Link); } } assert!( - (self.options.pre_link_objects_fallback.is_empty() - && self.options.post_link_objects_fallback.is_empty()) - || self.options.crt_objects_fallback.is_some() + (self.pre_link_objects_fallback.is_empty() + && self.post_link_objects_fallback.is_empty()) + || self.crt_objects_fallback.is_some() ); } } diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs index cc955799d2f..e5504675027 100644 --- a/compiler/rustc_target/src/spec/thumb_base.rs +++ b/compiler/rustc_target/src/spec/thumb_base.rs @@ -32,7 +32,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOpti pub fn opts() -> TargetOptions { // See rust-lang/rfcs#1645 for a discussion about these defaults TargetOptions { - target_vendor: String::new(), + vendor: String::new(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, // In most cases, LLD is good enough diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs index 561da4d15cd..352d2468743 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs @@ -7,7 +7,7 @@ use crate::spec::{Target, TargetOptions}; // https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf pub fn target() -> Target { - let base = super::linux_base::opts(); + let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".to_string(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs index 5b1fc74bdd0..a788167aede 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs @@ -24,7 +24,7 @@ pub fn target() -> Target { cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), - target_mcount: "\u{1}mcount".to_string(), + mcount: "\u{1}mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs index 91a39f7b9b4..79fe77495e7 100644 --- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs +++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs @@ -37,7 +37,7 @@ pub fn opts() -> TargetOptions { .extend(pre_link_args_msvc); TargetOptions { - target_os: "uefi".to_string(), + os: "uefi".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Link), disable_redzone: true, exe_suffix: ".efi".to_string(), diff --git a/compiler/rustc_target/src/spec/vxworks_base.rs b/compiler/rustc_target/src/spec/vxworks_base.rs index e8044e4dc1a..70bc9ce3e0e 100644 --- a/compiler/rustc_target/src/spec/vxworks_base.rs +++ b/compiler/rustc_target/src/spec/vxworks_base.rs @@ -17,14 +17,14 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - target_os: "vxworks".to_string(), - target_env: "gnu".to_string(), - target_vendor: "wrs".to_string(), + os: "vxworks".to_string(), + env: "gnu".to_string(), + vendor: "wrs".to_string(), linker: Some("wr-c++".to_string()), exe_suffix: ".vxe".to_string(), dynamic_linking: true, executables: true, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: args, @@ -34,7 +34,7 @@ pub fn opts() -> TargetOptions { crt_static_respected: true, crt_static_allows_dylibs: true, // VxWorks needs to implement this to support profiling - target_mcount: "_mcount".to_string(), + mcount: "_mcount".to_string(), ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index dbafe362f2a..c12757b8f98 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { ); let opts = TargetOptions { - target_os: "emscripten".to_string(), + os: "emscripten".to_string(), linker_flavor: LinkerFlavor::Em, // emcc emits two files - a .js file to instantiate the wasm and supply platform // functionality, and a .wasm file. @@ -27,7 +27,7 @@ pub fn target() -> Target { is_like_emscripten: true, panic_strategy: PanicStrategy::Unwind, post_link_args, - target_family: Some("unix".to_string()), + os_family: Some("unix".to_string()), ..wasm32_base::options() }; Target { diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 4401772788b..6037aa5b430 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -15,7 +15,7 @@ use super::{LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut options = wasm32_base::options(); - options.target_os = "unknown".to_string(); + options.os = "unknown".to_string(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 6f5316e30f6..9c697674f39 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -78,8 +78,8 @@ use super::{crt_objects, LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut options = wasm32_base::options(); - options.target_os = "wasi".to_string(); - options.target_vendor = String::new(); + options.os = "wasi".to_string(); + options.vendor = String::new(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); options .pre_link_args diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs index 37188a59eb5..f556a13a519 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs @@ -62,9 +62,9 @@ pub fn opts() -> TargetOptions { late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs); TargetOptions { - target_os: "windows".to_string(), - target_env: "gnu".to_string(), - target_vendor: "pc".to_string(), + os: "windows".to_string(), + env: "gnu".to_string(), + vendor: "pc".to_string(), // FIXME(#13846) this should be enabled for windows function_sections: false, linker: Some("gcc".to_string()), @@ -75,7 +75,7 @@ pub fn opts() -> TargetOptions { exe_suffix: ".exe".to_string(), staticlib_prefix: "lib".to_string(), staticlib_suffix: ".a".to_string(), - target_family: Some("windows".to_string()), + os_family: Some("windows".to_string()), is_like_windows: true, allows_weak_linkage: false, pre_link_args, diff --git a/compiler/rustc_target/src/spec/windows_msvc_base.rs b/compiler/rustc_target/src/spec/windows_msvc_base.rs index c1101623867..c041245e328 100644 --- a/compiler/rustc_target/src/spec/windows_msvc_base.rs +++ b/compiler/rustc_target/src/spec/windows_msvc_base.rs @@ -4,16 +4,16 @@ pub fn opts() -> TargetOptions { let base = super::msvc_base::opts(); TargetOptions { - target_os: "windows".to_string(), - target_env: "msvc".to_string(), - target_vendor: "pc".to_string(), + os: "windows".to_string(), + env: "msvc".to_string(), + vendor: "pc".to_string(), dynamic_linking: true, dll_prefix: String::new(), dll_suffix: ".dll".to_string(), exe_suffix: ".exe".to_string(), staticlib_prefix: String::new(), staticlib_suffix: ".lib".to_string(), - target_family: Some("windows".to_string()), + os_family: Some("windows".to_string()), crt_static_allows_dylibs: true, crt_static_respected: true, requires_uwtable: true, diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs index 225b94c3755..67d1be399b3 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs @@ -25,7 +25,7 @@ pub fn opts() -> TargetOptions { late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs); TargetOptions { - target_vendor: "uwp".to_string(), + vendor: "uwp".to_string(), executables: false, limit_rdylib_exports: false, late_link_args, diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs index 380d685dacf..700ee5ec646 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs +++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, TargetOptions}; pub fn opts() -> TargetOptions { let mut opts = super::windows_msvc_base::opts(); - opts.target_vendor = "uwp".to_string(); + opts.vendor = "uwp".to_string(); let pre_link_args_msvc = vec!["/APPCONTAINER".to_string(), "mincore.lib".to_string()]; opts.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); opts.pre_link_args 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 6cd4daa7a74..edb33fe6e2b 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -24,6 +24,6 @@ pub fn target() -> Target { data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .to_string(), arch: arch.to_string(), - options: TargetOptions { target_mcount: "\u{1}mcount".to_string(), ..base }, + options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs index 550d308ed8f..74fb6f0a834 100644 --- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs @@ -55,9 +55,9 @@ pub fn target() -> Target { "TEXT_SIZE", ]; let opts = TargetOptions { - target_os: "unknown".into(), - target_env: "sgx".into(), - target_vendor: "fortanix".into(), + os: "unknown".into(), + env: "sgx".into(), + vendor: "fortanix".into(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), dynamic_linking: false, executables: true, diff --git a/compiler/rustc_target/src/spec/x86_64_rumprun_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_rumprun_netbsd.rs index 511a4559935..095c6f15c77 100644 --- a/compiler/rustc_target/src/spec/x86_64_rumprun_netbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_rumprun_netbsd.rs @@ -2,7 +2,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::netbsd_base::opts(); - base.target_vendor = "rumprun".to_string(); + base.vendor = "rumprun".to_string(); base.cpu = "x86-64".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.linker = Some("x86_64-rumprun-netbsd-gcc".to_string()); @@ -20,6 +20,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .to_string(), arch: "x86_64".to_string(), - options: TargetOptions { target_mcount: "__mcount".to_string(), ..base }, + options: TargetOptions { mcount: "__mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs index 1f368ff1611..f127dd49bc4 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs index 375b22fd92b..0cae5752848 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string()); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs index 656ef90892c..7e91a6ddbe2 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs @@ -13,6 +13,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .to_string(), arch: "x86_64".to_string(), - options: TargetOptions { target_mcount: "__mcount".to_string(), ..base }, + options: TargetOptions { mcount: "__mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 638a8253e7e..e1721a5a88a 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -512,6 +512,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { block = &self.body.basic_blocks()[next]; } else { assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); + // `AbstractConst`s should not contain any promoteds as they require references which + // are not allowed. + assert!(!self.nodes.iter().any(|n| matches!( + n.node, + Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(_, _, Some(_)), ty: _ }) + ))); + self.nodes[self.locals[mir::RETURN_PLACE]].used = true; if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { self.error(Some(unused.span), "dead code")?; @@ -609,6 +616,10 @@ pub(super) fn try_unify<'tcx>( (Node::Leaf(a_ct), Node::Leaf(b_ct)) => { let a_ct = a_ct.subst(tcx, a.substs); let b_ct = b_ct.subst(tcx, b.substs); + if a_ct.ty != b_ct.ty { + return false; + } + match (a_ct.val, b_ct.val) { // We can just unify errors with everything to reduce the amount of // emitted errors here. @@ -621,6 +632,12 @@ pub(super) fn try_unify<'tcx>( // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This // means that we only allow inference variables if they are equal. (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val, + // We may want to instead recurse into unevaluated constants here. That may require some + // care to prevent infinite recursion, so let's just ignore this for now. + ( + ty::ConstKind::Unevaluated(a_def, a_substs, None), + ty::ConstKind::Unevaluated(b_def, b_substs, None), + ) => a_def == b_def && a_substs == b_substs, // FIXME(const_evaluatable_checked): We may want to either actually try // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like // this, for now we just return false here. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4cc4bc0acda..a91f693f175 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -279,7 +279,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// tracking is not enabled, just returns an empty vector. pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> { assert!(self.intercrate); - self.intercrate_ambiguity_causes.take().unwrap_or(vec![]) + self.intercrate_ambiguity_causes.take().unwrap_or_default() } pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx> { diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index a54fe08394e..8bd9e29629d 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -12,9 +12,9 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -chalk-ir = "0.32.0" -chalk-solve = "0.32.0" -chalk-engine = "0.32.0" +chalk-ir = "0.36.0" +chalk-solve = "0.36.0" +chalk-engine = "0.36.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index e5ae899a2f3..c5a46b1003d 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -37,7 +37,7 @@ impl<'tcx> RustIrDatabase<'tcx> { def_id: DefId, bound_vars: SubstsRef<'tcx>, ) -> Vec<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> { - let predicates = self.interner.tcx.predicates_of(def_id).predicates; + let predicates = self.interner.tcx.predicates_defined_on(def_id).predicates; let mut regions_substitutor = lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder); predicates @@ -118,34 +118,27 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t .map(|i| chalk_ir::AssocTypeId(i.def_id)) .collect(); - let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) { + let lang_items = self.interner.tcx.lang_items(); + let well_known = if lang_items.sized_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Sized) - } else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) { + } else if lang_items.copy_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Copy) - } else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) { + } else if lang_items.clone_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Clone) - } else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) { + } else if lang_items.drop_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Drop) - } else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) { + } else if lang_items.fn_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Fn) - } else if self - .interner - .tcx - .lang_items() - .fn_once_trait() - .map(|t| def_id == t) - .unwrap_or(false) - { + } else if lang_items.fn_once_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::FnOnce) - } else if self - .interner - .tcx - .lang_items() - .fn_mut_trait() - .map(|t| def_id == t) - .unwrap_or(false) - { + } else if lang_items.fn_mut_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::FnMut) + } else if lang_items.unsize_trait() == Some(def_id) { + Some(chalk_solve::rust_ir::WellKnownTrait::Unsize) + } else if lang_items.unpin_trait() == Some(def_id) { + Some(chalk_solve::rust_ir::WellKnownTrait::Unpin) + } else if lang_items.coerce_unsized_trait() == Some(def_id) { + Some(chalk_solve::rust_ir::WellKnownTrait::CoerceUnsized) } else { None }; @@ -281,11 +274,20 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t where_clauses, }; + let associated_ty_value_ids: Vec<_> = self + .interner + .tcx + .associated_items(def_id) + .in_definition_order() + .filter(|i| i.kind == AssocKind::Type) + .map(|i| chalk_solve::rust_ir::AssociatedTyValueId(i.def_id)) + .collect(); + Arc::new(chalk_solve::rust_ir::ImplDatum { - polarity: chalk_solve::rust_ir::Polarity::Positive, + polarity: self.interner.tcx.impl_polarity(def_id).lower_into(&self.interner), binders: chalk_ir::Binders::new(binders, value), impl_type: chalk_solve::rust_ir::ImplType::Local, - associated_ty_value_ids: vec![], + associated_ty_value_ids, }) } @@ -324,19 +326,19 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t fn impl_provided_for( &self, auto_trait_id: chalk_ir::TraitId<RustInterner<'tcx>>, - app_ty: &chalk_ir::ApplicationTy<RustInterner<'tcx>>, + chalk_ty: &chalk_ir::TyKind<RustInterner<'tcx>>, ) -> bool { use chalk_ir::Scalar::*; - use chalk_ir::TypeName::*; + use chalk_ir::TyKind::*; let trait_def_id = auto_trait_id.0; let all_impls = self.interner.tcx.all_impls(trait_def_id); for impl_def_id in all_impls { let trait_ref = self.interner.tcx.impl_trait_ref(impl_def_id).unwrap(); let self_ty = trait_ref.self_ty(); - let provides = match (self_ty.kind(), app_ty.name) { - (&ty::Adt(impl_adt_def, ..), Adt(id)) => impl_adt_def.did == id.0.did, - (_, AssociatedType(_ty_id)) => { + let provides = match (self_ty.kind(), chalk_ty) { + (&ty::Adt(impl_adt_def, ..), Adt(id, ..)) => impl_adt_def.did == id.0.did, + (_, AssociatedType(_ty_id, ..)) => { // FIXME(chalk): See https://github.com/rust-lang/rust/pull/77152#discussion_r494484774 false } @@ -365,10 +367,10 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t (ast::FloatTy::F32, chalk_ir::FloatTy::F32) | (ast::FloatTy::F64, chalk_ir::FloatTy::F64) ), - (&ty::Tuple(..), Tuple(..)) => true, - (&ty::Array(..), Array) => true, - (&ty::Slice(..), Slice) => true, - (&ty::RawPtr(type_and_mut), Raw(mutability)) => { + (&ty::Tuple(substs), Tuple(len, _)) => substs.len() == *len, + (&ty::Array(..), Array(..)) => true, + (&ty::Slice(..), Slice(..)) => true, + (&ty::RawPtr(type_and_mut), Raw(mutability, _)) => { match (type_and_mut.mutbl, mutability) { (ast::Mutability::Mut, chalk_ir::Mutability::Mut) => true, (ast::Mutability::Mut, chalk_ir::Mutability::Not) => false, @@ -376,17 +378,19 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t (ast::Mutability::Not, chalk_ir::Mutability::Not) => true, } } - (&ty::Ref(.., mutability1), Ref(mutability2)) => match (mutability1, mutability2) { - (ast::Mutability::Mut, chalk_ir::Mutability::Mut) => true, - (ast::Mutability::Mut, chalk_ir::Mutability::Not) => false, - (ast::Mutability::Not, chalk_ir::Mutability::Mut) => false, - (ast::Mutability::Not, chalk_ir::Mutability::Not) => true, - }, - (&ty::Opaque(def_id, ..), OpaqueType(opaque_ty_id)) => def_id == opaque_ty_id.0, - (&ty::FnDef(def_id, ..), FnDef(fn_def_id)) => def_id == fn_def_id.0, + (&ty::Ref(.., mutability1), Ref(mutability2, ..)) => { + match (mutability1, mutability2) { + (ast::Mutability::Mut, chalk_ir::Mutability::Mut) => true, + (ast::Mutability::Mut, chalk_ir::Mutability::Not) => false, + (ast::Mutability::Not, chalk_ir::Mutability::Mut) => false, + (ast::Mutability::Not, chalk_ir::Mutability::Not) => true, + } + } + (&ty::Opaque(def_id, ..), OpaqueType(opaque_ty_id, ..)) => def_id == opaque_ty_id.0, + (&ty::FnDef(def_id, ..), FnDef(fn_def_id, ..)) => def_id == fn_def_id.0, (&ty::Str, Str) => true, (&ty::Never, Never) => true, - (&ty::Closure(def_id, ..), Closure(closure_id)) => def_id == closure_id.0, + (&ty::Closure(def_id, ..), Closure(closure_id, _)) => def_id == closure_id.0, (&ty::Foreign(def_id), Foreign(foreign_def_id)) => def_id == foreign_def_id.0, (&ty::Error(..), Error) => false, _ => false, @@ -404,24 +408,38 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t ) -> Arc<chalk_solve::rust_ir::AssociatedTyValue<RustInterner<'tcx>>> { let def_id = associated_ty_id.0; let assoc_item = self.interner.tcx.associated_item(def_id); - let impl_id = match assoc_item.container { - AssocItemContainer::TraitContainer(def_id) => def_id, - _ => unimplemented!("Not possible??"), + let (impl_id, trait_id) = match assoc_item.container { + AssocItemContainer::TraitContainer(def_id) => (def_id, def_id), + AssocItemContainer::ImplContainer(def_id) => { + (def_id, self.interner.tcx.impl_trait_ref(def_id).unwrap().def_id) + } }; match assoc_item.kind { AssocKind::Type => {} _ => unimplemented!("Not possible??"), } + + let trait_item = self + .interner + .tcx + .associated_items(trait_id) + .find_by_name_and_kind(self.interner.tcx, assoc_item.ident, assoc_item.kind, trait_id) + .unwrap(); let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); let binders = binders_for(&self.interner, bound_vars); - let ty = self.interner.tcx.type_of(def_id); + let ty = self + .interner + .tcx + .type_of(def_id) + .subst(self.interner.tcx, bound_vars) + .lower_into(&self.interner); Arc::new(chalk_solve::rust_ir::AssociatedTyValue { impl_id: chalk_ir::ImplId(impl_id), - associated_ty_id: chalk_ir::AssocTypeId(def_id), + associated_ty_id: chalk_ir::AssocTypeId(trait_item.def_id), value: chalk_ir::Binders::new( binders, - chalk_solve::rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) }, + chalk_solve::rust_ir::AssociatedTyValueBound { ty }, ), }) } @@ -441,19 +459,61 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t &self, opaque_ty_id: chalk_ir::OpaqueTyId<RustInterner<'tcx>>, ) -> Arc<chalk_solve::rust_ir::OpaqueTyDatum<RustInterner<'tcx>>> { - let bound_vars = bound_vars_for_item(self.interner.tcx, opaque_ty_id.0); - let binders = binders_for(&self.interner, bound_vars); + let bound_vars = ty::fold::shift_vars( + self.interner.tcx, + &bound_vars_for_item(self.interner.tcx, opaque_ty_id.0), + 1, + ); let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars); - let bounds = self.bounds_for(opaque_ty_id.0, bound_vars); + + let identity_substs = InternalSubsts::identity_for_item(self.interner.tcx, opaque_ty_id.0); + + let bounds = + self.interner + .tcx + .explicit_item_bounds(opaque_ty_id.0) + .iter() + .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) + .map(|bound| { + bound.fold_with(&mut ty::fold::BottomUpFolder { + tcx: self.interner.tcx, + ty_op: |ty| { + if let ty::Opaque(def_id, substs) = *ty.kind() { + if def_id == opaque_ty_id.0 && substs == identity_substs { + return self.interner.tcx.mk_ty(ty::Bound( + ty::INNERMOST, + ty::BoundTy::from(ty::BoundVar::from_u32(0)), + )); + } + } + ty + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }) + }) + .filter_map(|bound| { + LowerInto::< + Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> + >::lower_into(bound, &self.interner) + }) + .collect(); + + // Binder for the bound variable representing the concrete impl Trait type. + let existential_binder = chalk_ir::VariableKinds::from1( + &self.interner, + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), + ); let value = chalk_solve::rust_ir::OpaqueTyDatumBound { - bounds: chalk_ir::Binders::new(binders.clone(), bounds), - where_clauses: chalk_ir::Binders::new(binders, where_clauses), + bounds: chalk_ir::Binders::new(existential_binder.clone(), bounds), + where_clauses: chalk_ir::Binders::new(existential_binder, where_clauses), }; + let binders = binders_for(&self.interner, bound_vars); Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { opaque_ty_id, - bound: chalk_ir::Binders::empty(&self.interner, value), + bound: chalk_ir::Binders::new(binders, value), }) } @@ -506,17 +566,11 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t substs: &chalk_ir::Substitution<RustInterner<'tcx>>, ) -> chalk_solve::rust_ir::ClosureKind { let kind = &substs.as_slice(&self.interner)[substs.len(&self.interner) - 3]; - match kind.assert_ty_ref(&self.interner).data(&self.interner) { - chalk_ir::TyData::Apply(apply) => match apply.name { - chalk_ir::TypeName::Scalar(scalar) => match scalar { - chalk_ir::Scalar::Int(int_ty) => match int_ty { - chalk_ir::IntTy::I8 => chalk_solve::rust_ir::ClosureKind::Fn, - chalk_ir::IntTy::I16 => chalk_solve::rust_ir::ClosureKind::FnMut, - chalk_ir::IntTy::I32 => chalk_solve::rust_ir::ClosureKind::FnOnce, - _ => bug!("bad closure kind"), - }, - _ => bug!("bad closure kind"), - }, + match kind.assert_ty_ref(&self.interner).kind(&self.interner) { + chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(int_ty)) => match int_ty { + chalk_ir::IntTy::I8 => chalk_solve::rust_ir::ClosureKind::Fn, + chalk_ir::IntTy::I16 => chalk_solve::rust_ir::ClosureKind::FnMut, + chalk_ir::IntTy::I32 => chalk_solve::rust_ir::ClosureKind::FnOnce, _ => bug!("bad closure kind"), }, _ => bug!("bad closure kind"), @@ -530,23 +584,19 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t ) -> chalk_ir::Binders<chalk_solve::rust_ir::FnDefInputsAndOutputDatum<RustInterner<'tcx>>> { let sig = &substs.as_slice(&self.interner)[substs.len(&self.interner) - 2]; - match sig.assert_ty_ref(&self.interner).data(&self.interner) { - chalk_ir::TyData::Function(f) => { + match sig.assert_ty_ref(&self.interner).kind(&self.interner) { + chalk_ir::TyKind::Function(f) => { let substitution = f.substitution.as_slice(&self.interner); let return_type = substitution.last().unwrap().assert_ty_ref(&self.interner).clone(); // Closure arguments are tupled let argument_tuple = substitution[0].assert_ty_ref(&self.interner); - let argument_types = match argument_tuple.data(&self.interner) { - chalk_ir::TyData::Apply(apply) => match apply.name { - chalk_ir::TypeName::Tuple(_) => apply - .substitution - .iter(&self.interner) - .map(|arg| arg.assert_ty_ref(&self.interner)) - .cloned() - .collect(), - _ => bug!("Expecting closure FnSig args to be tupled."), - }, + let argument_types = match argument_tuple.kind(&self.interner) { + chalk_ir::TyKind::Tuple(_len, substitution) => substitution + .iter(&self.interner) + .map(|arg| arg.assert_ty_ref(&self.interner)) + .cloned() + .collect(), _ => bug!("Expecting closure FnSig args to be tupled."), }; @@ -637,7 +687,7 @@ fn binders_for<'tcx>( bound_vars.iter().map(|arg| match arg.unpack() { ty::subst::GenericArgKind::Lifetime(_re) => chalk_ir::VariableKind::Lifetime, ty::subst::GenericArgKind::Type(_ty) => { - chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General) + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General) } ty::subst::GenericArgKind::Const(c) => { chalk_ir::VariableKind::Const(c.ty.lower_into(interner)) diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 01c4dd12487..c4e2c7f839d 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -31,11 +31,12 @@ //! not. To lower anything wrapped in a `Binder`, we first deeply find any bound //! variables from the current `Binder`. +use rustc_ast::ast; use rustc_middle::traits::{ChalkEnvironmentAndGoal, ChalkRustInterner as RustInterner}; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{ - self, Binder, BoundRegion, Region, RegionKind, Ty, TyCtxt, TyKind, TypeFoldable, TypeVisitor, + self, Binder, BoundRegion, Region, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor, }; use rustc_span::def_id::DefId; @@ -240,24 +241,16 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq<RustInterner<'tcx>>> impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> { fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Ty<RustInterner<'tcx>> { - use chalk_ir::TyData; use rustc_ast as ast; - use TyKind::*; - let empty = || chalk_ir::Substitution::empty(interner); - let struct_ty = - |def_id| chalk_ir::TypeName::Adt(chalk_ir::AdtId(interner.tcx.adt_def(def_id))); - let apply = |name, substitution| { - TyData::Apply(chalk_ir::ApplicationTy { name, substitution }).intern(interner) - }; - let int = |i| apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Int(i)), empty()); - let uint = |i| apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Uint(i)), empty()); - let float = |f| apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Float(f)), empty()); + let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)); + let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)); + let float = |f| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Float(f)); match *self.kind() { - Bool => apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Bool), empty()), - Char => apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Char), empty()), - Int(ty) => match ty { + ty::Bool => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Bool), + ty::Char => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Char), + ty::Int(ty) => match ty { ast::IntTy::Isize => int(chalk_ir::IntTy::Isize), ast::IntTy::I8 => int(chalk_ir::IntTy::I8), ast::IntTy::I16 => int(chalk_ir::IntTy::I16), @@ -265,7 +258,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> { ast::IntTy::I64 => int(chalk_ir::IntTy::I64), ast::IntTy::I128 => int(chalk_ir::IntTy::I128), }, - Uint(ty) => match ty { + ty::Uint(ty) => match ty { ast::UintTy::Usize => uint(chalk_ir::UintTy::Usize), ast::UintTy::U8 => uint(chalk_ir::UintTy::U8), ast::UintTy::U16 => uint(chalk_ir::UintTy::U16), @@ -273,80 +266,35 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> { ast::UintTy::U64 => uint(chalk_ir::UintTy::U64), ast::UintTy::U128 => uint(chalk_ir::UintTy::U128), }, - Float(ty) => match ty { + ty::Float(ty) => match ty { ast::FloatTy::F32 => float(chalk_ir::FloatTy::F32), ast::FloatTy::F64 => float(chalk_ir::FloatTy::F64), }, - Adt(def, substs) => apply(struct_ty(def.did), substs.lower_into(interner)), - Foreign(def_id) => apply(chalk_ir::TypeName::Foreign(ForeignDefId(def_id)), empty()), - Str => apply(chalk_ir::TypeName::Str, empty()), - Array(ty, len) => { - let value = match len.val { - ty::ConstKind::Value(val) => { - chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: val }) - } - ty::ConstKind::Bound(db, bound) => { - chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new( - chalk_ir::DebruijnIndex::new(db.as_u32()), - bound.index(), - )) - } - _ => unimplemented!("Const not implemented. {:?}", len.val), - }; - apply( - chalk_ir::TypeName::Array, - chalk_ir::Substitution::from_iter( - interner, - &[ - chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), - chalk_ir::GenericArgData::Const( - chalk_ir::ConstData { ty: len.ty.lower_into(interner), value } - .intern(interner), - ) - .intern(interner), - ], - ), - ) + ty::Adt(def, substs) => { + chalk_ir::TyKind::Adt(chalk_ir::AdtId(def), substs.lower_into(interner)) } - Slice(ty) => apply( - chalk_ir::TypeName::Slice, - chalk_ir::Substitution::from1( - interner, - chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), - ), - ), - RawPtr(ptr) => { - let name = match ptr.mutbl { - ast::Mutability::Mut => chalk_ir::TypeName::Raw(chalk_ir::Mutability::Mut), - ast::Mutability::Not => chalk_ir::TypeName::Raw(chalk_ir::Mutability::Not), - }; - apply(name, chalk_ir::Substitution::from1(interner, ptr.ty.lower_into(interner))) + ty::Foreign(def_id) => chalk_ir::TyKind::Foreign(ForeignDefId(def_id)), + ty::Str => chalk_ir::TyKind::Str, + ty::Array(ty, len) => { + chalk_ir::TyKind::Array(ty.lower_into(interner), len.lower_into(interner)) } - Ref(region, ty, mutability) => { - let name = match mutability { - ast::Mutability::Mut => chalk_ir::TypeName::Ref(chalk_ir::Mutability::Mut), - ast::Mutability::Not => chalk_ir::TypeName::Ref(chalk_ir::Mutability::Not), - }; - apply( - name, - chalk_ir::Substitution::from_iter( - interner, - &[ - chalk_ir::GenericArgData::Lifetime(region.lower_into(interner)) - .intern(interner), - chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), - ], - ), - ) + ty::Slice(ty) => chalk_ir::TyKind::Slice(ty.lower_into(interner)), + + ty::RawPtr(ptr) => { + chalk_ir::TyKind::Raw(ptr.mutbl.lower_into(interner), ptr.ty.lower_into(interner)) } - FnDef(def_id, substs) => apply( - chalk_ir::TypeName::FnDef(chalk_ir::FnDefId(def_id)), - substs.lower_into(interner), + ty::Ref(region, ty, mutability) => chalk_ir::TyKind::Ref( + mutability.lower_into(interner), + region.lower_into(interner), + ty.lower_into(interner), ), - FnPtr(sig) => { + ty::FnDef(def_id, substs) => { + chalk_ir::TyKind::FnDef(chalk_ir::FnDefId(def_id), substs.lower_into(interner)) + } + ty::FnPtr(sig) => { let (inputs_and_outputs, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, &sig.inputs_and_output()); - TyData::Function(chalk_ir::FnPointer { + chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders: binders.len(interner), sig: sig.lower_into(interner), substitution: chalk_ir::Substitution::from_iter( @@ -356,148 +304,115 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> { }), ), }) - .intern(interner) } - Dynamic(predicates, region) => TyData::Dyn(chalk_ir::DynTy { + ty::Dynamic(predicates, region) => chalk_ir::TyKind::Dyn(chalk_ir::DynTy { bounds: predicates.lower_into(interner), lifetime: region.lower_into(interner), - }) - .intern(interner), - Closure(def_id, substs) => apply( - chalk_ir::TypeName::Closure(chalk_ir::ClosureId(def_id)), - substs.lower_into(interner), - ), - Generator(_def_id, _substs, _) => unimplemented!(), - GeneratorWitness(_) => unimplemented!(), - Never => apply(chalk_ir::TypeName::Never, empty()), - Tuple(substs) => { - apply(chalk_ir::TypeName::Tuple(substs.len()), substs.lower_into(interner)) + }), + ty::Closure(def_id, substs) => { + chalk_ir::TyKind::Closure(chalk_ir::ClosureId(def_id), substs.lower_into(interner)) } - Projection(proj) => TyData::Alias(proj.lower_into(interner)).intern(interner), - Opaque(def_id, substs) => { - TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { + ty::Generator(_def_id, _substs, _) => unimplemented!(), + ty::GeneratorWitness(_) => unimplemented!(), + ty::Never => chalk_ir::TyKind::Never, + ty::Tuple(substs) => chalk_ir::TyKind::Tuple(substs.len(), substs.lower_into(interner)), + ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)), + ty::Opaque(def_id, substs) => { + chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { opaque_ty_id: chalk_ir::OpaqueTyId(def_id), substitution: substs.lower_into(interner), })) - .intern(interner) } // This should have been done eagerly prior to this, and all Params // should have been substituted to placeholders - Param(_) => panic!("Lowering Param when not expected."), - Bound(db, bound) => TyData::BoundVar(chalk_ir::BoundVar::new( + ty::Param(_) => panic!("Lowering Param when not expected."), + ty::Bound(db, bound) => chalk_ir::TyKind::BoundVar(chalk_ir::BoundVar::new( chalk_ir::DebruijnIndex::new(db.as_u32()), bound.var.index(), - )) - .intern(interner), - Placeholder(_placeholder) => TyData::Placeholder(chalk_ir::PlaceholderIndex { - ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() }, - idx: _placeholder.name.as_usize(), - }) - .intern(interner), - Infer(_infer) => unimplemented!(), - Error(_) => apply(chalk_ir::TypeName::Error, empty()), + )), + ty::Placeholder(_placeholder) => { + chalk_ir::TyKind::Placeholder(chalk_ir::PlaceholderIndex { + ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() }, + idx: _placeholder.name.as_usize(), + }) + } + ty::Infer(_infer) => unimplemented!(), + ty::Error(_) => chalk_ir::TyKind::Error, } + .intern(interner) } } impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> { fn lower_into(self, interner: &RustInterner<'tcx>) -> Ty<'tcx> { - use chalk_ir::TyData; - use rustc_ast::ast; + use chalk_ir::TyKind; - let kind = match self.data(interner) { - TyData::Apply(application_ty) => match application_ty.name { - chalk_ir::TypeName::Adt(struct_id) => { - ty::Adt(struct_id.0, application_ty.substitution.lower_into(interner)) - } - chalk_ir::TypeName::Scalar(scalar) => match scalar { - chalk_ir::Scalar::Bool => ty::Bool, - chalk_ir::Scalar::Char => ty::Char, - chalk_ir::Scalar::Int(int_ty) => match int_ty { - chalk_ir::IntTy::Isize => ty::Int(ast::IntTy::Isize), - chalk_ir::IntTy::I8 => ty::Int(ast::IntTy::I8), - chalk_ir::IntTy::I16 => ty::Int(ast::IntTy::I16), - chalk_ir::IntTy::I32 => ty::Int(ast::IntTy::I32), - chalk_ir::IntTy::I64 => ty::Int(ast::IntTy::I64), - chalk_ir::IntTy::I128 => ty::Int(ast::IntTy::I128), - }, - chalk_ir::Scalar::Uint(int_ty) => match int_ty { - chalk_ir::UintTy::Usize => ty::Uint(ast::UintTy::Usize), - chalk_ir::UintTy::U8 => ty::Uint(ast::UintTy::U8), - chalk_ir::UintTy::U16 => ty::Uint(ast::UintTy::U16), - chalk_ir::UintTy::U32 => ty::Uint(ast::UintTy::U32), - chalk_ir::UintTy::U64 => ty::Uint(ast::UintTy::U64), - chalk_ir::UintTy::U128 => ty::Uint(ast::UintTy::U128), - }, - chalk_ir::Scalar::Float(float_ty) => match float_ty { - chalk_ir::FloatTy::F32 => ty::Float(ast::FloatTy::F32), - chalk_ir::FloatTy::F64 => ty::Float(ast::FloatTy::F64), - }, + let kind = match self.kind(interner) { + TyKind::Adt(struct_id, substitution) => { + ty::Adt(struct_id.0, substitution.lower_into(interner)) + } + TyKind::Scalar(scalar) => match scalar { + chalk_ir::Scalar::Bool => ty::Bool, + chalk_ir::Scalar::Char => ty::Char, + chalk_ir::Scalar::Int(int_ty) => match int_ty { + chalk_ir::IntTy::Isize => ty::Int(ast::IntTy::Isize), + chalk_ir::IntTy::I8 => ty::Int(ast::IntTy::I8), + chalk_ir::IntTy::I16 => ty::Int(ast::IntTy::I16), + chalk_ir::IntTy::I32 => ty::Int(ast::IntTy::I32), + chalk_ir::IntTy::I64 => ty::Int(ast::IntTy::I64), + chalk_ir::IntTy::I128 => ty::Int(ast::IntTy::I128), + }, + chalk_ir::Scalar::Uint(int_ty) => match int_ty { + chalk_ir::UintTy::Usize => ty::Uint(ast::UintTy::Usize), + chalk_ir::UintTy::U8 => ty::Uint(ast::UintTy::U8), + chalk_ir::UintTy::U16 => ty::Uint(ast::UintTy::U16), + chalk_ir::UintTy::U32 => ty::Uint(ast::UintTy::U32), + chalk_ir::UintTy::U64 => ty::Uint(ast::UintTy::U64), + chalk_ir::UintTy::U128 => ty::Uint(ast::UintTy::U128), + }, + chalk_ir::Scalar::Float(float_ty) => match float_ty { + chalk_ir::FloatTy::F32 => ty::Float(ast::FloatTy::F32), + chalk_ir::FloatTy::F64 => ty::Float(ast::FloatTy::F64), }, - chalk_ir::TypeName::Array => { - let substs = application_ty.substitution.as_slice(interner); - let ty = substs[0].assert_ty_ref(interner).lower_into(interner); - let c = substs[1].assert_const_ref(interner).lower_into(interner); - ty::Array(ty, interner.tcx.mk_const(c)) - } - chalk_ir::TypeName::FnDef(id) => { - ty::FnDef(id.0, application_ty.substitution.lower_into(interner)) - } - chalk_ir::TypeName::Closure(closure) => { - ty::Closure(closure.0, application_ty.substitution.lower_into(interner)) - } - chalk_ir::TypeName::Generator(_) => unimplemented!(), - chalk_ir::TypeName::GeneratorWitness(_) => unimplemented!(), - chalk_ir::TypeName::Never => ty::Never, - chalk_ir::TypeName::Tuple(_size) => { - ty::Tuple(application_ty.substitution.lower_into(interner)) - } - chalk_ir::TypeName::Slice => ty::Slice( - application_ty.substitution.as_slice(interner)[0] - .ty(interner) - .unwrap() - .lower_into(interner), - ), - chalk_ir::TypeName::Raw(mutbl) => ty::RawPtr(ty::TypeAndMut { - ty: application_ty.substitution.as_slice(interner)[0] - .ty(interner) - .unwrap() - .lower_into(interner), - mutbl: match mutbl { - chalk_ir::Mutability::Mut => ast::Mutability::Mut, - chalk_ir::Mutability::Not => ast::Mutability::Not, - }, - }), - chalk_ir::TypeName::Ref(mutbl) => ty::Ref( - application_ty.substitution.as_slice(interner)[0] - .lifetime(interner) - .unwrap() - .lower_into(interner), - application_ty.substitution.as_slice(interner)[1] - .ty(interner) - .unwrap() - .lower_into(interner), - match mutbl { - chalk_ir::Mutability::Mut => ast::Mutability::Mut, - chalk_ir::Mutability::Not => ast::Mutability::Not, - }, - ), - chalk_ir::TypeName::Str => ty::Str, - chalk_ir::TypeName::OpaqueType(opaque_ty) => { - ty::Opaque(opaque_ty.0, application_ty.substitution.lower_into(interner)) - } - chalk_ir::TypeName::AssociatedType(assoc_ty) => ty::Projection(ty::ProjectionTy { - substs: application_ty.substitution.lower_into(interner), - item_def_id: assoc_ty.0, - }), - chalk_ir::TypeName::Foreign(def_id) => ty::Foreign(def_id.0), - chalk_ir::TypeName::Error => unimplemented!(), }, - TyData::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder { + TyKind::Array(ty, c) => { + let ty = ty.lower_into(interner); + let c = c.lower_into(interner); + ty::Array(ty, interner.tcx.mk_const(c)) + } + TyKind::FnDef(id, substitution) => ty::FnDef(id.0, substitution.lower_into(interner)), + TyKind::Closure(closure, substitution) => { + ty::Closure(closure.0, substitution.lower_into(interner)) + } + TyKind::Generator(..) => unimplemented!(), + TyKind::GeneratorWitness(..) => unimplemented!(), + TyKind::Never => ty::Never, + TyKind::Tuple(_len, substitution) => ty::Tuple(substitution.lower_into(interner)), + TyKind::Slice(ty) => ty::Slice(ty.lower_into(interner)), + TyKind::Raw(mutbl, ty) => ty::RawPtr(ty::TypeAndMut { + ty: ty.lower_into(interner), + mutbl: mutbl.lower_into(interner), + }), + TyKind::Ref(mutbl, lifetime, ty) => ty::Ref( + lifetime.lower_into(interner), + ty.lower_into(interner), + mutbl.lower_into(interner), + ), + TyKind::Str => ty::Str, + TyKind::OpaqueType(opaque_ty, substitution) => { + ty::Opaque(opaque_ty.0, substitution.lower_into(interner)) + } + TyKind::AssociatedType(assoc_ty, substitution) => ty::Projection(ty::ProjectionTy { + substs: substitution.lower_into(interner), + item_def_id: assoc_ty.0, + }), + TyKind::Foreign(def_id) => ty::Foreign(def_id.0), + TyKind::Error => return interner.tcx.ty_error(), + TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder { universe: ty::UniverseIndex::from_usize(placeholder.ui.counter), name: ty::BoundVar::from_usize(placeholder.idx), }), - chalk_ir::TyData::Alias(alias_ty) => match alias_ty { + TyKind::Alias(alias_ty) => match alias_ty { chalk_ir::AliasTy::Projection(projection) => ty::Projection(ty::ProjectionTy { item_def_id: projection.associated_ty_id.0, substs: projection.substitution.lower_into(interner), @@ -506,16 +421,16 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> { ty::Opaque(opaque.opaque_ty_id.0, opaque.substitution.lower_into(interner)) } }, - TyData::Function(_quantified_ty) => unimplemented!(), - TyData::BoundVar(_bound) => ty::Bound( + TyKind::Function(_quantified_ty) => unimplemented!(), + TyKind::BoundVar(_bound) => ty::Bound( ty::DebruijnIndex::from_usize(_bound.debruijn.depth() as usize), ty::BoundTy { var: ty::BoundVar::from_usize(_bound.index), kind: ty::BoundTyKind::Anon, }, ), - TyData::InferenceVar(_, _) => unimplemented!(), - TyData::Dyn(_) => unimplemented!(), + TyKind::InferenceVar(_, _) => unimplemented!(), + TyKind::Dyn(_) => unimplemented!(), }; interner.tcx.mk_ty(kind) } @@ -706,8 +621,16 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru self, interner: &RustInterner<'tcx>, ) -> chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<RustInterner<'tcx>>> { + // `Self` has one binder: + // Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>> + // The return type has two: + // Binders<&[Binders<WhereClause<I>>]> + // This means that any variables that are escaping `self` need to be + // shifted in by one so that they are still escaping. + let shifted_predicates = ty::fold::shift_vars(interner.tcx, &self, 1); + let (predicates, binders, _named_regions) = - collect_bound_vars(interner, interner.tcx, &self); + collect_bound_vars(interner, interner.tcx, &shifted_predicates); let self_ty = interner.tcx.mk_ty(ty::Bound( // This is going to be wrapped in a binder ty::DebruijnIndex::from_usize(1), @@ -716,7 +639,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru let where_clauses = predicates.into_iter().map(|predicate| match predicate { ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id, substs }) => { chalk_ir::Binders::new( - chalk_ir::VariableKinds::empty(interner), + binders.clone(), chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { trait_id: chalk_ir::TraitId(def_id), substitution: interner @@ -727,25 +650,34 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru ) } ty::ExistentialPredicate::Projection(predicate) => chalk_ir::Binders::new( - chalk_ir::VariableKinds::empty(interner), + binders.clone(), chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id), - substitution: predicate.substs.lower_into(interner), + substitution: interner + .tcx + .mk_substs_trait(self_ty, predicate.substs) + .lower_into(interner), }), ty: predicate.ty.lower_into(interner), }), ), ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new( - chalk_ir::VariableKinds::empty(interner), + binders.clone(), chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { trait_id: chalk_ir::TraitId(def_id), substitution: interner.tcx.mk_substs_trait(self_ty, &[]).lower_into(interner), }), ), }); + + // Binder for the bound variable representing the concrete underlying type. + let existential_binder = chalk_ir::VariableKinds::from1( + interner, + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), + ); let value = chalk_ir::QuantifiedWhereClauses::from_iter(interner, where_clauses); - chalk_ir::Binders::new(binders, value) + chalk_ir::Binders::new(existential_binder, value) } } @@ -818,6 +750,35 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>>> } } +impl<'tcx> LowerInto<'tcx, chalk_ir::Mutability> for ast::Mutability { + fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_ir::Mutability { + match self { + rustc_ast::Mutability::Mut => chalk_ir::Mutability::Mut, + rustc_ast::Mutability::Not => chalk_ir::Mutability::Not, + } + } +} + +impl<'tcx> LowerInto<'tcx, ast::Mutability> for chalk_ir::Mutability { + fn lower_into(self, _interner: &RustInterner<'tcx>) -> ast::Mutability { + match self { + chalk_ir::Mutability::Mut => ast::Mutability::Mut, + chalk_ir::Mutability::Not => ast::Mutability::Not, + } + } +} + +impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::Polarity> for ty::ImplPolarity { + fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity { + match self { + ty::ImplPolarity::Positive => chalk_solve::rust_ir::Polarity::Positive, + ty::ImplPolarity::Negative => chalk_solve::rust_ir::Polarity::Negative, + // FIXME(chalk) reservation impls + ty::ImplPolarity::Reservation => chalk_solve::rust_ir::Polarity::Negative, + } + } +} + impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>>> for ty::ProjectionPredicate<'tcx> { @@ -910,7 +871,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { match self.parameters.entry(bound_ty.var.as_u32()) { Entry::Vacant(entry) => { - entry.insert(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)); + entry.insert(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)); } Entry::Occupied(entry) => match entry.get() { chalk_ir::VariableKind::Ty(_) => {} diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs index f174a92274e..b117e28875e 100644 --- a/compiler/rustc_traits/src/chalk/mod.rs +++ b/compiler/rustc_traits/src/chalk/mod.rs @@ -69,15 +69,15 @@ crate fn evaluate_goal<'tcx>( CanonicalVarKind::PlaceholderRegion(_ui) => unimplemented!(), CanonicalVarKind::Ty(ty) => match ty { CanonicalTyVarKind::General(ui) => chalk_ir::WithKind::new( - chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General), + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), chalk_ir::UniverseIndex { counter: ui.index() }, ), CanonicalTyVarKind::Int => chalk_ir::WithKind::new( - chalk_ir::VariableKind::Ty(chalk_ir::TyKind::Integer), + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::Integer), chalk_ir::UniverseIndex::root(), ), CanonicalTyVarKind::Float => chalk_ir::WithKind::new( - chalk_ir::VariableKind::Ty(chalk_ir::TyKind::Float), + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::Float), chalk_ir::UniverseIndex::root(), ), }, @@ -97,7 +97,8 @@ crate fn evaluate_goal<'tcx>( use chalk_solve::Solver; let mut solver = chalk_engine::solve::SLGSolver::new(32, None); let db = ChalkRustIrDatabase { interner, reempty_placeholder }; - let solution = chalk_solve::logging::with_tracing_logs(|| solver.solve(&db, &lowered_goal)); + let solution = solver.solve(&db, &lowered_goal); + debug!(?obligation, ?solution, "evaluatate goal"); // Ideally, the code to convert *back* to rustc types would live close to // the code to convert *from* rustc types. Right now though, we don't diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 324aa1a66a6..af19ad08c1d 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -718,39 +718,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - fn is_destructuring_place_expr(&self, expr: &'tcx hir::Expr<'tcx>) -> bool { - match &expr.kind { - ExprKind::Array(comps) | ExprKind::Tup(comps) => { - comps.iter().all(|e| self.is_destructuring_place_expr(e)) - } - ExprKind::Struct(_path, fields, rest) => { - rest.as_ref().map(|e| self.is_destructuring_place_expr(e)).unwrap_or(true) - && fields.iter().all(|f| self.is_destructuring_place_expr(&f.expr)) - } - _ => expr.is_syntactic_place_expr(), - } - } - pub(crate) fn check_lhs_assignable( &self, lhs: &'tcx hir::Expr<'tcx>, err_code: &'static str, expr_span: &Span, ) { - if !lhs.is_syntactic_place_expr() { - // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set. - let mut err = self.tcx.sess.struct_span_err_with_code( - *expr_span, - "invalid left-hand side of assignment", - DiagnosticId::Error(err_code.into()), - ); - err.span_label(lhs.span, "cannot assign to this expression"); - if self.is_destructuring_place_expr(lhs) { - err.note("destructuring assignments are not currently supported"); - err.note("for more information, see https://github.com/rust-lang/rfcs/issues/372"); - } - err.emit(); + if lhs.is_syntactic_place_expr() { + return; } + + // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set. + let mut err = self.tcx.sess.struct_span_err_with_code( + *expr_span, + "invalid left-hand side of assignment", + DiagnosticId::Error(err_code.into()), + ); + err.span_label(lhs.span, "cannot assign to this expression"); + err.emit(); } /// Type check assignment expression `expr` of form `lhs = rhs`. diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index f87e6b607d4..0bb7b464f16 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_def_id: DefId, ) -> Vec<DeferredCallResolution<'tcx>> { let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut(); - deferred_call_resolutions.remove(&closure_def_id).unwrap_or(vec![]) + deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default() } pub fn tag(&self) -> String { diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index d403e259398..713b24e583a 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::AllTraits, |probe_cx| Ok(probe_cx.candidate_method_names()), ) - .unwrap_or(vec![]); + .unwrap_or_default(); method_names .iter() .flat_map(|&method_name| { diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index f76f42dea1e..6489b7838d6 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -270,6 +270,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode { + // When we perform destructuring assignment, we disable default match bindings, which are + // unintuitive in this context. + if !pat.default_binding_modes { + return AdjustMode::Reset; + } match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index ba0f22513a1..7b31b9f3915 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -577,7 +577,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn link_pattern(&self, discr_cmt: PlaceWithHirId<'tcx>, root_pat: &hir::Pat<'_>) { debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat); ignore_err!(self.with_mc(|mc| { - mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id }| { + mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id, .. }| { // `ref x` pattern if let PatKind::Binding(..) = kind { if let Some(ty::BindByReference(mutbl)) = diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index f014ea3d5a9..b431de90369 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2653,7 +2653,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>(); match segments.as_slice() { [sym::arm, sym::a32] | [sym::arm, sym::t32] => { - if !tcx.sess.target.options.has_thumb_interworking { + if !tcx.sess.target.has_thumb_interworking { struct_span_err!( tcx.sess.diagnostic(), attr.span, diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 9c29ceeb593..e596dd1a396 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -61,23 +61,23 @@ fn opaque_type_bounds<'tcx>( bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { - let item_ty = - tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); + ty::print::with_no_queries(|| { + let item_ty = + tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); - let bounds = ty::print::with_no_queries(|| { - AstConv::compute_bounds( + let bounds = AstConv::compute_bounds( &ItemCtxt::new(tcx, opaque_def_id), item_ty, bounds, SizedByDefault::Yes, span, ) - }); + .predicates(tcx, item_ty); - let bounds = bounds.predicates(tcx, item_ty); - debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); + debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); - tcx.arena.alloc_slice(&bounds) + tcx.arena.alloc_slice(&bounds) + }) } pub(super) fn explicit_item_bounds( diff --git a/config.toml.example b/config.toml.example index 1edb390e0fe..c9e18388750 100644 --- a/config.toml.example +++ b/config.toml.example @@ -138,6 +138,9 @@ changelog-seen = 2 # Whether or not to specify `-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=YES` #allow-old-toolchain = false +# Whether to include the Polly optimizer. +#polly = false + # ============================================================================= # General build configuration options # ============================================================================= @@ -583,6 +586,15 @@ changelog-seen = 2 # build native code. #android-ndk = "/path/to/ndk" +# Build the sanitizer runtimes for this target. +# This option will override the same option under [build] section. +#sanitizers = false + +# Build the profiler runtime for this target(required when compiling with options that depend +# on this runtime, such as `-C profile-generate` or `-Z instrument-coverage`). +# This option will override the same option under [build] section. +#profiler = false + # Force static or dynamic linkage of the standard library for this target. If # this target is a host for rustc, this will also affect the linkage of the # compiler itself. This is useful for building rustc on targets that normally diff --git a/library/alloc/src/collections/btree/append.rs b/library/alloc/src/collections/btree/append.rs new file mode 100644 index 00000000000..e0362b2f37d --- /dev/null +++ b/library/alloc/src/collections/btree/append.rs @@ -0,0 +1,124 @@ +use super::map::MIN_LEN; +use super::merge_iter::MergeIterInner; +use super::node::{self, ForceResult::*, Root}; +use core::iter::FusedIterator; + +impl<K, V> Root<K, V> { + /// Appends all key-value pairs from the union of two ascending iterators, + /// incrementing a `length` variable along the way. The latter makes it + /// easier for the caller to avoid a leak when a drop handler panicks. + /// + /// If both iterators produce the same key, this method drops the pair from + /// the left iterator and appends the pair from the right iterator. + /// + /// If you want the tree to end up in a strictly ascending order, like for + /// a `BTreeMap`, both iterators should produce keys in strictly ascending + /// order, each greater than all keys in the tree, including any keys + /// already in the tree upon entry. + pub fn append_from_sorted_iters<I>(&mut self, left: I, right: I, length: &mut usize) + where + K: Ord, + I: Iterator<Item = (K, V)> + FusedIterator, + { + // We prepare to merge `left` and `right` into a sorted sequence in linear time. + let iter = MergeIter(MergeIterInner::new(left, right)); + + // Meanwhile, we build a tree from the sorted sequence in linear time. + self.bulk_push(iter, length) + } + + /// Pushes all key-value pairs to the end of the tree, incrementing a + /// `length` variable along the way. The latter makes it easier for the + /// caller to avoid a leak when the iterator panicks. + fn bulk_push<I>(&mut self, iter: I, length: &mut usize) + where + I: Iterator<Item = (K, V)>, + { + let mut cur_node = self.node_as_mut().last_leaf_edge().into_node(); + // Iterate through all key-value pairs, pushing them into nodes at the right level. + for (key, value) in iter { + // Try to push key-value pair into the current leaf node. + if cur_node.len() < node::CAPACITY { + cur_node.push(key, value); + } else { + // No space left, go up and push there. + let mut open_node; + let mut test_node = cur_node.forget_type(); + loop { + match test_node.ascend() { + Ok(parent) => { + let parent = parent.into_node(); + if parent.len() < node::CAPACITY { + // Found a node with space left, push here. + open_node = parent; + break; + } else { + // Go up again. + test_node = parent.forget_type(); + } + } + Err(_) => { + // We are at the top, create a new root node and push there. + open_node = self.push_internal_level(); + break; + } + } + } + + // Push key-value pair and new right subtree. + let tree_height = open_node.height() - 1; + let mut right_tree = Root::new_leaf(); + for _ in 0..tree_height { + right_tree.push_internal_level(); + } + open_node.push(key, value, right_tree); + + // Go down to the right-most leaf again. + cur_node = open_node.forget_type().last_leaf_edge().into_node(); + } + + // Increment length every iteration, to make sure the map drops + // the appended elements even if advancing the iterator panicks. + *length += 1; + } + self.fix_right_edge(); + } + + fn fix_right_edge(&mut self) { + // Handle underfull nodes, start from the top. + let mut cur_node = self.node_as_mut(); + while let Internal(internal) = cur_node.force() { + // Check if right-most child is underfull. + let mut last_edge = internal.last_edge(); + let right_child_len = last_edge.reborrow().descend().len(); + if right_child_len < MIN_LEN { + // We need to steal. + let mut last_kv = match last_edge.left_kv() { + Ok(left) => left, + Err(_) => unreachable!(), + }; + last_kv.bulk_steal_left(MIN_LEN - right_child_len); + last_edge = last_kv.right_edge(); + } + + // Go further down. + cur_node = last_edge.descend(); + } + } +} + +// An iterator for merging two sorted sequences into one +struct MergeIter<K, V, I: Iterator<Item = (K, V)>>(MergeIterInner<I>); + +impl<K: Ord, V, I> Iterator for MergeIter<K, V, I> +where + I: Iterator<Item = (K, V)> + FusedIterator, +{ + type Item = (K, V); + + /// If two keys are equal, returns the key-value pair from the right source. + fn next(&mut self) -> Option<(K, V)> { + let (a_next, b_next) = self.0.nexts(|a: &(K, V), b: &(K, V)| K::cmp(&a.0, &b.0)); + b_next.or(a_next) + } +} diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 07c23d29e20..49122f53d33 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -9,7 +9,6 @@ use core::ops::{Index, RangeBounds}; use core::ptr; use super::borrow::DormantMutRef; -use super::merge_iter::MergeIterInner; use super::node::{self, marker, ForceResult::*, Handle, NodeRef}; use super::search::{self, SearchResult::*}; use super::unwrap_unchecked; @@ -458,9 +457,6 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> { } } -// An iterator for merging two sorted sequences into one -struct MergeIter<K, V, I: Iterator<Item = (K, V)>>(MergeIterInner<I>); - impl<K: Ord, V> BTreeMap<K, V> { /// Makes a new empty BTreeMap. /// @@ -908,13 +904,10 @@ impl<K: Ord, V> BTreeMap<K, V> { return; } - // First, we merge `self` and `other` into a sorted sequence in linear time. let self_iter = mem::take(self).into_iter(); let other_iter = mem::take(other).into_iter(); - let iter = MergeIter(MergeIterInner::new(self_iter, other_iter)); - - // Second, we build a tree from the sorted sequence in linear time. - self.from_sorted_iter(iter); + let root = BTreeMap::ensure_is_owned(&mut self.root); + root.append_from_sorted_iters(self_iter, other_iter, &mut self.length) } /// Constructs a double-ended iterator over a sub-range of elements in the map. @@ -1039,78 +1032,6 @@ impl<K: Ord, V> BTreeMap<K, V> { } } - fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) { - let root = Self::ensure_is_owned(&mut self.root); - let mut cur_node = root.node_as_mut().last_leaf_edge().into_node(); - // Iterate through all key-value pairs, pushing them into nodes at the right level. - for (key, value) in iter { - // Try to push key-value pair into the current leaf node. - if cur_node.len() < node::CAPACITY { - cur_node.push(key, value); - } else { - // No space left, go up and push there. - let mut open_node; - let mut test_node = cur_node.forget_type(); - loop { - match test_node.ascend() { - Ok(parent) => { - let parent = parent.into_node(); - if parent.len() < node::CAPACITY { - // Found a node with space left, push here. - open_node = parent; - break; - } else { - // Go up again. - test_node = parent.forget_type(); - } - } - Err(_) => { - // We are at the top, create a new root node and push there. - open_node = root.push_internal_level(); - break; - } - } - } - - // Push key-value pair and new right subtree. - let tree_height = open_node.height() - 1; - let mut right_tree = node::Root::new_leaf(); - for _ in 0..tree_height { - right_tree.push_internal_level(); - } - open_node.push(key, value, right_tree); - - // Go down to the right-most leaf again. - cur_node = open_node.forget_type().last_leaf_edge().into_node(); - } - - self.length += 1; - } - Self::fix_right_edge(root) - } - - fn fix_right_edge(root: &mut node::Root<K, V>) { - // Handle underfull nodes, start from the top. - let mut cur_node = root.node_as_mut(); - while let Internal(internal) = cur_node.force() { - // Check if right-most child is underfull. - let mut last_edge = internal.last_edge(); - let right_child_len = last_edge.reborrow().descend().len(); - if right_child_len < MIN_LEN { - // We need to steal. - let mut last_kv = match last_edge.left_kv() { - Ok(left) => left, - Err(_) => unreachable!(), - }; - last_kv.bulk_steal_left(MIN_LEN - right_child_len); - last_edge = last_kv.right_edge(); - } - - // Go further down. - cur_node = last_edge.descend(); - } - } - /// Splits the collection into two at the given key. Returns everything after the given key, /// including the key. /// @@ -2220,18 +2141,5 @@ impl<K, V> BTreeMap<K, V> { } } -impl<K: Ord, V, I> Iterator for MergeIter<K, V, I> -where - I: Iterator<Item = (K, V)> + ExactSizeIterator + FusedIterator, -{ - type Item = (K, V); - - /// If two keys are equal, returns the key/value-pair from the right source. - fn next(&mut self) -> Option<(K, V)> { - let (a_next, b_next) = self.0.nexts(|a: &(K, V), b: &(K, V)| K::cmp(&a.0, &b.0)); - b_next.or(a_next) - } -} - #[cfg(test)] mod tests; diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index d5b1c600d93..dd3ebcccf76 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -42,7 +42,7 @@ fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T> } } -impl<'a, K: 'a, V: 'a> BTreeMap<K, V> { +impl<K, V> BTreeMap<K, V> { /// Panics if the map (or the code navigating it) is corrupted. fn check(&self) where @@ -54,14 +54,14 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> { assert!(root_node.ascend().is_err()); root_node.assert_back_pointers(); - let counted = root_node.assert_ascending(); - assert_eq!(self.length, counted); assert_eq!(self.length, root_node.calc_length()); root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 }); } else { assert_eq!(self.length, 0); } + + self.assert_ascending(); } /// Returns the height of the root, if any. @@ -79,10 +79,28 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> { String::from("not yet allocated") } } + + /// Asserts that the keys are in strictly ascending order. + fn assert_ascending(&self) + where + K: Copy + Debug + Ord, + { + let mut num_seen = 0; + let mut keys = self.keys(); + if let Some(mut previous) = keys.next() { + num_seen = 1; + for next in keys { + assert!(previous < next, "{:?} >= {:?}", previous, next); + previous = next; + num_seen += 1; + } + } + assert_eq!(num_seen, self.len()); + } } impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> { - pub fn assert_min_len(self, min_len: usize) { + fn assert_min_len(self, min_len: usize) { assert!(self.len() >= min_len, "{} < {}", self.len(), min_len); if let node::ForceResult::Internal(node) = self.force() { for idx in 0..=node.len() { @@ -1667,6 +1685,33 @@ create_append_test!(test_append_239, 239); #[cfg(not(miri))] // Miri is too slow create_append_test!(test_append_1700, 1700); +#[test] +fn test_append_drop_leak() { + static DROPS: AtomicUsize = AtomicUsize::new(0); + + struct D; + + impl Drop for D { + fn drop(&mut self) { + if DROPS.fetch_add(1, Ordering::SeqCst) == 0 { + panic!("panic in `drop`"); + } + } + } + + let mut left = BTreeMap::new(); + let mut right = BTreeMap::new(); + left.insert(0, D); + left.insert(1, D); // first to be dropped during append + left.insert(2, D); + right.insert(1, D); + right.insert(2, D); + + catch_unwind(move || left.append(&mut right)).unwrap_err(); + + assert_eq!(DROPS.load(Ordering::SeqCst), 4); // Rust issue #47949 ate one little piggy +} + fn rand_data(len: usize) -> Vec<(u32, u32)> { assert!(len * 2 <= 70029); // from that point on numbers repeat let mut rng = DeterministicRng::new(); diff --git a/library/alloc/src/collections/btree/merge_iter.rs b/library/alloc/src/collections/btree/merge_iter.rs index 88e6f86c2c6..7f23d93b990 100644 --- a/library/alloc/src/collections/btree/merge_iter.rs +++ b/library/alloc/src/collections/btree/merge_iter.rs @@ -2,27 +2,25 @@ use core::cmp::Ordering; use core::fmt::{self, Debug}; use core::iter::FusedIterator; -/// Core of an iterator that merges the output of two ascending iterators, +/// Core of an iterator that merges the output of two strictly ascending iterators, /// for instance a union or a symmetric difference. -pub struct MergeIterInner<I> -where - I: Iterator, -{ +pub struct MergeIterInner<I: Iterator> { a: I, b: I, peeked: Option<Peeked<I>>, } -/// Benchmarks faster than wrapping both iterators in a Peekable. +/// Benchmarks faster than wrapping both iterators in a Peekable, +/// probably because we can afford to impose a FusedIterator bound. #[derive(Clone, Debug)] enum Peeked<I: Iterator> { A(I::Item), B(I::Item), } -impl<I> Clone for MergeIterInner<I> +impl<I: Iterator> Clone for MergeIterInner<I> where - I: Clone + Iterator, + I: Clone, I::Item: Clone, { fn clone(&self) -> Self { @@ -30,20 +28,17 @@ where } } -impl<I> Debug for MergeIterInner<I> +impl<I: Iterator> Debug for MergeIterInner<I> where - I: Iterator + Debug, + I: Debug, I::Item: Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("MergeIterInner").field(&self.a).field(&self.b).finish() + f.debug_tuple("MergeIterInner").field(&self.a).field(&self.b).field(&self.peeked).finish() } } -impl<I> MergeIterInner<I> -where - I: ExactSizeIterator + FusedIterator, -{ +impl<I: Iterator> MergeIterInner<I> { /// Creates a new core for an iterator merging a pair of sources. pub fn new(a: I, b: I) -> Self { MergeIterInner { a, b, peeked: None } @@ -52,13 +47,17 @@ where /// Returns the next pair of items stemming from the pair of sources /// being merged. If both returned options contain a value, that value /// is equal and occurs in both sources. If one of the returned options - /// contains a value, that value doesn't occur in the other source. - /// If neither returned option contains a value, iteration has finished - /// and subsequent calls will return the same empty pair. + /// contains a value, that value doesn't occur in the other source (or + /// the sources are not strictly ascending). If neither returned option + /// contains a value, iteration has finished and subsequent calls will + /// return the same empty pair. pub fn nexts<Cmp: Fn(&I::Item, &I::Item) -> Ordering>( &mut self, cmp: Cmp, - ) -> (Option<I::Item>, Option<I::Item>) { + ) -> (Option<I::Item>, Option<I::Item>) + where + I: FusedIterator, + { let mut a_next; let mut b_next; match self.peeked.take() { @@ -86,7 +85,10 @@ where } /// Returns a pair of upper bounds for the `size_hint` of the final iterator. - pub fn lens(&self) -> (usize, usize) { + pub fn lens(&self) -> (usize, usize) + where + I: ExactSizeIterator, + { match self.peeked { Some(Peeked::A(_)) => (1 + self.a.len(), self.b.len()), Some(Peeked::B(_)) => (self.a.len(), 1 + self.b.len()), diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index 7bf1706dd6d..ebcbb0e467c 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -1,3 +1,4 @@ +mod append; mod borrow; pub mod map; mod mem; diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index c8d3de9e5cd..dbf9031620e 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -32,7 +32,6 @@ use core::cmp::Ordering; use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; use core::ptr::{self, NonNull, Unique}; -use core::slice; use crate::alloc::{AllocRef, Global, Layout}; use crate::boxed::Box; @@ -120,11 +119,11 @@ struct BoxedNode<K, V> { impl<K, V> BoxedNode<K, V> { fn from_leaf(node: Box<LeafNode<K, V>>) -> Self { - BoxedNode { ptr: Box::into_unique(node).0 } + BoxedNode { ptr: Unique::from(Box::leak(node)) } } fn from_internal(node: Box<InternalNode<K, V>>) -> Self { - BoxedNode { ptr: Unique::from(&mut Box::leak(node).data) } + BoxedNode { ptr: Unique::from(Box::leak(node)).cast() } } fn as_ptr(&self) -> NonNull<LeafNode<K, V>> { @@ -189,6 +188,11 @@ impl<K, V> Root<K, V> { NodeRef { height: self.height, node: self.node.as_ptr(), _marker: PhantomData } } + /// Packs the reference, aware of type and height, into a type-agnostic pointer. + fn into_boxed_node(self) -> BoxedNode<K, V> { + self.node + } + /// Adds a new internal node with a single edge pointing to the previous root node, /// make that new node the root node, and return it. This increases the height by 1 /// and is the opposite of `pop_internal_level`. @@ -218,15 +222,16 @@ impl<K, V> Root<K, V> { pub fn pop_internal_level(&mut self) { assert!(self.height > 0); - let top = self.node.ptr; + let top = BoxedNode::as_ptr(&self.node); let mut internal_node = unsafe { self.internal_node_as_mut() }; - self.node = unsafe { internal_node.as_internal_mut().edges[0].assume_init_read() }; + let internal_node = NodeRef::as_internal_mut(&mut internal_node); + self.node = unsafe { internal_node.edges[0].assume_init_read() }; self.height -= 1; - self.node_as_mut().as_leaf_mut().parent = None; + self.node_as_mut().clear_parent_link(); unsafe { - Global.dealloc(NonNull::from(top).cast(), Layout::new::<InternalNode<K, V>>()); + Global.dealloc(top.cast(), Layout::new::<InternalNode<K, V>>()); } } } @@ -236,21 +241,49 @@ impl<K, V> Root<K, V> { // internal use of `NodeRef` because we stay completely generic over `K` and `V`. // However, whenever a public type wraps `NodeRef`, make sure that it has the // correct variance. +/// /// A reference to a node. /// /// This type has a number of parameters that controls how it acts: -/// - `BorrowType`: This can be `Immut<'a>`, `Mut<'a>` or `ValMut<'a>' for some `'a` -/// or `Owned`. -/// When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`, -/// when this is `Mut<'a>`, the `NodeRef` acts roughly like `&'a mut Node`, -/// when this is `ValMut<'a>`, the `NodeRef` acts as immutable with respect -/// to keys and tree structure, but allows mutable references to values, -/// and when this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`. -/// - `K` and `V`: These control what types of things are stored in the nodes. +/// - `BorrowType`: A dummy type that describes the kind of borrow and carries a lifetime. +/// - When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`. +/// - When this is `ValMut<'a>`, the `NodeRef` acts roughly like `&'a Node` +/// with respect to keys and tree structure, but also allows many +/// mutable references to values throughout the tree to coexist. +/// - When this is `Mut<'a>`, the `NodeRef` acts roughly like `&'a mut Node`, +/// although insert methods allow a mutable pointer to a value to coexist. +/// - When this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`, +/// but does not have a destructor, and must be cleaned up manually. +/// - `K` and `V`: These are the types of keys and values stored in the nodes. /// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is /// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the /// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the /// `NodeRef` could be pointing to either type of node. +/// `Type` is named `NodeType` when used outside `NodeRef`. +/// +/// Both `BorrowType` and `NodeType` restrict what methods we implement, to +/// exploit static type safety. There are limitations in the way we can apply +/// such restrictions: +/// - For each type parameter, we can only define a method either generically +/// or for one particular type. For example, we cannot define a method like +/// `key_at` generically for all `BorrowType`, because we want to return +/// `&'a K` for most choices of `BorrowType`, but plain `K` for `Owned`. +/// We cannot define `key_at` once for all types that have a lifetime. +/// Therefore, we define it only for the least powerful type `Immut<'a>`. +/// - We cannot get implicit coercion from say `Mut<'a>` to `Immut<'a>`. +/// Therefore, we have to explicitly call `reborrow` on a more powerfull +/// `NodeRef` in order to reach a method like `key_at`. +/// - All methods on `NodeRef` that return some kind of reference, except +/// `reborrow` and `reborrow_mut`, take `self` by value and not by reference. +/// This avoids silently returning a second reference somewhere in the tree. +/// That is irrelevant when `BorrowType` is `Immut<'a>`, but the rule does +/// no harm because we make those `NodeRef` implicitly `Copy`. +/// The rule also avoids implicitly returning the lifetime of `&self`, +/// instead of the lifetime contained in `BorrowType`. +/// An exception to this rule are the insert functions. +/// - Given the above, we need a `reborrow_mut` to explicitly copy a `Mut<'a>` +/// `NodeRef` whenever we want to invoke a method returning an extra reference +/// somewhere in the tree. pub struct NodeRef<BorrowType, K, V, Type> { /// The number of levels below the node, a property of the node that cannot be /// entirely described by `Type` and that the node does not store itself either. @@ -277,30 +310,45 @@ unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::Mut<' unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::ValMut<'a>, K, V, Type> {} unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Owned, K, V, Type> {} +impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> { + /// Unpack a node reference that was packed by `Root::into_boxed_node`. + fn from_boxed_node(boxed_node: BoxedNode<K, V>, height: usize) -> Self { + NodeRef { height, node: boxed_node.as_ptr(), _marker: PhantomData } + } +} + +impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> { + /// Unpack a node reference that was packed as `NodeRef::parent`. + fn from_internal(node: NonNull<InternalNode<K, V>>, height: usize) -> Self { + debug_assert!(height > 0); + NodeRef { height, node: node.cast(), _marker: PhantomData } + } +} + impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> { - /// Exposes the data of an internal node for reading. + /// Exposes the data of an internal node. /// - /// Returns a raw ptr to avoid invalidating other references to this node, - /// which is possible when BorrowType is marker::ValMut. - fn as_internal_ptr(&self) -> *const InternalNode<K, V> { - self.node.as_ptr() as *const InternalNode<K, V> + /// Returns a raw ptr to avoid invalidating other references to this node. + fn as_internal_ptr(this: &Self) -> *mut InternalNode<K, V> { + // SAFETY: the static node type is `Internal`. + this.node.as_ptr() as *mut InternalNode<K, V> } } -impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { - /// Exposes the data of an internal node for reading, - /// when we know we have exclusive access. - fn as_internal(&mut self) -> &InternalNode<K, V> { - unsafe { &*self.as_internal_ptr() } +impl<'a, K, V> NodeRef<marker::Immut<'a>, K, V, marker::Internal> { + /// Exposes the data of an internal node in an immutable tree. + fn as_internal(this: &Self) -> &'a InternalNode<K, V> { + let ptr = Self::as_internal_ptr(this); + // SAFETY: there can be no mutable references into this tree borrowed as `Immut`. + unsafe { &*ptr } } } impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { - /// Exposes the data of an internal node for writing. - /// - /// We don't need to return a raw ptr because we have unique access to the entire node. - fn as_internal_mut(&mut self) -> &mut InternalNode<K, V> { - unsafe { &mut *(self.node.as_ptr() as *mut InternalNode<K, V>) } + /// Offers exclusive access to the data of an internal node. + fn as_internal_mut(this: &mut Self) -> &'a mut InternalNode<K, V> { + let ptr = Self::as_internal_ptr(this); + unsafe { &mut *ptr } } } @@ -312,7 +360,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> { pub fn len(&self) -> usize { // Crucially, we only access the `len` field here. If BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. - unsafe { usize::from((*self.as_leaf_ptr()).len) } + unsafe { usize::from((*Self::as_leaf_ptr(self)).len) } } /// Returns the height of this node with respect to the leaf level. Zero height means the @@ -322,48 +370,49 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> { } /// Temporarily takes out another, immutable reference to the same node. - fn reborrow(&self) -> NodeRef<marker::Immut<'_>, K, V, Type> { + pub fn reborrow(&self) -> NodeRef<marker::Immut<'_>, K, V, Type> { NodeRef { height: self.height, node: self.node, _marker: PhantomData } } /// Exposes the leaf portion of any leaf or internal node. /// - /// Returns a raw ptr to avoid invalidating other references to this node, - /// which is possible when BorrowType is marker::ValMut. - fn as_leaf_ptr(&self) -> *const LeafNode<K, V> { + /// Returns a raw ptr to avoid invalidating other references to this node. + fn as_leaf_ptr(this: &Self) -> *mut LeafNode<K, V> { // The node must be valid for at least the LeafNode portion. // This is not a reference in the NodeRef type because we don't know if // it should be unique or shared. - self.node.as_ptr() + this.node.as_ptr() } +} - /// Borrows a reference to one of the keys stored in the node. +impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> { + /// Exposes one of the keys stored in the node. /// /// # Safety /// The node has more than `idx` initialized elements. - pub unsafe fn key_at(&self, idx: usize) -> &K { - unsafe { self.reborrow().into_key_at(idx) } + pub unsafe fn key_at(self, idx: usize) -> &'a K { + debug_assert!(idx < self.len()); + unsafe { Self::as_leaf(&self).keys.get_unchecked(idx).assume_init_ref() } } - /// Borrows a reference to one of the values stored in the node. + /// Exposes one of the values stored in the node. /// /// # Safety /// The node has more than `idx` initialized elements. - unsafe fn val_at(&self, idx: usize) -> &V { - unsafe { self.reborrow().into_val_at(idx) } + unsafe fn val_at(self, idx: usize) -> &'a V { + debug_assert!(idx < self.len()); + unsafe { Self::as_leaf(&self).vals.get_unchecked(idx).assume_init_ref() } } } -impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> { - /// Borrows a reference to the contents of one of the edges that delimit - /// the elements of the node, without invalidating other references. +impl<'a, K, V> NodeRef<marker::Immut<'a>, K, V, marker::Internal> { + /// Exposes the contents of one of the edges in the node. /// /// # Safety /// The node has more than `idx` initialized elements. - unsafe fn edge_at(&self, idx: usize) -> &BoxedNode<K, V> { + unsafe fn edge_at(self, idx: usize) -> &'a BoxedNode<K, V> { debug_assert!(idx <= self.len()); - let node = self.as_internal_ptr(); - unsafe { (*node).edges.get_unchecked(idx).assume_init_ref() } + unsafe { Self::as_internal(&self).edges.get_unchecked(idx).assume_init_ref() } } } @@ -380,15 +429,11 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> { ) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> { // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. - let leaf_ptr = self.as_leaf_ptr(); + let leaf_ptr: *const _ = Self::as_leaf_ptr(&self); unsafe { (*leaf_ptr).parent } .as_ref() .map(|parent| Handle { - node: NodeRef { - height: self.height + 1, - node: parent.cast(), - _marker: PhantomData, - }, + node: NodeRef::from_internal(*parent, self.height + 1), idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) }, _marker: PhantomData, }) @@ -420,11 +465,11 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> { } impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> { - /// Exposes the data of a leaf node for reading in an immutable tree. - fn into_leaf(self) -> &'a LeafNode<K, V> { - // SAFETY: we can access the entire node freely and do no need raw pointers, - // because there can be no mutable references to this Immut tree. - unsafe { &(*self.as_leaf_ptr()) } + /// Exposes the leaf portion of any leaf or internal node in an immutable tree. + fn as_leaf(this: &Self) -> &'a LeafNode<K, V> { + let ptr = Self::as_leaf_ptr(this); + // SAFETY: there can be no mutable references into this tree borrowed as `Immut`. + unsafe { &*ptr } } } @@ -473,139 +518,155 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> { NodeRef { height: self.height, node: self.node, _marker: PhantomData } } - /// Exposes the leaf portion of any leaf or internal node for writing. - /// - /// We don't need to return a raw ptr because we have unique access to the entire node. - fn as_leaf_mut(&mut self) -> &'a mut LeafNode<K, V> { - unsafe { &mut (*self.node.as_ptr()) } + /// Offers exclusive access to the leaf portion of any leaf or internal node. + fn as_leaf_mut(this: &mut Self) -> &'a mut LeafNode<K, V> { + let ptr = Self::as_leaf_ptr(this); + // SAFETY: we have exclusive access to the entire node. + unsafe { &mut *ptr } } +} - /// Borrows a mutable reference to one of the keys stored in the node. +impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> { + /// Offers exclusive access to a part of the key storage area. /// /// # Safety /// The node has more than `idx` initialized elements. - unsafe fn key_mut_at(&mut self, idx: usize) -> &mut K { - unsafe { self.reborrow_mut().into_key_mut_at(idx) } + unsafe fn into_key_area_mut_at(mut self, idx: usize) -> &'a mut MaybeUninit<K> { + debug_assert!(idx < self.len()); + unsafe { Self::as_leaf_mut(&mut self).keys.get_unchecked_mut(idx) } } - /// Borrows a mutable reference to one of the values stored in the node. + /// Offers exclusive access to a part of the value storage area. /// /// # Safety /// The node has more than `idx` initialized elements. - unsafe fn val_mut_at(&mut self, idx: usize) -> &mut V { - unsafe { self.reborrow_mut().into_val_mut_at(idx) } - } - - fn keys_mut(&mut self) -> &mut [K] - where - K: 'a, - V: 'a, - { - // SAFETY: the caller will not be able to call further methods on self - // until the key slice reference is dropped, as we have unique access - // for the lifetime of the borrow. - // SAFETY: The keys of a node must always be initialized up to length. - unsafe { - slice::from_raw_parts_mut( - MaybeUninit::slice_as_mut_ptr(&mut self.as_leaf_mut().keys), - self.len(), - ) - } - } - - fn vals_mut(&mut self) -> &mut [V] - where - K: 'a, - V: 'a, - { - // SAFETY: the caller will not be able to call further methods on self - // until the value slice reference is dropped, as we have unique access - // for the lifetime of the borrow. - // SAFETY: The values of a node must always be initialized up to length. - unsafe { - slice::from_raw_parts_mut( - MaybeUninit::slice_as_mut_ptr(&mut self.as_leaf_mut().vals), - self.len(), - ) - } + unsafe fn into_val_area_mut_at(mut self, idx: usize) -> &'a mut MaybeUninit<V> { + debug_assert!(idx < self.len()); + unsafe { Self::as_leaf_mut(&mut self).vals.get_unchecked_mut(idx) } } } -impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { - fn edges_mut(&mut self) -> &mut [BoxedNode<K, V>] { - unsafe { - slice::from_raw_parts_mut( - MaybeUninit::slice_as_mut_ptr(&mut self.as_internal_mut().edges), - self.len() + 1, - ) - } +impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { + /// Offers exclusive access to a part of the storage area for edge contents. + /// + /// # Safety + /// The node has at least `idx` initialized elements. + unsafe fn into_edge_area_mut_at(mut self, idx: usize) -> &'a mut MaybeUninit<BoxedNode<K, V>> { + debug_assert!(idx <= self.len()); + unsafe { Self::as_internal_mut(&mut self).edges.get_unchecked_mut(idx) } } } impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> { - /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn into_key_at(self, idx: usize) -> &'a K { - unsafe { self.into_leaf().keys.get_unchecked(idx).assume_init_ref() } + /// Exposes the entire key storage area in the node, + /// regardless of the node's current length, + /// having exclusive access to the entire node. + unsafe fn key_area(self) -> &'a [MaybeUninit<K>] { + Self::as_leaf(&self).keys.as_slice() } - /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn into_val_at(self, idx: usize) -> &'a V { - unsafe { self.into_leaf().vals.get_unchecked(idx).assume_init_ref() } + /// Exposes the entire value storage area in the node, + /// regardless of the node's current length, + /// having exclusive access to the entire node. + unsafe fn val_area(self) -> &'a [MaybeUninit<V>] { + Self::as_leaf(&self).vals.as_slice() } } -impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> { - /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn into_key_mut_at(mut self, idx: usize) -> &'a mut K { - debug_assert!(idx < self.len()); +impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::Internal> { + /// Exposes the entire storage area for edge contents in the node, + /// regardless of the node's current length, + /// having exclusive access to the entire node. + unsafe fn edge_area(self) -> &'a [MaybeUninit<BoxedNode<K, V>>] { + Self::as_internal(&self).edges.as_slice() + } +} - let leaf = self.as_leaf_mut(); - unsafe { leaf.keys.get_unchecked_mut(idx).assume_init_mut() } +impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> { + /// Offers exclusive access to a sized slice of key storage area in the node. + unsafe fn into_key_area_slice(mut self) -> &'a mut [MaybeUninit<K>] { + let len = self.len(); + // SAFETY: the caller will not be able to call further methods on self + // until the key slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { Self::as_leaf_mut(&mut self).keys.get_unchecked_mut(..len) } } - /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn into_val_mut_at(mut self, idx: usize) -> &'a mut V { - debug_assert!(idx < self.len()); + /// Offers exclusive access to a sized slice of value storage area in the node. + unsafe fn into_val_area_slice(mut self) -> &'a mut [MaybeUninit<V>] { + let len = self.len(); + // SAFETY: the caller will not be able to call further methods on self + // until the value slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { Self::as_leaf_mut(&mut self).vals.get_unchecked_mut(..len) } + } +} - let leaf = self.as_leaf_mut(); - unsafe { leaf.vals.get_unchecked_mut(idx).assume_init_mut() } +impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { + /// Offers exclusive access to a sized slice of storage area for edge contents in the node. + unsafe fn into_edge_area_slice(mut self) -> &'a mut [MaybeUninit<BoxedNode<K, V>>] { + let len = self.len(); + // SAFETY: the caller will not be able to call further methods on self + // until the edge slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { Self::as_internal_mut(&mut self).edges.get_unchecked_mut(..len + 1) } } } impl<'a, K, V, Type> NodeRef<marker::ValMut<'a>, K, V, Type> { /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn into_key_val_mut_at(self, idx: usize) -> (&'a K, &'a mut V) { + /// - The node has more than `idx` initialized elements. + /// - The keys and values of the node must be initialized up to its current length. + unsafe fn into_key_val_mut_at(mut self, idx: usize) -> (&'a K, &'a mut V) { // We only create a reference to the one element we are interested in, // to avoid aliasing with outstanding references to other elements, // in particular, those returned to the caller in earlier iterations. - let leaf = self.node.as_ptr(); + let leaf = Self::as_leaf_ptr(&mut self); let keys = unsafe { &raw const (*leaf).keys }; let vals = unsafe { &raw mut (*leaf).vals }; // We must coerce to unsized array pointers because of Rust issue #74679. let keys: *const [_] = keys; let vals: *mut [_] = vals; - // SAFETY: The keys and values of a node must always be initialized up to length. let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() }; let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() }; (key, val) } } +impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> { + /// Exposes exclusive access to the length of the node. + pub fn into_len_mut(mut self) -> &'a mut u16 { + &mut (*Self::as_leaf_mut(&mut self)).len + } +} + +impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> { + /// Set or clear the node's link to its parent edge, + /// without invalidating other references to the node. + fn set_parent_link(&mut self, parent: NonNull<InternalNode<K, V>>, parent_idx: usize) { + let leaf = Self::as_leaf_ptr(self); + unsafe { (*leaf).parent = Some(parent) }; + unsafe { (*leaf).parent_idx.write(parent_idx as u16) }; + } + + /// Clear the node's link to its parent edge, freeing it from its tree. + /// This only makes sense when there are no other references to the node. + fn clear_parent_link(&mut self) { + let leaf = Self::as_leaf_mut(self); + leaf.parent = None; + } +} + impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> { /// Adds a key/value pair to the end of the node. pub fn push(&mut self, key: K, val: V) { - let len = &mut self.as_leaf_mut().len; + let len = unsafe { self.reborrow_mut().into_len_mut() }; let idx = usize::from(*len); assert!(idx < CAPACITY); *len += 1; unsafe { - ptr::write(self.key_mut_at(idx), key); - ptr::write(self.val_mut_at(idx), val); + self.reborrow_mut().into_key_area_mut_at(idx).write(key); + self.reborrow_mut().into_val_area_mut_at(idx).write(val); } } @@ -614,10 +675,10 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> { assert!(self.len() < CAPACITY); unsafe { - slice_insert(self.keys_mut(), 0, key); - slice_insert(self.vals_mut(), 0, val); + *self.reborrow_mut().into_len_mut() += 1; + slice_insert(self.reborrow_mut().into_key_area_slice(), 0, key); + slice_insert(self.reborrow_mut().into_val_area_slice(), 0, val); } - self.as_leaf_mut().len += 1; } } @@ -643,14 +704,14 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) { assert!(edge.height == self.height - 1); - let len = &mut self.as_leaf_mut().len; + let len = unsafe { self.reborrow_mut().into_len_mut() }; let idx = usize::from(*len); assert!(idx < CAPACITY); *len += 1; unsafe { - ptr::write(self.key_mut_at(idx), key); - ptr::write(self.val_mut_at(idx), val); - self.as_internal_mut().edges.get_unchecked_mut(idx + 1).write(edge.node); + self.reborrow_mut().into_key_area_mut_at(idx).write(key); + self.reborrow_mut().into_val_area_mut_at(idx).write(val); + self.reborrow_mut().into_edge_area_mut_at(idx + 1).write(edge.into_boxed_node()); Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link(); } } @@ -662,13 +723,12 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { assert!(self.len() < CAPACITY); unsafe { - slice_insert(self.keys_mut(), 0, key); - slice_insert(self.vals_mut(), 0, val); - slice_insert(self.edges_mut(), 0, edge.node); + *self.reborrow_mut().into_len_mut() += 1; + slice_insert(self.reborrow_mut().into_key_area_slice(), 0, key); + slice_insert(self.reborrow_mut().into_val_area_slice(), 0, val); + slice_insert(self.reborrow_mut().into_edge_area_slice(), 0, edge.into_boxed_node()); } - self.as_leaf_mut().len += 1; - self.correct_all_childrens_parent_links(); } } @@ -683,19 +743,21 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> { let idx = self.len() - 1; unsafe { - let key = ptr::read(self.key_at(idx)); - let val = ptr::read(self.val_at(idx)); + let key = ptr::read(self.reborrow().key_at(idx)); + let val = ptr::read(self.reborrow().val_at(idx)); let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(internal) => { - let edge = ptr::read(internal.edge_at(idx + 1)); - let mut new_root = Root { node: edge, height: internal.height - 1 }; - new_root.node_as_mut().as_leaf_mut().parent = None; - Some(new_root) + let boxed_node = ptr::read(internal.reborrow().edge_at(idx + 1)); + let mut edge = Root { node: boxed_node, height: internal.height - 1 }; + // In practice, clearing the parent is a waste of time, because we will + // insert the node elsewhere and set its parent link again. + edge.node_as_mut().clear_parent_link(); + Some(edge) } }; - self.as_leaf_mut().len -= 1; + *self.reborrow_mut().into_len_mut() -= 1; (key, val, edge) } } @@ -709,29 +771,35 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> { let old_len = self.len(); unsafe { - let key = slice_remove(self.keys_mut(), 0); - let val = slice_remove(self.vals_mut(), 0); + let key = slice_remove(self.reborrow_mut().into_key_area_slice(), 0); + let val = slice_remove(self.reborrow_mut().into_val_area_slice(), 0); let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(mut internal) => { - let edge = slice_remove(internal.edges_mut(), 0); - let mut new_root = Root { node: edge, height: internal.height - 1 }; - new_root.node_as_mut().as_leaf_mut().parent = None; + let boxed_node = + slice_remove(internal.reborrow_mut().into_edge_area_slice(), 0); + let mut edge = Root { node: boxed_node, height: internal.height - 1 }; + // In practice, clearing the parent is a waste of time, because we will + // insert the node elsewhere and set its parent link again. + edge.node_as_mut().clear_parent_link(); internal.correct_childrens_parent_links(0..old_len); - Some(new_root) + Some(edge) } }; - self.as_leaf_mut().len -= 1; + *self.reborrow_mut().into_len_mut() -= 1; (key, val, edge) } } fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) { - (self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr()) + let leaf = Self::as_leaf_mut(&mut self); + let keys = MaybeUninit::slice_as_mut_ptr(&mut leaf.keys); + let vals = MaybeUninit::slice_as_mut_ptr(&mut leaf.vals); + (keys, vals) } } @@ -816,7 +884,7 @@ impl<BorrowType, K, V, NodeType> NodeRef<BorrowType, K, V, NodeType> { /// Could be a public implementation of PartialEq, but only used in this module. fn eq(&self, other: &Self) -> bool { let Self { node, height, _marker: _ } = self; - if *node == other.node { + if node.eq(&other.node) { debug_assert_eq!(*height, other.height); true } else { @@ -924,11 +992,11 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark debug_assert!(self.node.len() < CAPACITY); unsafe { - slice_insert(self.node.keys_mut(), self.idx, key); - slice_insert(self.node.vals_mut(), self.idx, val); - self.node.as_leaf_mut().len += 1; + *self.node.reborrow_mut().into_len_mut() += 1; + slice_insert(self.node.reborrow_mut().into_key_area_slice(), self.idx, key); + slice_insert(self.node.reborrow_mut().into_val_area_slice(), self.idx, val); - self.node.val_mut_at(self.idx) + self.node.reborrow_mut().into_val_area_mut_at(self.idx).assume_init_mut() } } } @@ -964,12 +1032,12 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge> { /// Fixes the parent pointer and index in the child node below this edge. This is useful /// when the ordering of edges has been changed, such as in the various `insert` methods. - fn correct_parent_link(mut self) { - let idx = self.idx as u16; - let ptr = NonNull::new(self.node.as_internal_mut()); + fn correct_parent_link(self) { + // Create backpointer without invalidating other references to the node. + let ptr = unsafe { NonNull::new_unchecked(NodeRef::as_internal_ptr(&self.node)) }; + let idx = self.idx; let mut child = self.descend(); - child.as_leaf_mut().parent = ptr; - child.as_leaf_mut().parent_idx.write(idx); + child.set_parent_link(ptr, idx); } } @@ -981,11 +1049,12 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, debug_assert!(self.node.len() < CAPACITY); debug_assert!(edge.height == self.node.height - 1); + let boxed_node = edge.into_boxed_node(); unsafe { - slice_insert(self.node.keys_mut(), self.idx, key); - slice_insert(self.node.vals_mut(), self.idx, val); - slice_insert(self.node.edges_mut(), self.idx + 1, edge.node); - self.node.as_leaf_mut().len += 1; + *self.node.reborrow_mut().into_len_mut() += 1; + slice_insert(self.node.reborrow_mut().into_key_area_slice(), self.idx, key); + slice_insert(self.node.reborrow_mut().into_val_area_slice(), self.idx, val); + slice_insert(self.node.reborrow_mut().into_edge_area_slice(), self.idx + 1, boxed_node); self.node.correct_childrens_parent_links((self.idx + 1)..=self.node.len()); } @@ -1073,28 +1142,25 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marke // node pointer is dereferenced, we access the edges array with a // reference (Rust issue #73987) and invalidate any other references // to or inside the array, should any be around. - let internal_node = self.node.as_internal_ptr(); - NodeRef { - height: self.node.height - 1, - node: unsafe { (&*(*internal_node).edges.get_unchecked(self.idx).as_ptr()).as_ptr() }, - _marker: PhantomData, - } + let parent_ptr = NodeRef::as_internal_ptr(&self.node); + let boxed_node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() }; + NodeRef::from_boxed_node(boxed_node, self.node.height - 1) } } impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Immut<'a>, K, V, NodeType>, marker::KV> { pub fn into_kv(self) -> (&'a K, &'a V) { - (unsafe { self.node.into_key_at(self.idx) }, unsafe { self.node.into_val_at(self.idx) }) + (unsafe { self.node.key_at(self.idx) }, unsafe { self.node.val_at(self.idx) }) } } impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> { pub fn into_key_mut(self) -> &'a mut K { - unsafe { self.node.into_key_mut_at(self.idx) } + unsafe { self.node.into_key_area_mut_at(self.idx).assume_init_mut() } } pub fn into_val_mut(self) -> &'a mut V { - unsafe { self.node.into_val_mut_at(self.idx) } + unsafe { self.node.into_val_area_mut_at(self.idx).assume_init_mut() } } } @@ -1106,12 +1172,14 @@ impl<'a, K, V, NodeType> Handle<NodeRef<marker::ValMut<'a>, K, V, NodeType>, mar impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> { pub fn kv_mut(&mut self) -> (&mut K, &mut V) { - // We cannot call into_key_mut_at and into_val_mut_at, because calling the second one + // We cannot call separate key and value methods, because calling the second one // invalidates the reference returned by the first. - let leaf = self.node.as_leaf_mut(); - let key = unsafe { leaf.keys.get_unchecked_mut(self.idx).assume_init_mut() }; - let val = unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() }; - (key, val) + unsafe { + let leaf = NodeRef::as_leaf_mut(&mut self.node.reborrow_mut()); + let key = leaf.keys.get_unchecked_mut(self.idx).assume_init_mut(); + let val = leaf.vals.get_unchecked_mut(self.idx).assume_init_mut(); + (key, val) + } } } @@ -1127,23 +1195,23 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType> /// by taking care of leaf data. fn split_leaf_data(&mut self, new_node: &mut LeafNode<K, V>) -> (K, V) { let new_len = self.split_new_node_len(); + new_node.len = new_len as u16; unsafe { - let k = ptr::read(self.node.key_at(self.idx)); - let v = ptr::read(self.node.val_at(self.idx)); + let k = ptr::read(self.node.reborrow().key_at(self.idx)); + let v = ptr::read(self.node.reborrow().val_at(self.idx)); ptr::copy_nonoverlapping( - self.node.key_at(self.idx + 1), - MaybeUninit::slice_as_mut_ptr(&mut new_node.keys), + self.node.reborrow().key_area().as_ptr().add(self.idx + 1), + new_node.keys.as_mut_ptr(), new_len, ); ptr::copy_nonoverlapping( - self.node.val_at(self.idx + 1), - MaybeUninit::slice_as_mut_ptr(&mut new_node.vals), + self.node.reborrow().val_area().as_ptr().add(self.idx + 1), + new_node.vals.as_mut_ptr(), new_len, ); - self.node.as_leaf_mut().len = self.idx as u16; - new_node.len = new_len as u16; + *self.node.reborrow_mut().into_len_mut() = self.idx as u16; (k, v) } } @@ -1174,9 +1242,9 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark mut self, ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) { unsafe { - let k = slice_remove(self.node.keys_mut(), self.idx); - let v = slice_remove(self.node.vals_mut(), self.idx); - self.node.as_leaf_mut().len -= 1; + let k = slice_remove(self.node.reborrow_mut().into_key_area_slice(), self.idx); + let v = slice_remove(self.node.reborrow_mut().into_val_area_slice(), self.idx); + *self.node.reborrow_mut().into_len_mut() -= 1; ((k, v), self.left_edge()) } } @@ -1205,11 +1273,11 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Internal>, K, V, Root<K, V>) { unsafe { let mut new_node = Box::new(InternalNode::new()); - // Move edges out before reducing length: let new_len = self.split_new_node_len(); + // Move edges out before reducing length: ptr::copy_nonoverlapping( - self.node.edge_at(self.idx + 1), - MaybeUninit::slice_as_mut_ptr(&mut new_node.edges), + self.node.reborrow().edge_area().as_ptr().add(self.idx + 1), + new_node.edges.as_mut_ptr(), new_len + 1, ); let (k, v) = self.split_leaf_data(&mut new_node.data); @@ -1241,31 +1309,28 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, assert!(left_len + right_len < CAPACITY); unsafe { - ptr::write( - left_node.keys_mut().get_unchecked_mut(left_len), - slice_remove(self.node.keys_mut(), self.idx), - ); + *left_node.reborrow_mut().into_len_mut() += right_len as u16 + 1; + + let parent_key = slice_remove(self.node.reborrow_mut().into_key_area_slice(), self.idx); + left_node.reborrow_mut().into_key_area_mut_at(left_len).write(parent_key); ptr::copy_nonoverlapping( - right_node.key_at(0), - left_node.keys_mut().as_mut_ptr().add(left_len + 1), + right_node.reborrow().key_area().as_ptr(), + left_node.reborrow_mut().into_key_area_slice().as_mut_ptr().add(left_len + 1), right_len, ); - ptr::write( - left_node.vals_mut().get_unchecked_mut(left_len), - slice_remove(self.node.vals_mut(), self.idx), - ); + + let parent_val = slice_remove(self.node.reborrow_mut().into_val_area_slice(), self.idx); + left_node.reborrow_mut().into_val_area_mut_at(left_len).write(parent_val); ptr::copy_nonoverlapping( - right_node.val_at(0), - left_node.vals_mut().as_mut_ptr().add(left_len + 1), + right_node.reborrow().val_area().as_ptr(), + left_node.reborrow_mut().into_val_area_slice().as_mut_ptr().add(left_len + 1), right_len, ); - slice_remove(&mut self.node.edges_mut(), self.idx + 1); + slice_remove(&mut self.node.reborrow_mut().into_edge_area_slice(), self.idx + 1); let self_len = self.node.len(); self.node.correct_childrens_parent_links(self.idx + 1..self_len); - self.node.as_leaf_mut().len -= 1; - - left_node.as_leaf_mut().len += right_len as u16 + 1; + *self.node.reborrow_mut().into_len_mut() -= 1; if self.node.height > 1 { // SAFETY: the height of the nodes being merged is one below the height @@ -1273,8 +1338,8 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, let mut left_node = left_node.cast_to_internal_unchecked(); let right_node = right_node.cast_to_internal_unchecked(); ptr::copy_nonoverlapping( - right_node.edge_at(0), - left_node.edges_mut().as_mut_ptr().add(left_len + 1), + right_node.reborrow().edge_area().as_ptr(), + left_node.reborrow_mut().into_edge_area_slice().as_mut_ptr().add(left_len + 1), right_len + 1, ); @@ -1360,13 +1425,14 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, move_kv(left_kv, new_left_len, parent_kv, 0, 1); } - left_node.as_leaf_mut().len -= count as u16; - right_node.as_leaf_mut().len += count as u16; + *left_node.reborrow_mut().into_len_mut() -= count as u16; + *right_node.reborrow_mut().into_len_mut() += count as u16; match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { // Make room for stolen edges. - let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr(); + let left = left.reborrow(); + let right_edges = right.reborrow_mut().into_edge_area_slice().as_mut_ptr(); ptr::copy(right_edges, right_edges.add(count), right_len + 1); right.correct_childrens_parent_links(count..count + right_len + 1); @@ -1415,15 +1481,15 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, ptr::copy(right_kv.1.add(count), right_kv.1, new_right_len); } - left_node.as_leaf_mut().len += count as u16; - right_node.as_leaf_mut().len -= count as u16; + *left_node.reborrow_mut().into_len_mut() += count as u16; + *right_node.reborrow_mut().into_len_mut() -= count as u16; match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { - move_edges(right.reborrow_mut(), 0, left, left_len + 1, count); + move_edges(right.reborrow(), 0, left, left_len + 1, count); // Fix right indexing. - let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr(); + let right_edges = right.reborrow_mut().into_edge_area_slice().as_mut_ptr(); ptr::copy(right_edges.add(count), right_edges, new_right_len + 1); right.correct_childrens_parent_links(0..=new_right_len); } @@ -1448,16 +1514,16 @@ unsafe fn move_kv<K, V>( } // Source and destination must have the same height. -unsafe fn move_edges<K, V>( - mut source: NodeRef<marker::Mut<'_>, K, V, marker::Internal>, +unsafe fn move_edges<'a, K: 'a, V: 'a>( + source: NodeRef<marker::Immut<'a>, K, V, marker::Internal>, source_offset: usize, - mut dest: NodeRef<marker::Mut<'_>, K, V, marker::Internal>, + mut dest: NodeRef<marker::Mut<'a>, K, V, marker::Internal>, dest_offset: usize, count: usize, ) { - let source_ptr = source.as_internal().edges.as_ptr(); - let dest_ptr = dest.as_internal_mut().edges.as_mut_ptr(); unsafe { + let source_ptr = source.edge_area().as_ptr(); + let dest_ptr = dest.reborrow_mut().into_edge_area_slice().as_mut_ptr(); ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr.add(dest_offset), count); dest.correct_childrens_parent_links(dest_offset..dest_offset + count); } @@ -1553,11 +1619,12 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, ma move_kv(left_kv, left_new_len, right_kv, 0, right_new_len); - left_node.as_leaf_mut().len = left_new_len as u16; - right_node.as_leaf_mut().len = right_new_len as u16; + *left_node.reborrow_mut().into_len_mut() = left_new_len as u16; + *right_node.reborrow_mut().into_len_mut() = right_new_len as u16; match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(right)) => { + let left = left.reborrow(); move_edges(left, left_new_len + 1, right, 1, right_new_len); } (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} @@ -1606,17 +1673,34 @@ pub mod marker { pub enum Edge {} } -unsafe fn slice_insert<T>(slice: &mut [T], idx: usize, val: T) { +/// Inserts a value into a slice of initialized elements followed by one uninitialized element. +/// +/// # Safety +/// The slice has more than `idx` elements. +unsafe fn slice_insert<T>(slice: &mut [MaybeUninit<T>], idx: usize, val: T) { unsafe { - ptr::copy(slice.as_ptr().add(idx), slice.as_mut_ptr().add(idx + 1), slice.len() - idx); - ptr::write(slice.get_unchecked_mut(idx), val); + let len = slice.len(); + debug_assert!(len > idx); + let slice_ptr = slice.as_mut_ptr(); + if len > idx + 1 { + ptr::copy(slice_ptr.add(idx), slice_ptr.add(idx + 1), len - idx - 1); + } + (*slice_ptr.add(idx)).write(val); } } -unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T { +/// Removes and returns a value from a slice of all initialized elements, leaving behind one +/// trailing uninitialized element. +/// +/// # Safety +/// The slice has more than `idx` elements. +unsafe fn slice_remove<T>(slice: &mut [MaybeUninit<T>], idx: usize) -> T { unsafe { - let ret = ptr::read(slice.get_unchecked(idx)); - ptr::copy(slice.as_ptr().add(idx + 1), slice.as_mut_ptr().add(idx), slice.len() - idx - 1); + let len = slice.len(); + debug_assert!(idx < len); + let slice_ptr = slice.as_mut_ptr(); + let ret = (*slice_ptr.add(idx)).assume_init_read(); + ptr::copy(slice_ptr.add(idx + 1), slice_ptr.add(idx), len - idx - 1); ret } } diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index d6527057c5d..38c75de34ee 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -17,43 +17,6 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> } } - /// Asserts that the keys are in strictly ascending order. - /// Returns how many keys it encountered. - pub fn assert_ascending(self) -> usize - where - K: Copy + Debug + Ord, - { - struct SeriesChecker<T> { - num_seen: usize, - previous: Option<T>, - } - impl<T: Copy + Debug + Ord> SeriesChecker<T> { - fn is_ascending(&mut self, next: T) { - if let Some(previous) = self.previous { - assert!(previous < next, "{:?} >= {:?}", previous, next); - } - self.previous = Some(next); - self.num_seen += 1; - } - } - - let mut checker = SeriesChecker { num_seen: 0, previous: None }; - self.visit_nodes_in_order(|pos| match pos { - navigate::Position::Leaf(node) => { - for idx in 0..node.len() { - let key = *unsafe { node.key_at(idx) }; - checker.is_ascending(key); - } - } - navigate::Position::InternalKV(kv) => { - let key = *kv.into_kv().0; - checker.is_ascending(key); - } - navigate::Position::Internal(_) => {} - }); - checker.num_seen - } - pub fn dump_keys(self) -> String where K: Debug, diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs index 1526c0673c6..701d5ec73e2 100644 --- a/library/alloc/src/collections/btree/search.rs +++ b/library/alloc/src/collections/btree/search.rs @@ -72,7 +72,7 @@ where // is an index -- not a reference. let len = node.len(); for i in 0..len { - let k = unsafe { node.key_at(i) }; + let k = unsafe { node.reborrow().key_at(i) }; match key.cmp(k.borrow()) { Ordering::Greater => {} Ordering::Equal => return (i, true), diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 15092d463ec..f21fc8854d0 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -78,6 +78,7 @@ #![cfg_attr(test, feature(new_uninit))] #![feature(allocator_api)] #![feature(array_chunks)] +#![feature(array_methods)] #![feature(array_value_iter)] #![feature(array_windows)] #![feature(allow_internal_unstable)] diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 202e3a83638..2c8bc3d53ef 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2136,10 +2136,8 @@ impl<T> InPlaceDrop<T> { impl<T> Drop for InPlaceDrop<T> { #[inline] fn drop(&mut self) { - if mem::needs_drop::<T>() { - unsafe { - ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); - } + unsafe { + ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); } } } @@ -2871,10 +2869,8 @@ impl<T> IntoIter<T> { } fn drop_remaining(&mut self) { - if mem::needs_drop::<T>() { - unsafe { - ptr::drop_in_place(self.as_mut_slice()); - } + unsafe { + ptr::drop_in_place(self.as_mut_slice()); } self.ptr = self.end; } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 0e3129607a6..433f0129306 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -788,7 +788,7 @@ extern "rust-intrinsic" { /// The size of the referenced value in bytes. /// - /// The stabilized version of this intrinsic is [`size_of_val`]. + /// The stabilized version of this intrinsic is [`mem::size_of_val`]. #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] pub fn size_of_val<T: ?Sized>(_: *const T) -> usize; /// The required alignment of the referenced value. @@ -1704,7 +1704,7 @@ extern "rust-intrinsic" { /// Returns the number of variants of the type `T` cast to a `usize`; /// if `T` has no variants, returns 0. Uninhabited variants will be counted. /// - /// The to-be-stabilized version of this intrinsic is [`variant_count`]. + /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`]. #[rustc_const_unstable(feature = "variant_count", issue = "73662")] pub fn variant_count<T>() -> usize; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index ea560288c28..41202546566 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -159,6 +159,7 @@ #![feature(slice_ptr_get)] #![feature(no_niche)] // rust-lang/rust#68303 #![feature(unsafe_block_in_unsafe_fn)] +#![feature(int_error_matching)] #![deny(unsafe_op_in_unsafe_fn)] #[prelude_import] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 079d9f6006a..fe3eff04b4a 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -318,7 +318,7 @@ macro_rules! r#try { /// Writes formatted data into a buffer. /// -/// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be +/// This macro accepts a 'writer', a format string, and a list of arguments. Arguments will be /// formatted according to the specified format string and the result will be passed to the writer. /// The writer may be any value with a `write_fmt` method; generally this comes from an /// implementation of either the [`fmt::Write`] or the [`io::Write`] trait. The macro diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index aab17155186..9d8c8c86291 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -98,15 +98,18 @@ pub enum IntErrorKind { /// /// Among other causes, this variant will be constructed when parsing an empty string. Empty, - /// Contains an invalid digit. + /// Contains an invalid digit in its context. /// /// Among other causes, this variant will be constructed when parsing a string that - /// contains a letter. + /// contains a non-ASCII char. + /// + /// This variant is also constructed when a `+` or `-` is misplaced within a string + /// either on its own or in the middle of a number. InvalidDigit, /// Integer is too large to store in target integer type. - Overflow, + PosOverflow, /// Integer is too small to store in target integer type. - Underflow, + NegOverflow, /// Value was Zero /// /// This variant will be emitted when the parsing string has a value of zero, which @@ -119,7 +122,7 @@ impl ParseIntError { #[unstable( feature = "int_error_matching", reason = "it can be useful to match errors when making error messages \ - for integer parsing", + for integer parsing", issue = "22639" )] pub fn kind(&self) -> &IntErrorKind { @@ -136,8 +139,8 @@ impl ParseIntError { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", IntErrorKind::InvalidDigit => "invalid digit found in string", - IntErrorKind::Overflow => "number too large to fit in target type", - IntErrorKind::Underflow => "number too small to fit in target type", + IntErrorKind::PosOverflow => "number too large to fit in target type", + IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index c90887b89d0..9f5ae57b74a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -63,7 +63,12 @@ pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, No #[stable(feature = "try_from", since = "1.34.0")] pub use error::TryFromIntError; -#[unstable(feature = "int_error_matching", issue = "22639")] +#[unstable( + feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639" +)] pub use error::IntErrorKind; macro_rules! usize_isize_to_xe_bytes_doc { @@ -830,15 +835,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par let src = src.as_bytes(); let (is_positive, digits) = match src[0] { + b'+' | b'-' if src[1..].is_empty() => { + return Err(PIE { kind: InvalidDigit }); + } b'+' => (true, &src[1..]), b'-' if is_signed_ty => (false, &src[1..]), _ => (true, src), }; - if digits.is_empty() { - return Err(PIE { kind: Empty }); - } - let mut result = T::from_u32(0); if is_positive { // The number is positive @@ -849,11 +853,11 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par }; result = match result.checked_mul(radix) { Some(result) => result, - None => return Err(PIE { kind: Overflow }), + None => return Err(PIE { kind: PosOverflow }), }; result = match result.checked_add(x) { Some(result) => result, - None => return Err(PIE { kind: Overflow }), + None => return Err(PIE { kind: PosOverflow }), }; } } else { @@ -865,11 +869,11 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par }; result = match result.checked_mul(radix) { Some(result) => result, - None => return Err(PIE { kind: Underflow }), + None => return Err(PIE { kind: NegOverflow }), }; result = match result.checked_sub(x) { Some(result) => result, - None => return Err(PIE { kind: Underflow }), + None => return Err(PIE { kind: NegOverflow }), }; } } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 6dc542dee58..88b4e2a2436 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -108,18 +108,20 @@ impl Duration { #[unstable(feature = "duration_constants", issue = "57391")] pub const NANOSECOND: Duration = Duration::from_nanos(1); - /// The minimum duration. + /// A duration of zero time. /// /// # Examples /// /// ``` - /// #![feature(duration_constants)] + /// #![feature(duration_zero)] /// use std::time::Duration; /// - /// assert_eq!(Duration::MIN, Duration::new(0, 0)); + /// let duration = Duration::ZERO; + /// assert!(duration.is_zero()); + /// assert_eq!(duration.as_nanos(), 0); /// ``` - #[unstable(feature = "duration_constants", issue = "57391")] - pub const MIN: Duration = Duration::from_nanos(0); + #[unstable(feature = "duration_zero", issue = "73544")] + pub const ZERO: Duration = Duration::from_nanos(0); /// The maximum duration. /// @@ -166,24 +168,6 @@ impl Duration { Duration { secs, nanos } } - /// Creates a new `Duration` that spans no time. - /// - /// # Examples - /// - /// ``` - /// #![feature(duration_zero)] - /// use std::time::Duration; - /// - /// let duration = Duration::zero(); - /// assert!(duration.is_zero()); - /// assert_eq!(duration.as_nanos(), 0); - /// ``` - #[unstable(feature = "duration_zero", issue = "73544")] - #[inline] - pub const fn zero() -> Duration { - Duration { secs: 0, nanos: 0 } - } - /// Creates a new `Duration` from the specified number of whole seconds. /// /// # Examples @@ -277,7 +261,7 @@ impl Duration { /// #![feature(duration_zero)] /// use std::time::Duration; /// - /// assert!(Duration::zero().is_zero()); + /// assert!(Duration::ZERO.is_zero()); /// assert!(Duration::new(0, 0).is_zero()); /// assert!(Duration::from_nanos(0).is_zero()); /// assert!(Duration::from_secs(0).is_zero()); @@ -536,18 +520,18 @@ impl Duration { } } - /// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::MIN`] + /// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::ZERO`] /// if the result would be negative or if overflow occurred. /// /// # Examples /// /// ``` /// #![feature(duration_saturating_ops)] - /// #![feature(duration_constants)] + /// #![feature(duration_zero)] /// use std::time::Duration; /// /// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1)); - /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::MIN); + /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO); /// ``` #[unstable(feature = "duration_saturating_ops", issue = "76416")] #[inline] @@ -555,7 +539,7 @@ impl Duration { pub const fn saturating_sub(self, rhs: Duration) -> Duration { match self.checked_sub(rhs) { Some(res) => res, - None => Duration::MIN, + None => Duration::ZERO, } } diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index 825e5e63b59..fb1293c99bb 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -135,11 +135,11 @@ fn test_from_str() { ); assert_eq!( "-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()), - Some(IntErrorKind::Underflow) + Some(IntErrorKind::NegOverflow) ); assert_eq!( "257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), - Some(IntErrorKind::Overflow) + Some(IntErrorKind::PosOverflow) ); } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 190528fd445..49e5cc0eaa5 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -2,10 +2,11 @@ use core::cmp::PartialEq; use core::convert::{TryFrom, TryInto}; use core::fmt::Debug; use core::marker::Copy; -use core::num::TryFromIntError; +use core::num::{IntErrorKind, ParseIntError, TryFromIntError}; use core::ops::{Add, Div, Mul, Rem, Sub}; use core::option::Option; -use core::option::Option::{None, Some}; +use core::option::Option::None; +use core::str::FromStr; #[macro_use] mod int_macros; @@ -67,6 +68,15 @@ where assert_eq!(ten.rem(two), ten % two); } +/// Helper function for asserting number parsing returns a specific error +fn test_parse<T>(num_str: &str, expected: Result<T, IntErrorKind>) +where + T: FromStr<Err = ParseIntError>, + Result<T, IntErrorKind>: PartialEq + Debug, +{ + assert_eq!(num_str.parse::<T>().map_err(|e| e.kind().clone()), expected) +} + #[test] fn from_str_issue7588() { let u: Option<u8> = u8::from_str_radix("1000", 10).ok(); @@ -77,49 +87,52 @@ fn from_str_issue7588() { #[test] fn test_int_from_str_overflow() { - assert_eq!("127".parse::<i8>().ok(), Some(127i8)); - assert_eq!("128".parse::<i8>().ok(), None); + test_parse::<i8>("127", Ok(127)); + test_parse::<i8>("128", Err(IntErrorKind::PosOverflow)); - assert_eq!("-128".parse::<i8>().ok(), Some(-128i8)); - assert_eq!("-129".parse::<i8>().ok(), None); + test_parse::<i8>("-128", Ok(-128)); + test_parse::<i8>("-129", Err(IntErrorKind::NegOverflow)); - assert_eq!("32767".parse::<i16>().ok(), Some(32_767i16)); - assert_eq!("32768".parse::<i16>().ok(), None); + test_parse::<i16>("32767", Ok(32_767)); + test_parse::<i16>("32768", Err(IntErrorKind::PosOverflow)); - assert_eq!("-32768".parse::<i16>().ok(), Some(-32_768i16)); - assert_eq!("-32769".parse::<i16>().ok(), None); + test_parse::<i16>("-32768", Ok(-32_768)); + test_parse::<i16>("-32769", Err(IntErrorKind::NegOverflow)); - assert_eq!("2147483647".parse::<i32>().ok(), Some(2_147_483_647i32)); - assert_eq!("2147483648".parse::<i32>().ok(), None); + test_parse::<i32>("2147483647", Ok(2_147_483_647)); + test_parse::<i32>("2147483648", Err(IntErrorKind::PosOverflow)); - assert_eq!("-2147483648".parse::<i32>().ok(), Some(-2_147_483_648i32)); - assert_eq!("-2147483649".parse::<i32>().ok(), None); + test_parse::<i32>("-2147483648", Ok(-2_147_483_648)); + test_parse::<i32>("-2147483649", Err(IntErrorKind::NegOverflow)); - assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(9_223_372_036_854_775_807i64)); - assert_eq!("9223372036854775808".parse::<i64>().ok(), None); + test_parse::<i64>("9223372036854775807", Ok(9_223_372_036_854_775_807)); + test_parse::<i64>("9223372036854775808", Err(IntErrorKind::PosOverflow)); - assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(-9_223_372_036_854_775_808i64)); - assert_eq!("-9223372036854775809".parse::<i64>().ok(), None); + test_parse::<i64>("-9223372036854775808", Ok(-9_223_372_036_854_775_808)); + test_parse::<i64>("-9223372036854775809", Err(IntErrorKind::NegOverflow)); } #[test] fn test_leading_plus() { - assert_eq!("+127".parse::<u8>().ok(), Some(127)); - assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807)); + test_parse::<u8>("+127", Ok(127)); + test_parse::<i64>("+9223372036854775807", Ok(9223372036854775807)); } #[test] fn test_invalid() { - assert_eq!("--129".parse::<i8>().ok(), None); - assert_eq!("++129".parse::<i8>().ok(), None); - assert_eq!("Съешь".parse::<u8>().ok(), None); + test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit)); + test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit)); + test_parse::<u8>("123Hello", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("-", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("+", Err(IntErrorKind::InvalidDigit)); + test_parse::<u8>("-1", Err(IntErrorKind::InvalidDigit)); } #[test] fn test_empty() { - assert_eq!("-".parse::<i8>().ok(), None); - assert_eq!("+".parse::<i8>().ok(), None); - assert_eq!("".parse::<u8>().ok(), None); + test_parse::<u8>("", Err(IntErrorKind::Empty)); } #[test] diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index 7c43885040b..f14639e0d58 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -108,24 +108,24 @@ fn sub() { #[test] fn checked_sub() { - let zero = Duration::new(0, 0); - let one_nano = Duration::new(0, 1); - let one_sec = Duration::new(1, 0); - assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); - assert_eq!(one_sec.checked_sub(one_nano), Some(Duration::new(0, 999_999_999))); - assert_eq!(zero.checked_sub(one_nano), None); - assert_eq!(zero.checked_sub(one_sec), None); + assert_eq!(Duration::NANOSECOND.checked_sub(Duration::ZERO), Some(Duration::NANOSECOND)); + assert_eq!( + Duration::SECOND.checked_sub(Duration::NANOSECOND), + Some(Duration::new(0, 999_999_999)) + ); + assert_eq!(Duration::ZERO.checked_sub(Duration::NANOSECOND), None); + assert_eq!(Duration::ZERO.checked_sub(Duration::SECOND), None); } #[test] fn saturating_sub() { - let zero = Duration::new(0, 0); - let one_nano = Duration::new(0, 1); - let one_sec = Duration::new(1, 0); - assert_eq!(one_nano.saturating_sub(zero), Duration::new(0, 1)); - assert_eq!(one_sec.saturating_sub(one_nano), Duration::new(0, 999_999_999)); - assert_eq!(zero.saturating_sub(one_nano), Duration::MIN); - assert_eq!(zero.saturating_sub(one_sec), Duration::MIN); + assert_eq!(Duration::NANOSECOND.saturating_sub(Duration::ZERO), Duration::NANOSECOND); + assert_eq!( + Duration::SECOND.saturating_sub(Duration::NANOSECOND), + Duration::new(0, 999_999_999) + ); + assert_eq!(Duration::ZERO.saturating_sub(Duration::NANOSECOND), Duration::ZERO); + assert_eq!(Duration::ZERO.saturating_sub(Duration::SECOND), Duration::ZERO); } #[test] @@ -337,87 +337,82 @@ fn duration_const() { const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos(); assert_eq!(SUB_SEC_NANOS, 123_456_789); - const ZERO: Duration = Duration::zero(); - assert_eq!(ZERO, Duration::new(0, 0)); - - const IS_ZERO: bool = ZERO.is_zero(); + const IS_ZERO: bool = Duration::ZERO.is_zero(); assert!(IS_ZERO); - const ONE: Duration = Duration::new(1, 0); - - const SECONDS: u64 = ONE.as_secs(); + const SECONDS: u64 = Duration::SECOND.as_secs(); assert_eq!(SECONDS, 1); const FROM_SECONDS: Duration = Duration::from_secs(1); - assert_eq!(FROM_SECONDS, ONE); + assert_eq!(FROM_SECONDS, Duration::SECOND); - const SECONDS_F32: f32 = ONE.as_secs_f32(); + const SECONDS_F32: f32 = Duration::SECOND.as_secs_f32(); assert_eq!(SECONDS_F32, 1.0); const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0); - assert_eq!(FROM_SECONDS_F32, ONE); + assert_eq!(FROM_SECONDS_F32, Duration::SECOND); - const SECONDS_F64: f64 = ONE.as_secs_f64(); + const SECONDS_F64: f64 = Duration::SECOND.as_secs_f64(); assert_eq!(SECONDS_F64, 1.0); const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0); - assert_eq!(FROM_SECONDS_F64, ONE); + assert_eq!(FROM_SECONDS_F64, Duration::SECOND); - const MILLIS: u128 = ONE.as_millis(); + const MILLIS: u128 = Duration::SECOND.as_millis(); assert_eq!(MILLIS, 1_000); const FROM_MILLIS: Duration = Duration::from_millis(1_000); - assert_eq!(FROM_MILLIS, ONE); + assert_eq!(FROM_MILLIS, Duration::SECOND); - const MICROS: u128 = ONE.as_micros(); + const MICROS: u128 = Duration::SECOND.as_micros(); assert_eq!(MICROS, 1_000_000); const FROM_MICROS: Duration = Duration::from_micros(1_000_000); - assert_eq!(FROM_MICROS, ONE); + assert_eq!(FROM_MICROS, Duration::SECOND); - const NANOS: u128 = ONE.as_nanos(); + const NANOS: u128 = Duration::SECOND.as_nanos(); assert_eq!(NANOS, 1_000_000_000); const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000); - assert_eq!(FROM_NANOS, ONE); + assert_eq!(FROM_NANOS, Duration::SECOND); const MAX: Duration = Duration::new(u64::MAX, 999_999_999); - const CHECKED_ADD: Option<Duration> = MAX.checked_add(ONE); + const CHECKED_ADD: Option<Duration> = MAX.checked_add(Duration::SECOND); assert_eq!(CHECKED_ADD, None); - const CHECKED_SUB: Option<Duration> = ZERO.checked_sub(ONE); + const CHECKED_SUB: Option<Duration> = Duration::ZERO.checked_sub(Duration::SECOND); assert_eq!(CHECKED_SUB, None); - const CHECKED_MUL: Option<Duration> = ONE.checked_mul(1); - assert_eq!(CHECKED_MUL, Some(ONE)); + const CHECKED_MUL: Option<Duration> = Duration::SECOND.checked_mul(1); + assert_eq!(CHECKED_MUL, Some(Duration::SECOND)); - const MUL_F32: Duration = ONE.mul_f32(1.0); - assert_eq!(MUL_F32, ONE); + const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0); + assert_eq!(MUL_F32, Duration::SECOND); - const MUL_F64: Duration = ONE.mul_f64(1.0); - assert_eq!(MUL_F64, ONE); + const MUL_F64: Duration = Duration::SECOND.mul_f64(1.0); + assert_eq!(MUL_F64, Duration::SECOND); - const CHECKED_DIV: Option<Duration> = ONE.checked_div(1); - assert_eq!(CHECKED_DIV, Some(ONE)); + const CHECKED_DIV: Option<Duration> = Duration::SECOND.checked_div(1); + assert_eq!(CHECKED_DIV, Some(Duration::SECOND)); - const DIV_F32: Duration = ONE.div_f32(1.0); - assert_eq!(DIV_F32, ONE); + const DIV_F32: Duration = Duration::SECOND.div_f32(1.0); + assert_eq!(DIV_F32, Duration::SECOND); - const DIV_F64: Duration = ONE.div_f64(1.0); - assert_eq!(DIV_F64, ONE); + const DIV_F64: Duration = Duration::SECOND.div_f64(1.0); + assert_eq!(DIV_F64, Duration::SECOND); - const DIV_DURATION_F32: f32 = ONE.div_duration_f32(ONE); + const DIV_DURATION_F32: f32 = Duration::SECOND.div_duration_f32(Duration::SECOND); assert_eq!(DIV_DURATION_F32, 1.0); - const DIV_DURATION_F64: f64 = ONE.div_duration_f64(ONE); + const DIV_DURATION_F64: f64 = Duration::SECOND.div_duration_f64(Duration::SECOND); assert_eq!(DIV_DURATION_F64, 1.0); - const SATURATING_ADD: Duration = MAX.saturating_add(ONE); + const SATURATING_ADD: Duration = MAX.saturating_add(Duration::SECOND); assert_eq!(SATURATING_ADD, MAX); - const SATURATING_SUB: Duration = ZERO.saturating_sub(ONE); - assert_eq!(SATURATING_SUB, ZERO); + const SATURATING_SUB: Duration = Duration::ZERO.saturating_sub(Duration::SECOND); + assert_eq!(SATURATING_SUB, Duration::ZERO); const SATURATING_MUL: Duration = MAX.saturating_mul(2); assert_eq!(SATURATING_MUL, MAX); diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index dd760062380..375b015ccc8 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -316,7 +316,7 @@ pub fn take_alloc_error_hook() -> fn(Layout) { } fn default_alloc_error_hook(layout: Layout) { - dumb_print(format_args!("memory allocation of {} bytes failed", layout.size())); + dumb_print(format_args!("memory allocation of {} bytes failed\n", layout.size())); } #[cfg(not(test))] diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 161bfe3795c..c256f556b3c 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1701,10 +1701,14 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. /// +/// If `src` names a symbolic link, it is platform-specific whether the symbolic +/// link is followed. On platforms where it's possible to not follow it, it is +/// not followed, and the created hard link points to the symbolic link itself. +/// /// # Platform-specific behavior /// -/// This function currently corresponds to the `link` function on Unix -/// and the `CreateHardLink` function on Windows. +/// This function currently corresponds to the `linkat` function with no flags +/// on Unix and the `CreateHardLink` function on Windows. /// Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 38fd470a1c3..0642dca8e48 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1336,3 +1336,54 @@ fn metadata_access_times() { } } } + +/// Test creating hard links to symlinks. +#[test] +fn symlink_hard_link() { + let tmpdir = tmpdir(); + + // Create "file", a file. + check!(fs::File::create(tmpdir.join("file"))); + + // Create "symlink", a symlink to "file". + check!(symlink_file("file", tmpdir.join("symlink"))); + + // Create "hard_link", a hard link to "symlink". + check!(fs::hard_link(tmpdir.join("symlink"), tmpdir.join("hard_link"))); + + // "hard_link" should appear as a symlink. + assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); + + // We sould be able to open "file" via any of the above names. + let _ = check!(fs::File::open(tmpdir.join("file"))); + assert!(fs::File::open(tmpdir.join("file.renamed")).is_err()); + let _ = check!(fs::File::open(tmpdir.join("symlink"))); + let _ = check!(fs::File::open(tmpdir.join("hard_link"))); + + // Rename "file" to "file.renamed". + check!(fs::rename(tmpdir.join("file"), tmpdir.join("file.renamed"))); + + // Now, the symlink and the hard link should be dangling. + assert!(fs::File::open(tmpdir.join("file")).is_err()); + let _ = check!(fs::File::open(tmpdir.join("file.renamed"))); + assert!(fs::File::open(tmpdir.join("symlink")).is_err()); + assert!(fs::File::open(tmpdir.join("hard_link")).is_err()); + + // The symlink and the hard link should both still point to "file". + assert!(fs::read_link(tmpdir.join("file")).is_err()); + assert!(fs::read_link(tmpdir.join("file.renamed")).is_err()); + assert_eq!(check!(fs::read_link(tmpdir.join("symlink"))), Path::new("file")); + assert_eq!(check!(fs::read_link(tmpdir.join("hard_link"))), Path::new("file")); + + // Remove "file.renamed". + check!(fs::remove_file(tmpdir.join("file.renamed"))); + + // Now, we can't open the file by any name. + assert!(fs::File::open(tmpdir.join("file")).is_err()); + assert!(fs::File::open(tmpdir.join("file.renamed")).is_err()); + assert!(fs::File::open(tmpdir.join("symlink")).is_err()); + assert!(fs::File::open(tmpdir.join("hard_link")).is_err()); + + // "hard_link" should still appear as a symlink. + assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index bc218b77c87..fa2608e6fb6 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -257,6 +257,7 @@ #![feature(doc_spotlight)] #![feature(dropck_eyepatch)] #![feature(duration_constants)] +#![feature(duration_zero)] #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index d27d6e2c565..96594095cc3 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1081,7 +1081,20 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; - cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; + cfg_if::cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] { + // VxWorks, Redox, and old versions of Android lack `linkat`, so use + // `link` instead. POSIX leaves it implementation-defined whether + // `link` follows symlinks, so rely on the `symlink_hard_link` test + // in library/std/src/fs/tests.rs to check the behavior. + cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; + } else { + // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives + // us a flag to specify how symlinks should be handled. Pass 0 as + // the flags argument, meaning don't follow symlinks. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; + } + } Ok(()) } diff --git a/library/std/src/sys/unix/process/process_common/tests.rs b/library/std/src/sys/unix/process/process_common/tests.rs index e72fbf0beb4..10aa34e9443 100644 --- a/library/std/src/sys/unix/process/process_common/tests.rs +++ b/library/std/src/sys/unix/process/process_common/tests.rs @@ -14,17 +14,22 @@ macro_rules! t { }; } -// See #14232 for more information, but it appears that signal delivery to a -// newly spawned process may just be raced in the macOS, so to prevent this -// test from being flaky we ignore it on macOS. #[test] -#[cfg_attr(target_os = "macos", ignore)] -// When run under our current QEMU emulation test suite this test fails, -// although the reason isn't very clear as to why. For now this test is -// ignored there. -#[cfg_attr(target_arch = "arm", ignore)] -#[cfg_attr(target_arch = "aarch64", ignore)] -#[cfg_attr(target_arch = "riscv64", ignore)] +#[cfg_attr( + any( + // See #14232 for more information, but it appears that signal delivery to a + // newly spawned process may just be raced in the macOS, so to prevent this + // test from being flaky we ignore it on macOS. + target_os = "macos", + // When run under our current QEMU emulation test suite this test fails, + // although the reason isn't very clear as to why. For now this test is + // ignored there. + target_arch = "arm", + target_arch = "aarch64", + target_arch = "riscv64", + ), + ignore +)] fn test_process_mask() { unsafe { // Test to make sure that a signal mask does not get inherited. diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 64d7898f030..e433f69a8b0 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -322,7 +322,7 @@ impl Instant { /// ``` #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { - self.checked_duration_since(earlier).unwrap_or(Duration::new(0, 0)) + self.checked_duration_since(earlier).unwrap_or_default() } /// Returns the amount of time elapsed since this instant was created. diff --git a/library/std/src/time/tests.rs b/library/std/src/time/tests.rs index 783bf49f315..20c813fdc70 100644 --- a/library/std/src/time/tests.rs +++ b/library/std/src/time/tests.rs @@ -5,7 +5,7 @@ macro_rules! assert_almost_eq { let (a, b) = ($a, $b); if a != b { let (a, b) = if a > b { (a, b) } else { (b, a) }; - assert!(a - Duration::new(0, 1000) <= b, "{:?} is not almost equal to {:?}", a, b); + assert!(a - Duration::from_micros(1) <= b, "{:?} is not almost equal to {:?}", a, b); } }}; } @@ -34,7 +34,7 @@ fn instant_math() { assert_almost_eq!(b - dur, a); assert_almost_eq!(a + dur, b); - let second = Duration::new(1, 0); + let second = Duration::SECOND; assert_almost_eq!(a - second + second, a); assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a); @@ -65,24 +65,24 @@ fn instant_math_is_associative() { #[should_panic] fn instant_duration_since_panic() { let a = Instant::now(); - (a - Duration::new(1, 0)).duration_since(a); + (a - Duration::SECOND).duration_since(a); } #[test] fn instant_checked_duration_since_nopanic() { let now = Instant::now(); - let earlier = now - Duration::new(1, 0); - let later = now + Duration::new(1, 0); + let earlier = now - Duration::SECOND; + let later = now + Duration::SECOND; assert_eq!(earlier.checked_duration_since(now), None); - assert_eq!(later.checked_duration_since(now), Some(Duration::new(1, 0))); - assert_eq!(now.checked_duration_since(now), Some(Duration::new(0, 0))); + assert_eq!(later.checked_duration_since(now), Some(Duration::SECOND)); + assert_eq!(now.checked_duration_since(now), Some(Duration::ZERO)); } #[test] fn instant_saturating_duration_since_nopanic() { let a = Instant::now(); - let ret = (a - Duration::new(1, 0)).saturating_duration_since(a); - assert_eq!(ret, Duration::new(0, 0)); + let ret = (a - Duration::SECOND).saturating_duration_since(a); + assert_eq!(ret, Duration::ZERO); } #[test] @@ -90,7 +90,7 @@ fn system_time_math() { let a = SystemTime::now(); let b = SystemTime::now(); match b.duration_since(a) { - Ok(dur) if dur == Duration::new(0, 0) => { + Ok(Duration::ZERO) => { assert_almost_eq!(a, b); } Ok(dur) => { @@ -106,16 +106,16 @@ fn system_time_math() { } } - let second = Duration::new(1, 0); + let second = Duration::SECOND; assert_almost_eq!(a.duration_since(a - second).unwrap(), second); assert_almost_eq!(a.duration_since(a + second).unwrap_err().duration(), second); assert_almost_eq!(a - second + second, a); assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a); - let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0); + let one_second_from_epoch = UNIX_EPOCH + Duration::SECOND; let one_second_from_epoch2 = - UNIX_EPOCH + Duration::new(0, 500_000_000) + Duration::new(0, 500_000_000); + UNIX_EPOCH + Duration::from_millis(500) + Duration::from_millis(500); assert_eq!(one_second_from_epoch, one_second_from_epoch2); // checked_add_duration will not panic on overflow @@ -141,12 +141,12 @@ fn system_time_elapsed() { #[test] fn since_epoch() { let ts = SystemTime::now(); - let a = ts.duration_since(UNIX_EPOCH + Duration::new(1, 0)).unwrap(); + let a = ts.duration_since(UNIX_EPOCH + Duration::SECOND).unwrap(); let b = ts.duration_since(UNIX_EPOCH).unwrap(); assert!(b > a); - assert_eq!(b - a, Duration::new(1, 0)); + assert_eq!(b - a, Duration::SECOND); - let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30; + let thirty_years = Duration::SECOND * 60 * 60 * 24 * 365 * 30; // Right now for CI this test is run in an emulator, and apparently the // aarch64 emulator's sense of time is that we're still living in the diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index 7bb4e504275..a103c9fb0b7 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `x.py check` needs opt-in to check tests (--all-targets) [#77473](https://github.com/rust-lang/rust/pull/77473) - The default bootstrap profiles are now located at `bootstrap/defaults/config.$PROFILE.toml` (previously they were located at `bootstrap/defaults/config.toml.$PROFILE`) [#77558](https://github.com/rust-lang/rust/pull/77558) +- If you have Rust already installed, `x.py` will now infer the host target + from the default rust toolchain. [#78513](https://github.com/rust-lang/rust/pull/78513) ## [Version 2] - 2020-09-25 diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 87e15363818..54d0a23dec5 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -187,8 +187,23 @@ def format_build_time(duration): return str(datetime.timedelta(seconds=int(duration))) -def default_build_triple(): +def default_build_triple(verbose): """Build triple as in LLVM""" + # If the user already has a host build triple with an existing `rustc` + # install, use their preference. This fixes most issues with Windows builds + # being detected as GNU instead of MSVC. + try: + version = subprocess.check_output(["rustc", "--version", "--verbose"]) + host = next(x for x in version.split('\n') if x.startswith("host: ")) + triple = host.split("host: ")[1] + if verbose: + print("detected default triple {}".format(triple)) + return triple + except Exception as e: + if verbose: + print("rustup not detected: {}".format(e)) + print("falling back to auto-detect") + default_encoding = sys.getdefaultencoding() required = sys.platform != 'win32' ostype = require(["uname", "-s"], exit=required) @@ -831,7 +846,7 @@ class RustBuild(object): config = self.get_toml('build') if config: return config - return default_build_triple() + return default_build_triple(self.verbose) def check_submodule(self, module, slow_submodules): if not slow_submodules: diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b48508f2c24..3d724c14842 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -264,7 +264,7 @@ impl<'a> ShouldRun<'a> { /// `all_krates` should probably be removed at some point. pub fn all_krates(mut self, name: &str) -> Self { let mut set = BTreeSet::new(); - for krate in self.builder.in_tree_crates(name) { + for krate in self.builder.in_tree_crates(name, None) { let path = krate.local_path(self.builder); set.insert(path); } @@ -277,7 +277,7 @@ impl<'a> ShouldRun<'a> { /// /// `make_run` will be called separately for each matching command-line path. pub fn krate(mut self, name: &str) -> Self { - for krate in self.builder.in_tree_crates(name) { + for krate in self.builder.in_tree_crates(name, None) { let path = krate.local_path(self.builder); self.paths.insert(PathSet::one(path)); } @@ -1178,6 +1178,14 @@ impl<'a> Builder<'a> { } } + // Compile everything except libraries and proc macros with the more + // efficient initial-exec TLS model. This doesn't work with `dlopen`, + // so we can't use it by default in general, but we can use it for tools + // and our own internal libraries. + if !mode.must_support_dlopen() { + rustflags.arg("-Ztls-model=initial-exec"); + } + if self.config.incremental { cargo.env("CARGO_INCREMENTAL", "1"); } else { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2e3cfc98c8c..ecca12108b6 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -108,7 +108,7 @@ impl Step for Std { // Explicitly pass -p for all dependencies krates -- this will force cargo // to also check the tests/benches/examples for these crates, rather // than just the leaf crate. - for krate in builder.in_tree_crates("test") { + for krate in builder.in_tree_crates("test", Some(target)) { cargo.arg("-p").arg(krate.name); } @@ -172,7 +172,7 @@ impl Step for Rustc { // Explicitly pass -p for all compiler krates -- this will force cargo // to also check the tests/benches/examples for these crates, rather // than just the leaf crate. - for krate in builder.in_tree_crates("rustc-main") { + for krate in builder.in_tree_crates("rustc-main", Some(target)) { cargo.arg("-p").arg(krate.name); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ed9b9108586..cdad1cb4d49 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -143,7 +143,7 @@ fn copy_third_party_objects( } } - if builder.config.sanitizers && compiler.stage != 0 { + if builder.config.sanitizers_enabled(target) && compiler.stage != 0 { // The sanitizers are only copied in stage1 or above, // to avoid creating dependency on LLVM. target_deps.extend( @@ -251,7 +251,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car .arg("--features") .arg(features); } else { - let mut features = builder.std_features(); + let mut features = builder.std_features(target); features.push_str(compiler_builtins_c_feature); cargo diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 40ea9afb6f6..c0753d88504 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -99,6 +99,7 @@ pub struct Config { pub llvm_version_suffix: Option<String>, pub llvm_use_linker: Option<String>, pub llvm_allow_old_toolchain: Option<bool>, + pub llvm_polly: Option<bool>, pub llvm_from_ci: bool, pub use_lld: bool, @@ -278,6 +279,8 @@ pub struct Target { pub ranlib: Option<PathBuf>, pub linker: Option<PathBuf>, pub ndk: Option<PathBuf>, + pub sanitizers: bool, + pub profiler: bool, pub crt_static: Option<bool>, pub musl_root: Option<PathBuf>, pub musl_libdir: Option<PathBuf>, @@ -418,6 +421,7 @@ struct Llvm { use_libcxx: Option<bool>, use_linker: Option<String>, allow_old_toolchain: Option<bool>, + polly: Option<bool>, download_ci_llvm: Option<StringOrBool>, } @@ -501,6 +505,8 @@ struct TomlTarget { llvm_config: Option<String>, llvm_filecheck: Option<String>, android_ndk: Option<String>, + sanitizers: Option<bool>, + profiler: Option<bool>, crt_static: Option<bool>, musl_root: Option<String>, musl_libdir: Option<String>, @@ -762,6 +768,7 @@ impl Config { set(&mut config.llvm_use_libcxx, llvm.use_libcxx); config.llvm_use_linker = llvm.use_linker.clone(); config.llvm_allow_old_toolchain = llvm.allow_old_toolchain; + config.llvm_polly = llvm.polly; config.llvm_from_ci = match llvm.download_ci_llvm { Some(StringOrBool::String(s)) => { assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s); @@ -795,6 +802,7 @@ impl Config { check_ci_llvm!(llvm.use_libcxx); check_ci_llvm!(llvm.use_linker); check_ci_llvm!(llvm.allow_old_toolchain); + check_ci_llvm!(llvm.polly); // CI-built LLVM is shared config.llvm_link_shared = true; @@ -886,6 +894,8 @@ impl Config { target.musl_libdir = cfg.musl_libdir.map(PathBuf::from); target.wasi_root = cfg.wasi_root.map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from); + target.sanitizers = cfg.sanitizers.unwrap_or(build.sanitizers.unwrap_or_default()); + target.profiler = cfg.profiler.unwrap_or(build.profiler.unwrap_or_default()); config.target_config.insert(TargetSelection::from_user(&triple), target); } @@ -995,6 +1005,22 @@ impl Config { self.verbose > 1 } + pub fn sanitizers_enabled(&self, target: TargetSelection) -> bool { + self.target_config.get(&target).map(|t| t.sanitizers).unwrap_or(self.sanitizers) + } + + pub fn any_sanitizers_enabled(&self) -> bool { + self.target_config.values().any(|t| t.sanitizers) || self.sanitizers + } + + pub fn profiler_enabled(&self, target: TargetSelection) -> bool { + self.target_config.get(&target).map(|t| t.profiler).unwrap_or(self.profiler) + } + + pub fn any_profiler_enabled(&self) -> bool { + self.target_config.values().any(|t| t.profiler) || self.profiler + } + pub fn llvm_enabled(&self) -> bool { self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index e156952d56f..322e9d69232 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -266,7 +266,7 @@ config = {} def build(): if 'build' in known_args: return known_args['build'][-1][1] - return bootstrap.default_build_triple() + return bootstrap.default_build_triple(verbose=False) def set(key, value): diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index bdab12db435..5ce5737f318 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1040,6 +1040,30 @@ impl Step for Src { builder.copy(&builder.src.join(file), &dst_src.join(file)); } + // libtest includes std and everything else, so vendoring it + // creates exactly what's needed for `cargo -Zbuild-std` or any + // other analysis of the stdlib's source. Cargo also needs help + // finding the lock, so we copy it to libtest temporarily. + // + // Note that this requires std to only have one version of each + // crate. e.g. two versions of getopts won't be patchable. + let dst_libtest = dst_src.join("library/test"); + let dst_vendor = dst_src.join("vendor"); + let root_lock = dst_src.join("Cargo.lock"); + let temp_lock = dst_libtest.join("Cargo.lock"); + + // `cargo vendor` will delete everything from the lockfile that + // isn't used by libtest, so we need to not use any links! + builder.really_copy(&root_lock, &temp_lock); + + let mut cmd = Command::new(&builder.initial_cargo); + cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libtest); + builder.info("Dist src"); + let _time = timeit(builder); + builder.run(&mut cmd); + + builder.remove(&temp_lock); + // Create source tarball in rust-installer format let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -1056,8 +1080,6 @@ impl Step for Src { .arg("--component-name=rust-src") .arg("--legacy-manifest-dirs=rustlib,cargo"); - builder.info("Dist src"); - let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index aa670bd9a2e..af7f7eff894 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -535,8 +535,12 @@ impl Step for Rustc { // Find dependencies for top level crates. let mut compiler_crates = HashSet::new(); for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { - compiler_crates - .extend(builder.in_tree_crates(root_crate).into_iter().map(|krate| krate.name)); + compiler_crates.extend( + builder + .in_tree_crates(root_crate, Some(target)) + .into_iter() + .map(|krate| krate.name), + ); } for krate in &compiler_crates { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 0878b0ff789..9f037890483 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -169,17 +169,18 @@ pub use crate::config::Config; pub use crate::flags::Subcommand; const LLVM_TOOLS: &[&str] = &[ - "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility - "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume - "llvm-objdump", // used to disassemble programs + "llvm-cov", // used to generate coverage report + "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility + "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume + "llvm-objdump", // used to disassemble programs "llvm-profdata", // used to inspect and merge files generated by profiles - "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide - "llvm-size", // used to prints the size of the linker sections of a program - "llvm-strip", // used to discard symbols from binary files to reduce their size - "llvm-ar", // used for creating and modifying archive files - "llvm-dis", // used to disassemble LLVM bitcode - "llc", // used to compile LLVM bytecode - "opt", // used to optimize LLVM bytecode + "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide + "llvm-size", // used to prints the size of the linker sections of a program + "llvm-strip", // used to discard symbols from binary files to reduce their size + "llvm-ar", // used for creating and modifying archive files + "llvm-dis", // used to disassemble LLVM bitcode + "llc", // used to compile LLVM bytecode + "opt", // used to optimize LLVM bytecode ]; pub const VERSION: usize = 2; @@ -332,6 +333,10 @@ impl Mode { pub fn is_tool(&self) -> bool { matches!(self, Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd) } + + pub fn must_support_dlopen(&self) -> bool { + matches!(self, Mode::Std | Mode::Codegen) + } } impl Build { @@ -537,7 +542,7 @@ impl Build { /// Gets the space-separated set of activated features for the standard /// library. - fn std_features(&self) -> String { + fn std_features(&self, target: TargetSelection) -> String { let mut features = "panic-unwind".to_string(); match self.config.llvm_libunwind.unwrap_or_default() { @@ -548,7 +553,7 @@ impl Build { if self.config.backtrace { features.push_str(" backtrace"); } - if self.config.profiler { + if self.config.profiler_enabled(target) { features.push_str(" profiler"); } features @@ -1111,7 +1116,7 @@ impl Build { /// Returns a Vec of all the dependencies of the given root crate, /// including transitive dependencies and the root itself. Only includes /// "local" crates (those in the local source tree, not from a registry). - fn in_tree_crates(&self, root: &str) -> Vec<&Crate> { + fn in_tree_crates(&self, root: &str, target: Option<TargetSelection>) -> Vec<&Crate> { let mut ret = Vec::new(); let mut list = vec![INTERNER.intern_str(root)]; let mut visited = HashSet::new(); @@ -1132,7 +1137,10 @@ impl Build { // metadata::build. if visited.insert(dep) && dep != "build_helper" - && (dep != "profiler_builtins" || self.config.profiler) + && (dep != "profiler_builtins" + || target + .map(|t| self.config.profiler_enabled(t)) + .unwrap_or(self.config.any_profiler_enabled())) && (dep != "rustc_codegen_llvm" || self.config.llvm_enabled()) { list.push(*dep); @@ -1167,6 +1175,27 @@ impl Build { paths } + /// Copies a file from `src` to `dst` and doesn't use links, so + /// that the copy can be modified without affecting the original. + pub fn really_copy(&self, src: &Path, dst: &Path) { + if self.config.dry_run { + return; + } + self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst)); + if src == dst { + return; + } + let _ = fs::remove_file(&dst); + let metadata = t!(src.symlink_metadata()); + if let Err(e) = fs::copy(src, dst) { + panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e) + } + t!(fs::set_permissions(dst, metadata.permissions())); + let atime = FileTime::from_last_access_time(&metadata); + let mtime = FileTime::from_last_modification_time(&metadata); + t!(filetime::set_file_times(dst, atime, mtime)); + } + /// Copies a file from `src` to `dst` pub fn copy(&self, src: &Path, dst: &Path) { if self.config.dry_run { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 37d6fab070b..6dc83c7d70a 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -257,6 +257,10 @@ impl Step for Llvm { enabled_llvm_projects.push("compiler-rt"); } + if let Some(true) = builder.config.llvm_polly { + enabled_llvm_projects.push("polly"); + } + // We want libxml to be disabled. // See https://github.com/rust-lang/rust/pull/50104 cfg.define("LLVM_ENABLE_LIBXML2", "OFF"); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 6826d177a4a..4cfcf6ca407 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -91,7 +91,7 @@ pub fn check(build: &mut Build) { .unwrap_or(true) }) .any(|build_llvm_ourselves| build_llvm_ourselves); - if building_llvm || build.config.sanitizers { + if building_llvm || build.config.any_sanitizers_enabled() { cmd_finder.must_have("cmake"); } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 2b87c4b91af..60808dcba61 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1271,11 +1271,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.env("RUSTC_BOOTSTRAP", "1"); builder.add_rust_test_threads(&mut cmd); - if builder.config.sanitizers { + if builder.config.sanitizers_enabled(target) { cmd.env("RUSTC_SANITIZER_SUPPORT", "1"); } - if builder.config.profiler { + if builder.config.profiler_enabled(target) { cmd.env("RUSTC_PROFILER_SUPPORT", "1"); } @@ -1591,7 +1591,7 @@ impl Step for CrateLibrustc { let builder = run.builder; let compiler = builder.compiler(builder.top_stage, run.build_triple()); - for krate in builder.in_tree_crates("rustc-main") { + for krate in builder.in_tree_crates("rustc-main", Some(run.target)) { if krate.path.ends_with(&run.path) { let test_kind = builder.kind.into(); @@ -1698,7 +1698,7 @@ impl Step for Crate { }); }; - for krate in builder.in_tree_crates("test") { + for krate in builder.in_tree_crates("test", Some(run.target)) { if krate.path.ends_with(&run.path) { make(Mode::Std, krate); } diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile index df65f9df441..95c54ca1abc 100644 --- a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile @@ -35,6 +35,5 @@ ENV HOSTS=aarch64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-profiler \ - --enable-sanitizers \ - --disable-docs + --enable-sanitizers ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile deleted file mode 100644 index 7db6e58c4d6..00000000000 --- a/src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile +++ /dev/null @@ -1,34 +0,0 @@ -FROM ubuntu:18.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - clang \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3 \ - git \ - cmake \ - sudo \ - bzip2 \ - xz-utils \ - wget \ - libssl-dev \ - pkg-config - -COPY scripts/freebsd-toolchain.sh /tmp/ -RUN /tmp/freebsd-toolchain.sh i686 - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV \ - AR_i686_unknown_freebsd=i686-unknown-freebsd11-ar \ - CC_i686_unknown_freebsd=i686-unknown-freebsd11-clang \ - CXX_i686_unknown_freebsd=i686-unknown-freebsd11-clang++ - -ENV HOSTS=i686-unknown-freebsd - -ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs -ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 47a66f74808..b8b81ab327b 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -48,6 +48,9 @@ ENV \ CFLAGS_x86_64_fortanix_unknown_sgx="-mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ CXX_x86_64_fortanix_unknown_sgx=x86_64-fortanix-unknown-sgx-clang++-11 \ CXXFLAGS_x86_64_fortanix_unknown_sgx="-mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ + AR_i686_unknown_freebsd=i686-unknown-freebsd11-ar \ + CC_i686_unknown_freebsd=i686-unknown-freebsd11-clang \ + CXX_i686_unknown_freebsd=i686-unknown-freebsd11-clang++ \ CC=gcc-7 \ CXX=g++-7 @@ -74,6 +77,9 @@ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/ RUN /tmp/build-wasi-toolchain.sh +COPY scripts/freebsd-toolchain.sh /tmp/ +RUN /tmp/freebsd-toolchain.sh i686 + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -99,6 +105,7 @@ ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi +ENV TARGETS=$TARGETS,i686-unknown-freebsd # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-7 (for gnux32) but not in the search path of the diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh index 9d7461ebee3..fcf869b68be 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh @@ -29,7 +29,8 @@ mkdir ../gcc-build cd ../gcc-build hide_output ../gcc-$GCC/configure \ --prefix=/rustroot \ - --enable-languages=c,c++ + --enable-languages=c,c++ \ + --disable-gnu-unique-object hide_output make -j10 hide_output make install ln -s gcc /rustroot/bin/cc diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 4cbb7b62cd6..031000d147c 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -301,6 +301,9 @@ jobs: # Linux/Docker builders # ############################# + - name: aarch64-gnu + <<: *job-aarch64-linux + - name: arm-android <<: *job-linux-xl @@ -325,9 +328,6 @@ jobs: - name: dist-i586-gnu-i586-i686-musl <<: *job-linux-xl - - name: dist-i686-freebsd - <<: *job-linux-xl - - name: dist-i686-linux <<: *job-linux-xl @@ -635,23 +635,6 @@ jobs: SCRIPT: python x.py dist <<: *job-windows-xl - auto-fallible: - <<: *base-ci-job - name: auto-fallible - env: - <<: [*shared-ci-variables, *dummy-variables] - if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust' - strategy: - fail-fast: false - matrix: - include: - ############################# - # Linux/Docker builders # - ############################# - - - name: aarch64-gnu - <<: *job-aarch64-linux - try: <<: *base-ci-job name: try diff --git a/src/ci/scripts/should-skip-this.sh b/src/ci/scripts/should-skip-this.sh index f945db0ada2..36bf4368990 100755 --- a/src/ci/scripts/should-skip-this.sh +++ b/src/ci/scripts/should-skip-this.sh @@ -14,6 +14,10 @@ elif git diff HEAD^ | grep --quiet "^index .* 160000"; then # Submodules pseudo-files inside git have the 160000 permissions, so when # those files are present in the diff a submodule was updated. echo "Executing the job since submodules are updated" +elif git diff --name-only HEAD^ | grep --quiet src/tools/clippy; then + # There is not an easy blanket search for subtrees. For now, manually list + # clippy. + echo "Executing the job since clippy subtree was updated" else echo "Not executing this job since no submodules were updated" ciCommandSetEnv SKIP_JOB 1 diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 85c6f91f085..215e5d3d104 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -34,6 +34,7 @@ Specifically they will each satisfy the following requirements: target | std | host | notes -------|-----|------|------- +`aarch64-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (kernel 4.2, glibc 2.17+) [^missing-stack-probes] `i686-pc-windows-gnu` | ✓ | ✓ | 32-bit MinGW (Windows 7+) `i686-pc-windows-msvc` | ✓ | ✓ | 32-bit MSVC (Windows 7+) `i686-unknown-linux-gnu` | ✓ | ✓ | 32-bit Linux (kernel 2.6.32+, glibc 2.11+) @@ -42,6 +43,12 @@ target | std | host | notes `x86_64-pc-windows-msvc` | ✓ | ✓ | 64-bit MSVC (Windows 7+) `x86_64-unknown-linux-gnu` | ✓ | ✓ | 64-bit Linux (kernel 2.6.32+, glibc 2.11+) +[^missing-stack-probes]: Stack probes support is missing on + `aarch64-unknown-linux-gnu`, but it's planned to be implemented in the near + future. The implementation is tracked on [issue #77071][77071]. + +[77071]: https://github.com/rust-lang/rust/issues/77071 + ## Tier 2 Tier 2 platforms can be thought of as "guaranteed to build". Automated tests @@ -62,7 +69,6 @@ target | std | host | notes `aarch64-fuchsia` | ✓ | | ARM64 Fuchsia `aarch64-linux-android` | ✓ | | ARM64 Android `aarch64-pc-windows-msvc` | ✓ | ✓ | ARM64 Windows MSVC -`aarch64-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (kernel 4.2, glibc 2.17) `aarch64-unknown-linux-musl` | ✓ | ✓ | ARM64 Linux with MUSL `aarch64-unknown-none` | * | | Bare ARM64, hardfloat `aarch64-unknown-none-softfloat` | * | | Bare ARM64, softfloat @@ -88,7 +94,7 @@ target | std | host | notes `i586-unknown-linux-gnu` | ✓ | | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23) `i586-unknown-linux-musl` | ✓ | | 32-bit Linux w/o SSE, MUSL `i686-linux-android` | ✓ | | 32-bit x86 Android -`i686-unknown-freebsd` | ✓ | ✓ | 32-bit FreeBSD +`i686-unknown-freebsd` | ✓ | | 32-bit FreeBSD `i686-unknown-linux-musl` | ✓ | | 32-bit Linux with MUSL `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) `mips-unknown-linux-musl` | ✓ | | MIPS Linux with MUSL diff --git a/src/doc/unstable-book/src/language-features/cfg-panic.md b/src/doc/unstable-book/src/language-features/cfg-panic.md new file mode 100644 index 00000000000..f5b73128ad6 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/cfg-panic.md @@ -0,0 +1,38 @@ +# `cfg_panic` + +The tracking issue for this feature is: [#77443] + +[#77443]: https://github.com/rust-lang/rust/issues/77443 + +------------------------ + +The `cfg_panic` feature makes it possible to execute different code +depending on the panic strategy. + +Possible values at the moment are `"unwind"` or `"abort"`, although +it is possible that new panic strategies may be added to Rust in the +future. + +## Examples + +```rust +#![feature(cfg_panic)] + +#[cfg(panic = "unwind")] +fn a() { + // ... +} + +#[cfg(not(panic = "unwind"))] +fn a() { + // ... +} + +fn b() { + if cfg!(panic = "abort") { + // ... + } else { + // ... + } +} +``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bfc74705818..366548d5b5f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -935,8 +935,7 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) { .iter() .enumerate() .map(|(i, ty)| { - let mut name = - self.1.get(i).map(|ident| ident.to_string()).unwrap_or(String::new()); + let mut name = self.1.get(i).map(|ident| ident.to_string()).unwrap_or_default(); if name.is_empty() { name = "_".to_string(); } @@ -1967,10 +1966,15 @@ impl Clean<Span> for rustc_span::Span { return Span::empty(); } + // Get the macro invocation instead of the definition, + // in case the span is result of a macro expansion. + // (See rust-lang/rust#39726) + let span = self.source_callsite(); + let sm = cx.sess().source_map(); - let filename = sm.span_to_filename(*self); - let lo = sm.lookup_char_pos(self.lo()); - let hi = sm.lookup_char_pos(self.hi()); + let filename = sm.span_to_filename(span); + let lo = sm.lookup_char_pos(span.lo()); + let hi = sm.lookup_char_pos(span.hi()); Span { filename, cnum: lo.file.cnum, @@ -1978,7 +1982,7 @@ impl Clean<Span> for rustc_span::Span { locol: lo.col.to_usize(), hiline: hi.line, hicol: hi.col.to_usize(), - original: *self, + original: span, } } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 5eca54199d6..4cad6418d6a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -322,7 +322,8 @@ pub fn run_core( let cpath = Some(input.clone()); let input = Input::File(input); - let intra_link_resolution_failure_name = lint::builtin::BROKEN_INTRA_DOC_LINKS.name; + let broken_intra_doc_links = lint::builtin::BROKEN_INTRA_DOC_LINKS.name; + let private_intra_doc_links = lint::builtin::PRIVATE_INTRA_DOC_LINKS.name; let missing_docs = rustc_lint::builtin::MISSING_DOCS.name; let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name; let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name; @@ -336,7 +337,8 @@ pub fn run_core( // In addition to those specific lints, we also need to allow those given through // command line, otherwise they'll get ignored and we don't want that. let lints_to_show = vec![ - intra_link_resolution_failure_name.to_owned(), + broken_intra_doc_links.to_owned(), + private_intra_doc_links.to_owned(), missing_docs.to_owned(), missing_doc_example.to_owned(), private_doc_tests.to_owned(), @@ -349,9 +351,8 @@ pub fn run_core( ]; let (lint_opts, lint_caps) = init_lints(lints_to_show, lint_opts, |lint| { - if lint.name == intra_link_resolution_failure_name - || lint.name == invalid_codeblock_attributes_name - { + // FIXME: why is this necessary? + if lint.name == broken_intra_doc_links || lint.name == invalid_codeblock_attributes_name { None } else { Some((lint.name_lower(), lint::Allow)) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index cf785d362cd..add28de17ed 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -128,7 +128,7 @@ pub fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { .module .as_ref() .map(|module| shorten(plain_text_summary(module.doc_value()))) - .unwrap_or(String::new()); + .unwrap_or_default(); #[derive(Serialize)] struct CrateData<'a> { diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/settings.css index 4bacd7b245b..fb8990b30e2 100644 --- a/src/librustdoc/html/static/settings.css +++ b/src/librustdoc/html/static/settings.css @@ -26,7 +26,8 @@ } .toggle input { - display: none; + opacity: 0; + position: absolute; } .select-wrapper { @@ -90,7 +91,7 @@ input:checked + .slider { } input:focus + .slider { - box-shadow: 0 0 1px #2196F3; + box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); } input:checked + .slider:before { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8be9482acff..c9d4f51cbf3 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1,3 +1,7 @@ +//! This module implements [RFC 1946]: Intra-rustdoc-links +//! +//! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md + use rustc_ast as ast; use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; @@ -27,7 +31,7 @@ use std::cell::Cell; use std::mem; use std::ops::Range; -use crate::clean::*; +use crate::clean::{self, Crate, GetDefId, Import, Item, ItemLink, PrimitiveType}; use crate::core::DocContext; use crate::fold::DocFolder; use crate::html::markdown::markdown_links; @@ -42,10 +46,10 @@ pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass { }; pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate { - let mut coll = LinkCollector::new(cx); - coll.fold_crate(krate) + LinkCollector::new(cx).fold_crate(krate) } +/// Top-level errors emitted by this pass. enum ErrorKind<'a> { Resolve(Box<ResolutionFailure<'a>>), AnchorFailure(AnchorFailure), @@ -58,18 +62,37 @@ impl<'a> From<ResolutionFailure<'a>> for ErrorKind<'a> { } #[derive(Debug)] +/// A link failed to resolve. enum ResolutionFailure<'a> { /// This resolved, but with the wrong namespace. - /// `Namespace` is the expected namespace (as opposed to the actual). - WrongNamespace(Res, Namespace), + /// + /// `Namespace` is the namespace specified with a disambiguator + /// (as opposed to the actual namespace of the `Res`). + WrongNamespace(Res, /* disambiguated */ Namespace), /// The link failed to resolve. `resolution_failure` should look to see if there's /// a more helpful error that can be given. - NotResolved { module_id: DefId, partial_res: Option<Res>, unresolved: Cow<'a, str> }, - /// should not ever happen + NotResolved { + /// The scope the link was resolved in. + module_id: DefId, + /// If part of the link resolved, this has the `Res`. + /// + /// In `[std::io::Error::x]`, `std::io::Error` would be a partial resolution. + partial_res: Option<Res>, + /// The remaining unresolved path segments. + /// + /// In `[std::io::Error::x]`, `x` would be unresolved. + unresolved: Cow<'a, str>, + }, + /// This happens when rustdoc can't determine the parent scope for an item. + /// + /// It is always a bug in rustdoc. NoParentItem, /// This link has malformed generic parameters; e.g., the angle brackets are unbalanced. MalformedGenerics(MalformedGenerics), - /// used to communicate that this should be ignored, but shouldn't be reported to the user + /// Used to communicate that this should be ignored, but shouldn't be reported to the user + /// + /// This happens when there is no disambiguator and one of the namespaces + /// failed to resolve. Dummy, } @@ -115,7 +138,9 @@ enum MalformedGenerics { } impl ResolutionFailure<'a> { - // This resolved fully (not just partially) but is erroneous for some other reason + /// This resolved fully (not just partially) but is erroneous for some other reason + /// + /// Returns the full resolution of the link, if present. fn full_res(&self) -> Option<Res> { match self { Self::WrongNamespace(res, _) => Some(*res), @@ -125,13 +150,30 @@ impl ResolutionFailure<'a> { } enum AnchorFailure { + /// User error: `[std#x#y]` is not valid MultipleAnchors, + /// The anchor provided by the user conflicts with Rustdoc's generated anchor. + /// + /// This is an unfortunate state of affairs. Not every item that can be + /// linked to has its own page; sometimes it is a subheading within a page, + /// like for associated items. In those cases, rustdoc uses an anchor to + /// link to the subheading. Since you can't have two anchors for the same + /// link, Rustdoc disallows having a user-specified anchor. + /// + /// Most of the time this is fine, because you can just link to the page of + /// the item if you want to provide your own anchor. For primitives, though, + /// rustdoc uses the anchor as a side channel to know which page to link to; + /// it doesn't show up in the generated link. Ideally, rustdoc would remove + /// this limitation, allowing you to link to subheaders on primitives. RustdocAnchorConflict(Res), } struct LinkCollector<'a, 'tcx> { cx: &'a DocContext<'tcx>, - // NOTE: this may not necessarily be a module in the current crate + /// A stack of modules used to decide what scope to resolve in. + /// + /// The last module will be used if the parent scope of the current item is + /// unknown. mod_ids: Vec<DefId>, /// This is used to store the kind of associated items, /// because `clean` and the disambiguator code expect them to be different. @@ -144,6 +186,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { LinkCollector { cx, mod_ids: Vec::new(), kind_side_channel: Cell::new(None) } } + /// Given a full link, parse it as an [enum struct variant]. + /// + /// In particular, this will return an error whenever there aren't three + /// full path segments left in the link. + /// + /// [enum struct variant]: hir::VariantData::Struct fn variant_field( &self, path_str: &'path str, @@ -235,6 +283,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } } + /// Given a primitive type, try to resolve an associated item. + /// + /// HACK(jynelson): `item_str` is passed in instead of derived from `item_name` so the + /// lifetimes on `&'path` will work. fn resolve_primitive_associated_item( &self, prim_ty: hir::PrimTy, @@ -286,7 +338,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } /// Resolves a string as a macro. - fn macro_resolve( + /// + /// FIXME(jynelson): Can this be unified with `resolve()`? + fn resolve_macro( &self, path_str: &'a str, module_id: DefId, @@ -294,6 +348,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { let cx = self.cx; let path = ast::Path::from_ident(Ident::from_str(path_str)); cx.enter_resolver(|resolver| { + // FIXME(jynelson): does this really need 3 separate lookups? if let Ok((Some(ext), res)) = resolver.resolve_macro_path( &path, None, @@ -326,6 +381,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }) } + /// Convenience wrapper around `resolve_str_path_error`. + /// + /// This also handles resolving `true` and `false` as booleans. + /// NOTE: `resolve_str_path_error` knows only about paths, not about types. + /// Associated items will never be resolved by this function. fn resolve_path(&self, path_str: &str, ns: Namespace, module_id: DefId) -> Option<Res> { let result = self.cx.enter_resolver(|resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) @@ -339,12 +399,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } } - /// Resolves a string as a path within a particular namespace. Also returns an optional - /// URL fragment in the case of variants and methods. + /// Resolves a string as a path within a particular namespace. Returns an + /// optional URL fragment in the case of variants and methods. fn resolve<'path>( &self, path_str: &'path str, ns: Namespace, + // FIXME(#76467): This is for `Self`, and it's wrong. current_item: &Option<String>, module_id: DefId, extra_fragment: &Option<String>, @@ -353,15 +414,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { if let Some(res) = self.resolve_path(path_str, ns, module_id) { match res { + // FIXME(#76467): make this fallthrough to lookup the associated + // item a separate function. Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => { assert_eq!(ns, ValueNS); - // Fall through: In case this is a trait item, skip the - // early return and try looking for the trait. } Res::Def(DefKind::AssocTy, _) => { assert_eq!(ns, TypeNS); - // Fall through: In case this is a trait item, skip the - // early return and try looking for the trait. } Res::Def(DefKind::Variant, _) => { return handle_variant(cx, res, extra_fragment); @@ -410,7 +469,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { })?; // FIXME: are these both necessary? - let ty_res = if let Some(ty_res) = is_primitive(&path_root, TypeNS) + let ty_res = if let Some(ty_res) = resolve_primitive(&path_root, TypeNS) .map(|(_, res)| res) .or_else(|| self.resolve_path(&path_root, TypeNS, module_id)) { @@ -452,8 +511,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // There should only ever be one associated item that matches from any inherent impl .next() // Check if item_name belongs to `impl SomeTrait for SomeItem` - // This gives precedence to `impl SomeItem`: - // Although having both would be ambiguous, use impl version for compat. sake. + // FIXME(#74563): This gives precedence to `impl SomeItem`: + // Although having both would be ambiguous, use impl version for compatibility's sake. // To handle that properly resolve() would have to support // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn) .or_else(|| { @@ -480,6 +539,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }) } else if ns == Namespace::ValueNS { debug!("looking for variants or fields named {} for {:?}", item_name, did); + // FIXME(jynelson): why is this different from + // `variant_field`? match cx.tcx.type_of(did).kind() { ty::Adt(def, _) => { let field = if def.is_enum() { @@ -577,7 +638,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ) -> Option<Res> { // resolve() can't be used for macro namespace let result = match ns { - Namespace::MacroNS => self.macro_resolve(path_str, module_id).map_err(ErrorKind::from), + Namespace::MacroNS => self.resolve_macro(path_str, module_id).map_err(ErrorKind::from), Namespace::TypeNS | Namespace::ValueNS => self .resolve(path_str, ns, current_item, module_id, extra_fragment) .map(|(res, _)| res), @@ -593,6 +654,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } } +/// Look to see if a resolved item has an associated item named `item_name`. +/// +/// Given `[std::io::Error::source]`, where `source` is unresolved, this would +/// find `std::error::Error::source` and return +/// `<io::Error as error::Error>::source`. fn resolve_associated_trait_item( did: DefId, module: DefId, @@ -601,12 +667,12 @@ fn resolve_associated_trait_item( cx: &DocContext<'_>, ) -> Option<(ty::AssocKind, DefId)> { let ty = cx.tcx.type_of(did); - // First consider automatic impls: `impl From<T> for T` + // First consider blanket impls: `impl From<T> for T` let implicit_impls = crate::clean::get_auto_trait_and_blanket_impls(cx, ty, did); let mut candidates: Vec<_> = implicit_impls .flat_map(|impl_outer| { match impl_outer.inner { - ImplItem(impl_) => { + clean::ImplItem(impl_) => { debug!("considering auto or blanket impl for trait {:?}", impl_.trait_); // Give precedence to methods that were overridden if !impl_.provided_trait_methods.contains(&*item_name.as_str()) { @@ -669,7 +735,7 @@ fn resolve_associated_trait_item( .map(|assoc| (assoc.kind, assoc.def_id)) })); } - // FIXME: warn about ambiguity + // FIXME(#74563): warn about ambiguity debug!("the candidates were {:?}", candidates); candidates.pop() } @@ -719,20 +785,15 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx iter.collect() } -/// Check for resolve collisions between a trait and its derive +/// Check for resolve collisions between a trait and its derive. /// -/// These are common and we should just resolve to the trait in that case +/// These are common and we should just resolve to the trait in that case. fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_>>>) -> bool { - if let PerNS { + matches!(*ns, PerNS { type_ns: Ok((Res::Def(DefKind::Trait, _), _)), macro_ns: Ok((Res::Def(DefKind::Macro(MacroKind::Derive), _), _)), .. - } = *ns - { - true - } else { - false - } + }) } impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { @@ -772,29 +833,30 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } let current_item = match item.inner { - ModuleItem(..) => { + clean::ModuleItem(..) => { if item.attrs.inner_docs { if item.def_id.is_top_level_module() { item.name.clone() } else { None } } else { match parent_node.or(self.mod_ids.last().copied()) { Some(parent) if !parent.is_top_level_module() => { - // FIXME: can we pull the parent module's name from elsewhere? Some(self.cx.tcx.item_name(parent).to_string()) } _ => None, } } } - ImplItem(Impl { ref for_, .. }) => { + clean::ImplItem(clean::Impl { ref for_, .. }) => { for_.def_id().map(|did| self.cx.tcx.item_name(did).to_string()) } // we don't display docs on `extern crate` items anyway, so don't process them. - ExternCrateItem(..) => { + clean::ExternCrateItem(..) => { debug!("ignoring extern crate item {:?}", item.def_id); return self.fold_item_recur(item); } - ImportItem(Import { kind: ImportKind::Simple(ref name, ..), .. }) => Some(name.clone()), - MacroItem(..) => None, + clean::ImportItem(Import { kind: clean::ImportKind::Simple(ref name, ..), .. }) => { + Some(name.clone()) + } + clean::MacroItem(..) => None, _ => item.name.clone(), }; @@ -803,6 +865,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } // find item's parent to resolve `Self` in item's docs below + // FIXME(#76467, #75809): this is a mess and doesn't handle cross-crate + // re-exports let parent_name = self.cx.as_local_hir_id(item.def_id).and_then(|item_hir| { let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir); let item_parent = self.cx.tcx.hir().find(parent_hir); @@ -870,7 +934,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }; // NOTE: if there are links that start in one crate and end in another, this will not resolve them. // This is a degenerate case and it's not supported by rustdoc. - // FIXME: this will break links that start in `#[doc = ...]` and end as a sugared doc. Should this be supported? for (ori_link, link_range) in markdown_links(&combined_docs) { let link = self.resolve_link( &item, @@ -888,15 +951,13 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } - if item.is_mod() && !item.attrs.inner_docs { - self.mod_ids.push(item.def_id); - } - if item.is_mod() { - let ret = self.fold_item_recur(item); + if !item.attrs.inner_docs { + self.mod_ids.push(item.def_id); + } + let ret = self.fold_item_recur(item); self.mod_ids.pop(); - ret } else { self.fold_item_recur(item) @@ -905,6 +966,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } impl LinkCollector<'_, '_> { + /// This is the entry point for resolving an intra-doc link. + /// + /// FIXME(jynelson): this is way too many arguments fn resolve_link( &self, item: &Item, @@ -943,129 +1007,120 @@ impl LinkCollector<'_, '_> { } else { (parts[0], None) }; - let resolved_self; - let link_text; - let mut path_str; - let disambiguator; - let stripped_path_string; - let (mut res, mut fragment) = { - path_str = if let Ok((d, path)) = Disambiguator::from_str(&link) { - disambiguator = Some(d); - path - } else { - disambiguator = None; - &link - } - .trim(); - if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, ".contains(ch))) { - return None; - } + // Parse and strip the disambiguator from the link, if present. + let (mut path_str, disambiguator) = if let Ok((d, path)) = Disambiguator::from_str(&link) { + (path.trim(), Some(d)) + } else { + (link.trim(), None) + }; - // We stripped `()` and `!` when parsing the disambiguator. - // Add them back to be displayed, but not prefix disambiguators. - link_text = disambiguator - .map(|d| d.display_for(path_str)) - .unwrap_or_else(|| path_str.to_owned()); - - // In order to correctly resolve intra-doc-links we need to - // pick a base AST node to work from. If the documentation for - // this module came from an inner comment (//!) then we anchor - // our name resolution *inside* the module. If, on the other - // hand it was an outer comment (///) then we anchor the name - // resolution in the parent module on the basis that the names - // used are more likely to be intended to be parent names. For - // this, we set base_node to None for inner comments since - // we've already pushed this node onto the resolution stack but - // for outer comments we explicitly try and resolve against the - // parent_node first. - let base_node = if item.is_mod() && item.attrs.inner_docs { - self.mod_ids.last().copied() - } else { - parent_node - }; + if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, ".contains(ch))) { + return None; + } - let mut module_id = if let Some(id) = base_node { - id - } else { - debug!("attempting to resolve item without parent module: {}", path_str); - let err_kind = ResolutionFailure::NoParentItem.into(); - resolution_failure( - self, - &item, - path_str, - disambiguator, - dox, - link_range, - smallvec![err_kind], - ); - return None; - }; + // We stripped `()` and `!` when parsing the disambiguator. + // Add them back to be displayed, but not prefix disambiguators. + let link_text = + disambiguator.map(|d| d.display_for(path_str)).unwrap_or_else(|| path_str.to_owned()); + + // In order to correctly resolve intra-doc-links we need to + // pick a base AST node to work from. If the documentation for + // this module came from an inner comment (//!) then we anchor + // our name resolution *inside* the module. If, on the other + // hand it was an outer comment (///) then we anchor the name + // resolution in the parent module on the basis that the names + // used are more likely to be intended to be parent names. For + // this, we set base_node to None for inner comments since + // we've already pushed this node onto the resolution stack but + // for outer comments we explicitly try and resolve against the + // parent_node first. + let base_node = if item.is_mod() && item.attrs.inner_docs { + self.mod_ids.last().copied() + } else { + parent_node + }; - // replace `Self` with suitable item's parent name - if path_str.starts_with("Self::") { - if let Some(ref name) = parent_name { - resolved_self = format!("{}::{}", name, &path_str[6..]); - path_str = &resolved_self; - } - } else if path_str.starts_with("crate::") { - use rustc_span::def_id::CRATE_DEF_INDEX; - - // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented. - // But rustdoc wants it to mean the crate this item was originally present in. - // To work around this, remove it and resolve relative to the crate root instead. - // HACK(jynelson)(2): If we just strip `crate::` then suddenly primitives become ambiguous - // (consider `crate::char`). Instead, change it to `self::`. This works because 'self' is now the crate root. - resolved_self = format!("self::{}", &path_str["crate::".len()..]); - path_str = &resolved_self; - module_id = DefId { krate, index: CRATE_DEF_INDEX }; - } + let mut module_id = if let Some(id) = base_node { + id + } else { + // This is a bug. + debug!("attempting to resolve item without parent module: {}", path_str); + let err_kind = ResolutionFailure::NoParentItem.into(); + resolution_failure( + self, + &item, + path_str, + disambiguator, + dox, + link_range, + smallvec![err_kind], + ); + return None; + }; - // Strip generics from the path. - if path_str.contains(['<', '>'].as_slice()) { - stripped_path_string = match strip_generics_from_path(path_str) { - Ok(path) => path, - Err(err_kind) => { - debug!("link has malformed generics: {}", path_str); - resolution_failure( - self, - &item, - path_str, - disambiguator, - dox, - link_range, - smallvec![err_kind], - ); - return None; - } - }; - path_str = &stripped_path_string; + let resolved_self; + // replace `Self` with suitable item's parent name + if path_str.starts_with("Self::") { + if let Some(ref name) = parent_name { + resolved_self = format!("{}::{}", name, &path_str[6..]); + path_str = &resolved_self; } + } else if path_str.starts_with("crate::") { + use rustc_span::def_id::CRATE_DEF_INDEX; + + // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented. + // But rustdoc wants it to mean the crate this item was originally present in. + // To work around this, remove it and resolve relative to the crate root instead. + // HACK(jynelson)(2): If we just strip `crate::` then suddenly primitives become ambiguous + // (consider `crate::char`). Instead, change it to `self::`. This works because 'self' is now the crate root. + // FIXME(#78696): This doesn't always work. + resolved_self = format!("self::{}", &path_str["crate::".len()..]); + path_str = &resolved_self; + module_id = DefId { krate, index: CRATE_DEF_INDEX }; + } - // Sanity check to make sure we don't have any angle brackets after stripping generics. - assert!(!path_str.contains(['<', '>'].as_slice())); + // Strip generics from the path. + let stripped_path_string; + if path_str.contains(['<', '>'].as_slice()) { + stripped_path_string = match strip_generics_from_path(path_str) { + Ok(path) => path, + Err(err_kind) => { + debug!("link has malformed generics: {}", path_str); + resolution_failure( + self, + &item, + path_str, + disambiguator, + dox, + link_range, + smallvec![err_kind], + ); + return None; + } + }; + path_str = &stripped_path_string; + } + // Sanity check to make sure we don't have any angle brackets after stripping generics. + assert!(!path_str.contains(['<', '>'].as_slice())); - // The link is not an intra-doc link if it still contains commas or spaces after - // stripping generics. - if path_str.contains([',', ' '].as_slice()) { - return None; - } + // The link is not an intra-doc link if it still contains commas or spaces after + // stripping generics. + if path_str.contains([',', ' '].as_slice()) { + return None; + } - match self.resolve_with_disambiguator( - disambiguator, - item, - dox, - path_str, - current_item, - module_id, - extra_fragment, - &ori_link, - link_range.clone(), - ) { - Some(x) => x, - None => return None, - } - }; + let (mut res, mut fragment) = self.resolve_with_disambiguator( + disambiguator, + item, + dox, + path_str, + current_item, + module_id, + extra_fragment, + &ori_link, + link_range.clone(), + )?; // Check for a primitive which might conflict with a module // Report the ambiguity and require that the user specify which one they meant. @@ -1075,7 +1130,7 @@ impl LinkCollector<'_, '_> { None | Some(Disambiguator::Namespace(Namespace::TypeNS) | Disambiguator::Primitive) ) && !matches!(res, Res::PrimTy(_)) { - if let Some((path, prim)) = is_primitive(path_str, TypeNS) { + if let Some((path, prim)) = resolve_primitive(path_str, TypeNS) { // `prim@char` if matches!(disambiguator, Some(Disambiguator::Primitive)) { if fragment.is_some() { @@ -1168,11 +1223,13 @@ impl LinkCollector<'_, '_> { privacy_error(cx, &item, &path_str, dox, link_range); } } - let id = register_res(cx, res); + let id = clean::register_res(cx, res); Some(ItemLink { link: ori_link, link_text, did: Some(id), fragment }) } } + /// After parsing the disambiguator, resolve the main part of the link. + // FIXME(jynelson): wow this is just so much fn resolve_with_disambiguator( &self, disambiguator: Option<Disambiguator>, @@ -1232,7 +1289,7 @@ impl LinkCollector<'_, '_> { // Try everything! let mut candidates = PerNS { macro_ns: self - .macro_resolve(path_str, base_node) + .resolve_macro(path_str, base_node) .map(|res| (res, extra_fragment.clone())), type_ns: match self.resolve( path_str, @@ -1320,10 +1377,10 @@ impl LinkCollector<'_, '_> { } } Some(MacroNS) => { - match self.macro_resolve(path_str, base_node) { + match self.resolve_macro(path_str, base_node) { Ok(res) => Some((res, extra_fragment)), Err(mut kind) => { - // `macro_resolve` only looks in the macro namespace. Try to give a better error if possible. + // `resolve_macro` only looks in the macro namespace. Try to give a better error if possible. for &ns in &[TypeNS, ValueNS] { if let Some(res) = self.check_full_res( ns, @@ -1354,9 +1411,15 @@ impl LinkCollector<'_, '_> { } #[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// Disambiguators for a link. enum Disambiguator { + /// `prim@` + /// + /// This is buggy, see <https://github.com/rust-lang/rust/pull/77875#discussion_r503583103> Primitive, + /// `struct@` or `f()` Kind(DefKind), + /// `type@` Namespace(Namespace), } @@ -1373,7 +1436,7 @@ impl Disambiguator { } } - /// (disambiguator, path_str) + /// Given a link, parse and return `(disambiguator, path_str)` fn from_str(link: &str) -> Result<(Self, &str), ()> { use Disambiguator::{Kind, Namespace as NS, Primitive}; @@ -1424,6 +1487,7 @@ impl Disambiguator { } } + /// Used for error reporting. fn suggestion(self) -> Suggestion { let kind = match self { Disambiguator::Primitive => return Suggestion::Prefix("prim"), @@ -1490,9 +1554,13 @@ impl Disambiguator { } } +/// A suggestion to show in a diagnostic. enum Suggestion { + /// `struct@` Prefix(&'static str), + /// `f()` Function, + /// `m!` Macro, } @@ -1582,6 +1650,11 @@ fn report_diagnostic( }); } +/// Reports a link that failed to resolve. +/// +/// This also tries to resolve any intermediate path segments that weren't +/// handled earlier. For example, if passed `Item::Crate(std)` and `path_str` +/// `std::io::Error::x`, this will resolve `std::io::Error`. fn resolution_failure( collector: &LinkCollector<'_, '_>, item: &Item, @@ -1816,6 +1889,7 @@ fn resolution_failure( ); } +/// Report an anchor failure. fn anchor_failure( cx: &DocContext<'_>, item: &Item, @@ -1840,6 +1914,7 @@ fn anchor_failure( }); } +/// Report an ambiguity error, where there were multiple possible resolutions. fn ambiguity_error( cx: &DocContext<'_>, item: &Item, @@ -1886,6 +1961,8 @@ fn ambiguity_error( }); } +/// In case of an ambiguity or mismatched disambiguator, suggest the correct +/// disambiguator. fn suggest_disambiguator( disambiguator: Disambiguator, diag: &mut DiagnosticBuilder<'_>, @@ -1911,6 +1988,7 @@ fn suggest_disambiguator( } } +/// Report a link from a public item to a private one. fn privacy_error( cx: &DocContext<'_>, item: &Item, @@ -1978,7 +2056,8 @@ const PRIMITIVES: &[(Symbol, Res)] = &[ (sym::char, Res::PrimTy(hir::PrimTy::Char)), ]; -fn is_primitive(path_str: &str, ns: Namespace) -> Option<(Symbol, Res)> { +/// Resolve a primitive type or value. +fn resolve_primitive(path_str: &str, ns: Namespace) -> Option<(Symbol, Res)> { is_bool_value(path_str, ns).or_else(|| { if ns == TypeNS { // FIXME: this should be replaced by a lookup in PrimitiveTypeTable @@ -1990,6 +2069,7 @@ fn is_primitive(path_str: &str, ns: Namespace) -> Option<(Symbol, Res)> { }) } +/// Resolve a primitive value. fn is_bool_value(path_str: &str, ns: Namespace) -> Option<(Symbol, Res)> { if ns == TypeNS && (path_str == "true" || path_str == "false") { Some((sym::bool, Res::PrimTy(hir::PrimTy::Bool))) diff --git a/src/test/mir-opt/inline/inline-cycle.rs b/src/test/mir-opt/inline/inline-cycle.rs new file mode 100644 index 00000000000..63ad57de1d4 --- /dev/null +++ b/src/test/mir-opt/inline/inline-cycle.rs @@ -0,0 +1,60 @@ +// Check that inliner handles various forms of recursion and doesn't fall into +// an infinite inlining cycle. The particular outcome of inlining is not +// crucial otherwise. +// +// Regression test for issue #78573. + +fn main() { + one(); + two(); +} + +// EMIT_MIR inline_cycle.one.Inline.diff +fn one() { + <C as Call>::call(); +} + +pub trait Call { + fn call(); +} + +pub struct A<T>(T); +pub struct B<T>(T); +pub struct C; + +impl<T: Call> Call for A<T> { + #[inline] + fn call() { + <B<T> as Call>::call() + } +} + + +impl<T: Call> Call for B<T> { + #[inline] + fn call() { + <T as Call>::call() + } +} + +impl Call for C { + #[inline] + fn call() { + A::<C>::call() + } +} + +// EMIT_MIR inline_cycle.two.Inline.diff +fn two() { + call(f); +} + +#[inline] +fn call<F: FnOnce()>(f: F) { + f(); +} + +#[inline] +fn f() { + call(f); +} diff --git a/src/test/mir-opt/inline/inline-diverging.rs b/src/test/mir-opt/inline/inline-diverging.rs new file mode 100644 index 00000000000..ae6f814c290 --- /dev/null +++ b/src/test/mir-opt/inline/inline-diverging.rs @@ -0,0 +1,40 @@ +// Tests inlining of diverging calls. +// +// ignore-wasm32-bare compiled with panic=abort by default +#![crate_type = "lib"] + +// EMIT_MIR inline_diverging.f.Inline.diff +pub fn f() { + sleep(); +} + +// EMIT_MIR inline_diverging.g.Inline.diff +pub fn g(i: i32) -> u32 { + if i > 0 { + i as u32 + } else { + panic(); + } +} + +// EMIT_MIR inline_diverging.h.Inline.diff +pub fn h() { + call_twice(sleep); +} + +#[inline(always)] +pub fn call_twice<R, F: Fn() -> R>(f: F) -> (R, R) { + let a = f(); + let b = f(); + (a, b) +} + +#[inline(always)] +fn panic() -> ! { + panic!(); +} + +#[inline(always)] +fn sleep() -> ! { + loop {} +} diff --git a/src/test/mir-opt/inline/inline-options.rs b/src/test/mir-opt/inline/inline-options.rs new file mode 100644 index 00000000000..477f050b69e --- /dev/null +++ b/src/test/mir-opt/inline/inline-options.rs @@ -0,0 +1,19 @@ +// Checks that inlining threshold can be controlled with +// inline-mir-threshold and inline-hint-threshold options. +// +// compile-flags: -Zinline-mir-threshold=90 +// compile-flags: -Zinline-mir-hint-threshold=50 + +// EMIT_MIR inline_options.main.Inline.after.mir +fn main() { + not_inlined(); + inlined::<u32>(); +} + +// Cost is approximately 3 * 25 + 5 = 80. +#[inline] +pub fn not_inlined() { g(); g(); g(); } +pub fn inlined<T>() { g(); g(); g(); } + +#[inline(never)] +fn g() {} diff --git a/src/test/mir-opt/inline/inline-shims.rs b/src/test/mir-opt/inline/inline-shims.rs new file mode 100644 index 00000000000..7c8618f71e5 --- /dev/null +++ b/src/test/mir-opt/inline/inline-shims.rs @@ -0,0 +1,13 @@ +// ignore-wasm32-bare compiled with panic=abort by default +#![crate_type = "lib"] + +// EMIT_MIR inline_shims.clone.Inline.diff +pub fn clone<A, B>(f: fn(A, B)) -> fn(A, B) { + f.clone() +} + +// EMIT_MIR inline_shims.drop.Inline.diff +pub fn drop<A, B>(a: *mut Vec<A>, b: *mut Option<B>) { + unsafe { std::ptr::drop_in_place(a) } + unsafe { std::ptr::drop_in_place(b) } +} diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff new file mode 100644 index 00000000000..1b53c827885 --- /dev/null +++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff @@ -0,0 +1,27 @@ +- // MIR for `one` before Inline ++ // MIR for `one` after Inline + + fn one() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline-cycle.rs:13:10: 13:10 + let _1: (); // in scope 0 at $DIR/inline-cycle.rs:14:5: 14:24 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline-cycle.rs:14:5: 14:24 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline-cycle.rs:14:5: 14:24 +- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle.rs:14:5: 14:24 ++ _1 = <A<C> as Call>::call() -> bb1; // scope 1 at $DIR/inline-cycle.rs:14:5: 14:24 + // mir::Constant +- // + span: $DIR/inline-cycle.rs:14:5: 14:22 +- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(Scalar(<ZST>)) } ++ // + span: $DIR/inline-cycle.rs:14:5: 14:24 ++ // + literal: Const { ty: fn() {<A<C> as Call>::call}, val: Value(Scalar(<ZST>)) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline-cycle.rs:14:24: 14:25 + _0 = const (); // scope 0 at $DIR/inline-cycle.rs:13:10: 15:2 + return; // scope 0 at $DIR/inline-cycle.rs:15:2: 15:2 + } + } + diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff new file mode 100644 index 00000000000..b44baca9bf4 --- /dev/null +++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff @@ -0,0 +1,47 @@ +- // MIR for `two` before Inline ++ // MIR for `two` after Inline + + fn two() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline-cycle.rs:48:10: 48:10 + let _1: (); // in scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 ++ let mut _2: fn() {f}; // in scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 ++ let mut _5: (); // in scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 ++ scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline-cycle.rs:49:5: 49:12 ++ debug f => _2; // in scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ let _3: (); // in scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ let mut _4: fn() {f}; // in scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline-cycle.rs:49:5: 49:12 ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 +- _1 = call::<fn() {f}>(f) -> bb1; // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 ++ StorageLive(_2); // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 ++ _2 = f; // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 + // mir::Constant +- // + span: $DIR/inline-cycle.rs:49:5: 49:9 +- // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(Scalar(<ZST>)) } +- // mir::Constant + // + span: $DIR/inline-cycle.rs:49:10: 49:11 + // + literal: Const { ty: fn() {f}, val: Value(Scalar(<ZST>)) } ++ StorageLive(_3); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ StorageLive(_4); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ _4 = move _2; // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ StorageLive(_5); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ _5 = const (); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ _3 = move _4() -> bb1; // scope 2 at $DIR/inline-cycle.rs:49:5: 49:12 + } + + bb1: { ++ StorageDead(_5); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ StorageDead(_4); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ StorageDead(_3); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ _1 = const (); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12 ++ StorageDead(_2); // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 + StorageDead(_1); // scope 0 at $DIR/inline-cycle.rs:49:12: 49:13 + _0 = const (); // scope 0 at $DIR/inline-cycle.rs:48:10: 50:2 + return; // scope 0 at $DIR/inline-cycle.rs:50:2: 50:2 + } + } + diff --git a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff new file mode 100644 index 00000000000..6e36dc06a20 --- /dev/null +++ b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff @@ -0,0 +1,26 @@ +- // MIR for `f` before Inline ++ // MIR for `f` after Inline + + fn f() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:7:12: 7:12 + let mut _1: !; // in scope 0 at $DIR/inline-diverging.rs:7:12: 9:2 + let _2: !; // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12 ++ let mut _3: !; // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12 ++ scope 1 (inlined sleep) { // at $DIR/inline-diverging.rs:8:5: 8:12 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12 +- sleep(); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12 +- // mir::Constant +- // + span: $DIR/inline-diverging.rs:8:5: 8:10 +- // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) } ++ StorageLive(_3); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12 ++ goto -> bb1; // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12 ++ } ++ ++ bb1: { ++ goto -> bb1; // scope 1 at $DIR/inline-diverging.rs:8:5: 8:12 + } + } + diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff new file mode 100644 index 00000000000..3dc33354a5a --- /dev/null +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -0,0 +1,52 @@ +- // MIR for `g` before Inline ++ // MIR for `g` after Inline + + fn g(_1: i32) -> u32 { + debug i => _1; // in scope 0 at $DIR/inline-diverging.rs:12:10: 12:11 + let mut _0: u32; // return place in scope 0 at $DIR/inline-diverging.rs:12:21: 12:24 + let mut _2: bool; // in scope 0 at $DIR/inline-diverging.rs:13:8: 13:13 + let mut _3: i32; // in scope 0 at $DIR/inline-diverging.rs:13:8: 13:9 + let mut _4: i32; // in scope 0 at $DIR/inline-diverging.rs:14:9: 14:10 + let mut _5: !; // in scope 0 at $DIR/inline-diverging.rs:15:12: 17:6 + let _6: !; // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16 ++ let mut _7: !; // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16 ++ scope 1 (inlined panic) { // at $DIR/inline-diverging.rs:16:9: 16:16 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:13:8: 13:13 + StorageLive(_3); // scope 0 at $DIR/inline-diverging.rs:13:8: 13:9 + _3 = _1; // scope 0 at $DIR/inline-diverging.rs:13:8: 13:9 + _2 = Gt(move _3, const 0_i32); // scope 0 at $DIR/inline-diverging.rs:13:8: 13:13 + StorageDead(_3); // scope 0 at $DIR/inline-diverging.rs:13:12: 13:13 + switchInt(_2) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/inline-diverging.rs:13:5: 17:6 + } + + bb1: { + StorageLive(_6); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16 +- panic(); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16 ++ StorageLive(_7); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16 ++ begin_panic::<&str>(const "explicit panic"); // scope 1 at $DIR/inline-diverging.rs:16:9: 16:16 + // mir::Constant +- // + span: $DIR/inline-diverging.rs:16:9: 16:14 +- // + literal: Const { ty: fn() -> ! {panic}, val: Value(Scalar(<ZST>)) } ++ // + span: $DIR/inline-diverging.rs:16:9: 16:16 ++ // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar(<ZST>)) } ++ // ty::Const ++ // + ty: &str ++ // + val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, size: Size { raw: 14 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) ++ // mir::Constant ++ // + span: $DIR/inline-diverging.rs:16:9: 16:16 ++ // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, size: Size { raw: 14 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } + } + + bb2: { + StorageLive(_4); // scope 0 at $DIR/inline-diverging.rs:14:9: 14:10 + _4 = _1; // scope 0 at $DIR/inline-diverging.rs:14:9: 14:10 + _0 = move _4 as u32 (Misc); // scope 0 at $DIR/inline-diverging.rs:14:9: 14:17 + StorageDead(_4); // scope 0 at $DIR/inline-diverging.rs:14:16: 14:17 + StorageDead(_2); // scope 0 at $DIR/inline-diverging.rs:18:1: 18:2 + return; // scope 0 at $DIR/inline-diverging.rs:18:2: 18:2 + } + } + diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff new file mode 100644 index 00000000000..b728ad4b428 --- /dev/null +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -0,0 +1,58 @@ +- // MIR for `h` before Inline ++ // MIR for `h` after Inline + + fn h() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12 + let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let mut _7: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let mut _8: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22 ++ debug f => _2; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let _3: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let mut _5: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let mut _6: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ scope 2 { ++ debug a => _3; // in scope 2 at $DIR/inline-diverging.rs:22:5: 22:22 ++ scope 3 { ++ debug b => _6; // in scope 3 at $DIR/inline-diverging.rs:22:5: 22:22 ++ } ++ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:22:5: 22:22 ++ scope 7 (inlined sleep) { // at $DIR/inline-diverging.rs:22:5: 22:22 ++ } ++ } ++ } ++ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:22:5: 22:22 ++ scope 5 (inlined sleep) { // at $DIR/inline-diverging.rs:22:5: 22:22 ++ } ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 +- _1 = call_twice::<!, fn() -> ! {sleep}>(sleep) -> bb1; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ _2 = sleep; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 + // mir::Constant +- // + span: $DIR/inline-diverging.rs:22:5: 22:15 +- // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(Scalar(<ZST>)) } +- // mir::Constant + // + span: $DIR/inline-diverging.rs:22:16: 22:21 + // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) } ++ StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ StorageLive(_7); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ _7 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22 + } + + bb1: { +- StorageDead(_1); // scope 0 at $DIR/inline-diverging.rs:22:22: 22:23 +- _0 = const (); // scope 0 at $DIR/inline-diverging.rs:21:12: 23:2 +- return; // scope 0 at $DIR/inline-diverging.rs:23:2: 23:2 ++ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22 + } + } + diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index 0fbafd76e20..3c0dfb4a77e 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -18,6 +18,7 @@ StorageLive(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 _2 = Box(std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - (*_2) = Vec::<u32>::new() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageLive(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _4 = &mut (*_2); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 + // ty::Const @@ -34,6 +35,7 @@ + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + ((*_4).1: usize) = const 0_usize; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageDead(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 _1 = move _2; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 StorageDead(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 _0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:7:11: 9:2 diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 9277e57134e..a72db9cf1dc 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -18,6 +18,7 @@ StorageLive(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 _2 = Box(std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - (*_2) = Vec::<u32>::new() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageLive(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _4 = &mut (*_2); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 + // ty::Const @@ -34,6 +35,7 @@ + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, size: Size { raw: 16 }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + ((*_4).1: usize) = const 0_usize; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageDead(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 _1 = move _2; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 StorageDead(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 _0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:7:11: 9:2 diff --git a/src/test/mir-opt/inline/inline_options.main.Inline.after.mir b/src/test/mir-opt/inline/inline_options.main.Inline.after.mir new file mode 100644 index 00000000000..4cbdde2ba07 --- /dev/null +++ b/src/test/mir-opt/inline/inline_options.main.Inline.after.mir @@ -0,0 +1,56 @@ +// MIR for `main` after Inline + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline-options.rs:8:11: 8:11 + let _1: (); // in scope 0 at $DIR/inline-options.rs:9:5: 9:18 + let _2: (); // in scope 0 at $DIR/inline-options.rs:10:5: 10:21 + scope 1 (inlined inlined::<u32>) { // at $DIR/inline-options.rs:10:5: 10:21 + let _3: (); // in scope 1 at $DIR/inline-options.rs:10:5: 10:21 + let _4: (); // in scope 1 at $DIR/inline-options.rs:10:5: 10:21 + let _5: (); // in scope 1 at $DIR/inline-options.rs:10:5: 10:21 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline-options.rs:9:5: 9:18 + _1 = not_inlined() -> bb1; // scope 0 at $DIR/inline-options.rs:9:5: 9:18 + // mir::Constant + // + span: $DIR/inline-options.rs:9:5: 9:16 + // + literal: Const { ty: fn() {not_inlined}, val: Value(Scalar(<ZST>)) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline-options.rs:9:18: 9:19 + StorageLive(_2); // scope 0 at $DIR/inline-options.rs:10:5: 10:21 + StorageLive(_3); // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + _3 = g() -> bb2; // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + // mir::Constant + // + span: $DIR/inline-options.rs:10:5: 10:21 + // + literal: Const { ty: fn() {g}, val: Value(Scalar(<ZST>)) } + } + + bb2: { + StorageDead(_3); // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + StorageLive(_4); // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + _4 = g() -> bb3; // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + // mir::Constant + // + span: $DIR/inline-options.rs:10:5: 10:21 + // + literal: Const { ty: fn() {g}, val: Value(Scalar(<ZST>)) } + } + + bb3: { + StorageDead(_4); // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + StorageLive(_5); // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + _5 = g() -> bb4; // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + // mir::Constant + // + span: $DIR/inline-options.rs:10:5: 10:21 + // + literal: Const { ty: fn() {g}, val: Value(Scalar(<ZST>)) } + } + + bb4: { + StorageDead(_5); // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + _2 = const (); // scope 1 at $DIR/inline-options.rs:10:5: 10:21 + StorageDead(_2); // scope 0 at $DIR/inline-options.rs:10:21: 10:22 + _0 = const (); // scope 0 at $DIR/inline-options.rs:8:11: 11:2 + return; // scope 0 at $DIR/inline-options.rs:11:2: 11:2 + } +} diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff new file mode 100644 index 00000000000..3bdd4f4ff56 --- /dev/null +++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff @@ -0,0 +1,26 @@ +- // MIR for `clone` before Inline ++ // MIR for `clone` after Inline + + fn clone(_1: fn(A, B)) -> fn(A, B) { + debug f => _1; // in scope 0 at $DIR/inline-shims.rs:5:20: 5:21 + let mut _0: fn(A, B); // return place in scope 0 at $DIR/inline-shims.rs:5:36: 5:44 + let mut _2: &fn(A, B); // in scope 0 at $DIR/inline-shims.rs:6:5: 6:6 ++ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline-shims.rs:6:5: 6:14 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline-shims.rs:6:5: 6:6 + _2 = &_1; // scope 0 at $DIR/inline-shims.rs:6:5: 6:6 +- _0 = <fn(A, B) as Clone>::clone(move _2) -> bb1; // scope 0 at $DIR/inline-shims.rs:6:5: 6:14 +- // mir::Constant +- // + span: $DIR/inline-shims.rs:6:7: 6:12 +- // + literal: Const { ty: for<'r> fn(&'r fn(A, B)) -> fn(A, B) {<fn(A, B) as std::clone::Clone>::clone}, val: Value(Scalar(<ZST>)) } +- } +- +- bb1: { ++ _0 = (*_2); // scope 1 at $DIR/inline-shims.rs:6:5: 6:14 + StorageDead(_2); // scope 0 at $DIR/inline-shims.rs:6:13: 6:14 + return; // scope 0 at $DIR/inline-shims.rs:7:2: 7:2 + } + } + diff --git a/src/test/mir-opt/inline/inline_shims.drop.Inline.diff b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff new file mode 100644 index 00000000000..503d8bc6b7a --- /dev/null +++ b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff @@ -0,0 +1,52 @@ +- // MIR for `drop` before Inline ++ // MIR for `drop` after Inline + + fn drop(_1: *mut Vec<A>, _2: *mut Option<B>) -> () { + debug a => _1; // in scope 0 at $DIR/inline-shims.rs:10:19: 10:20 + debug b => _2; // in scope 0 at $DIR/inline-shims.rs:10:35: 10:36 + let mut _0: (); // return place in scope 0 at $DIR/inline-shims.rs:10:54: 10:54 + let _3: (); // in scope 0 at $DIR/inline-shims.rs:11:14: 11:40 + let mut _4: *mut std::vec::Vec<A>; // in scope 0 at $DIR/inline-shims.rs:11:38: 11:39 + let mut _5: *mut std::option::Option<B>; // in scope 0 at $DIR/inline-shims.rs:12:38: 12:39 + scope 1 { + } + scope 2 { ++ scope 3 (inlined drop_in_place::<Option<B>> - shim(Some(Option<B>))) { // at $DIR/inline-shims.rs:12:14: 12:40 ++ let mut _6: isize; // in scope 3 at $DIR/inline-shims.rs:12:14: 12:40 ++ let mut _7: isize; // in scope 3 at $DIR/inline-shims.rs:12:14: 12:40 ++ } + } + + bb0: { + StorageLive(_3); // scope 0 at $DIR/inline-shims.rs:11:5: 11:42 + StorageLive(_4); // scope 1 at $DIR/inline-shims.rs:11:38: 11:39 + _4 = _1; // scope 1 at $DIR/inline-shims.rs:11:38: 11:39 + _3 = drop_in_place::<Vec<A>>(move _4) -> bb1; // scope 1 at $DIR/inline-shims.rs:11:14: 11:40 + // mir::Constant + // + span: $DIR/inline-shims.rs:11:14: 11:37 + // + literal: Const { ty: unsafe fn(*mut std::vec::Vec<A>) {std::intrinsics::drop_in_place::<std::vec::Vec<A>>}, val: Value(Scalar(<ZST>)) } + } + + bb1: { + StorageDead(_4); // scope 1 at $DIR/inline-shims.rs:11:39: 11:40 + StorageDead(_3); // scope 0 at $DIR/inline-shims.rs:11:41: 11:42 + StorageLive(_5); // scope 2 at $DIR/inline-shims.rs:12:38: 12:39 + _5 = _2; // scope 2 at $DIR/inline-shims.rs:12:38: 12:39 +- _0 = drop_in_place::<Option<B>>(move _5) -> bb2; // scope 2 at $DIR/inline-shims.rs:12:14: 12:40 +- // mir::Constant +- // + span: $DIR/inline-shims.rs:12:14: 12:37 +- // + literal: Const { ty: unsafe fn(*mut std::option::Option<B>) {std::intrinsics::drop_in_place::<std::option::Option<B>>}, val: Value(Scalar(<ZST>)) } ++ _6 = discriminant((*_5)); // scope 3 at $DIR/inline-shims.rs:12:14: 12:40 ++ switchInt(move _6) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $DIR/inline-shims.rs:12:14: 12:40 + } + + bb2: { + StorageDead(_5); // scope 2 at $DIR/inline-shims.rs:12:39: 12:40 + return; // scope 0 at $DIR/inline-shims.rs:13:2: 13:2 ++ } ++ ++ bb3: { ++ drop((((*_5) as Some).0: B)) -> bb2; // scope 3 at $DIR/inline-shims.rs:12:14: 12:40 + } + } + diff --git a/src/test/rustdoc/external-macro-src.rs b/src/test/rustdoc/external-macro-src.rs index 4394415e5c7..6a7dbb004a3 100644 --- a/src/test/rustdoc/external-macro-src.rs +++ b/src/test/rustdoc/external-macro-src.rs @@ -1,15 +1,12 @@ // aux-build:external-macro-src.rs -// ignore-tidy-linelength #![crate_name = "foo"] #[macro_use] extern crate external_macro_src; -// @has foo/index.html '//a[@href="../src/foo/external-macro-src.rs.html#4-15"]' '[src]' +// @has foo/index.html '//a[@href="../src/foo/external-macro-src.rs.html#3-12"]' '[src]' // @has foo/struct.Foo.html -// @has - '//a[@href="https://example.com/src/external_macro_src/external-macro-src.rs.html#8"]' '[src]' -// @has - '//a[@href="https://example.com/src/external_macro_src/external-macro-src.rs.html#9-13"]' '[src]' -// @has - '//a[@href="https://example.com/src/external_macro_src/external-macro-src.rs.html#10-12"]' '[src]' +// @has - '//a[@href="../src/foo/external-macro-src.rs.html#12"]' '[src]' make_foo!(); diff --git a/src/test/rustdoc/issue-26606.rs b/src/test/rustdoc/issue-26606.rs index c8e9a63ea9f..bd6f38e9123 100644 --- a/src/test/rustdoc/issue-26606.rs +++ b/src/test/rustdoc/issue-26606.rs @@ -7,5 +7,5 @@ extern crate issue_26606_macro; // @has issue_26606/constant.FOO.html -// @has - '//a/@href' '../src/issue_26606_macro/issue-26606-macro.rs.html#3' +// @has - '//a[@href="../src/issue_26606/issue-26606.rs.html#11"]' '[src]' make_item!(FOO); diff --git a/src/test/rustdoc/thread-local-src.rs b/src/test/rustdoc/thread-local-src.rs index 022d81a4dbf..5e56bb5819a 100644 --- a/src/test/rustdoc/thread-local-src.rs +++ b/src/test/rustdoc/thread-local-src.rs @@ -2,5 +2,5 @@ // @has foo/index.html '//a[@href="../src/foo/thread-local-src.rs.html#1-6"]' '[src]' -// @has foo/constant.FOO.html '//a/@href' 'https://doc.rust-lang.org/nightly/src/std/' +// @has foo/constant.FOO.html '//a[@href="../src/foo/thread-local-src.rs.html#6"]' '[src]' thread_local!(pub static FOO: bool = false); diff --git a/src/test/ui/async-await/issue-74072-lifetime-name-annotations.rs b/src/test/ui/async-await/issue-74072-lifetime-name-annotations.rs new file mode 100644 index 00000000000..95683241aba --- /dev/null +++ b/src/test/ui/async-await/issue-74072-lifetime-name-annotations.rs @@ -0,0 +1,37 @@ +// edition:2018 +#![feature(async_closure)] +use std::future::Future; + +// test the quality of annotations giving lifetimes names (`'1`) when async constructs are involved + +pub async fn async_fn(x: &mut i32) -> &i32 { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y +} + +pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> { + (async move || { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y + })() +} + +pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> { + (async move || -> &i32 { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y + })() +} + +pub fn async_block(x: &mut i32) -> impl Future<Output=&i32> { + async move { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/src/test/ui/async-await/issue-74072-lifetime-name-annotations.stderr new file mode 100644 index 00000000000..123c3192cff --- /dev/null +++ b/src/test/ui/async-await/issue-74072-lifetime-name-annotations.stderr @@ -0,0 +1,51 @@ +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:9:5 + | +LL | pub async fn async_fn(x: &mut i32) -> &i32 { + | - let's call the lifetime of this reference `'1` +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:16:9 + | +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` +LL | })() + | - return type of async closure is &'1 i32 + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:24:9 + | +LL | (async move || -> &i32 { + | - let's call the lifetime of this reference `'1` +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:32:9 + | +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` +LL | } + | - return type of async block is &'1 i32 + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/async-await/issue-74497-lifetime-in-opaque.rs b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.rs new file mode 100644 index 00000000000..2d765eb41be --- /dev/null +++ b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.rs @@ -0,0 +1,19 @@ +// edition:2018 + +// test that names give to anonymous lifetimes in opaque types like `impl Future` are correctly +// introduced in error messages + +use std::future::Future; + +pub async fn foo<F, T>(_: F) +where + F: Fn(&u8) -> T, + T: Future<Output = ()>, +{ +} + +pub async fn bar(_: &u8) {} + +fn main() { + let _ = foo(|x| bar(x)); //~ ERROR lifetime may not live long enough +} diff --git a/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr new file mode 100644 index 00000000000..89fe1abb365 --- /dev/null +++ b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-74497-lifetime-in-opaque.rs:18:21 + | +LL | let _ = foo(|x| bar(x)); + | -- ^^^^^^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure `impl Future` contains a lifetime `'2` + | has type `&'1 u8` + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issues/issue-63388-1.stderr b/src/test/ui/async-await/issues/issue-63388-1.stderr index 8813183312d..ac29cca9d3f 100644 --- a/src/test/ui/async-await/issues/issue-63388-1.stderr +++ b/src/test/ui/async-await/issues/issue-63388-1.stderr @@ -2,12 +2,14 @@ error[E0623]: lifetime mismatch --> $DIR/issue-63388-1.rs:14:9 | LL | &'a self, foo: &dyn Foo - | -------- this parameter and the return type are declared with different lifetimes... + | -------- this parameter and the returned future are declared with different lifetimes... LL | ) -> &dyn Foo | -------- + | | + | this `async fn` implicitly returns an `impl Future<Output = &dyn Foo>` LL | { LL | foo - | ^^^ ...but data from `foo` is returned here + | ^^^ ...but data from `foo` is held across an await point here error: aborting due to previous error diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 7b8f290d6c2..5041b39a9e9 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -4,8 +4,9 @@ error[E0623]: lifetime mismatch LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { | ------ ^^^^^^^^^^^^^^ | | | - | | ...but data from `b` is returned here - | this parameter and the return type are declared with different lifetimes... + | | ...but data from `b` is held across an await point here + | | this `async fn` implicitly returns an `impl Future<Output = impl Trait<'a>>` + | this parameter and the returned future are declared with different lifetimes... error: aborting due to previous error diff --git a/src/test/ui/bad/bad-expr-lhs.rs b/src/test/ui/bad/bad-expr-lhs.rs index d7cf1b77005..39536f12e3b 100644 --- a/src/test/ui/bad/bad-expr-lhs.rs +++ b/src/test/ui/bad/bad-expr-lhs.rs @@ -1,10 +1,12 @@ fn main() { 1 = 2; //~ ERROR invalid left-hand side of assignment 1 += 2; //~ ERROR invalid left-hand side of assignment - (1, 2) = (3, 4); //~ ERROR invalid left-hand side of assignment + (1, 2) = (3, 4); //~ ERROR destructuring assignments are unstable + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment let (a, b) = (1, 2); - (a, b) = (3, 4); //~ ERROR invalid left-hand side of assignment + (a, b) = (3, 4); //~ ERROR destructuring assignments are unstable None = Some(3); //~ ERROR invalid left-hand side of assignment } diff --git a/src/test/ui/bad/bad-expr-lhs.stderr b/src/test/ui/bad/bad-expr-lhs.stderr index a195e1054d0..d4b2193d09f 100644 --- a/src/test/ui/bad/bad-expr-lhs.stderr +++ b/src/test/ui/bad/bad-expr-lhs.stderr @@ -1,3 +1,25 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/bad-expr-lhs.rs:4:12 + | +LL | (1, 2) = (3, 4); + | ------ ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/bad-expr-lhs.rs:9:12 + | +LL | (a, b) = (3, 4); + | ------ ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + error[E0070]: invalid left-hand side of assignment --> $DIR/bad-expr-lhs.rs:2:7 | @@ -18,30 +40,27 @@ error[E0070]: invalid left-hand side of assignment --> $DIR/bad-expr-lhs.rs:4:12 | LL | (1, 2) = (3, 4); - | ------ ^ - | | - | cannot assign to this expression + | - ^ + | | + | cannot assign to this expression error[E0070]: invalid left-hand side of assignment - --> $DIR/bad-expr-lhs.rs:7:12 - | -LL | (a, b) = (3, 4); - | ------ ^ - | | - | cannot assign to this expression + --> $DIR/bad-expr-lhs.rs:4:12 | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 +LL | (1, 2) = (3, 4); + | - ^ + | | + | cannot assign to this expression error[E0070]: invalid left-hand side of assignment - --> $DIR/bad-expr-lhs.rs:9:10 + --> $DIR/bad-expr-lhs.rs:11:10 | LL | None = Some(3); | ---- ^ | | | cannot assign to this expression -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0067, E0070. +Some errors have detailed explanations: E0067, E0070, E0658. For more information about an error, try `rustc --explain E0067`. diff --git a/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr b/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr index e8a026cfab9..a7c3b9eec73 100644 --- a/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr +++ b/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | let _action = move || { | ------- | | | - | | return type of closure is [closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:15] + | | return type of closure `[closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:15]` contains a lifetime `'2` | lifetime `'1` represents this closure's body LL | || f() // The `nested` closure | ^^^^^^ returning this value requires that `'1` must outlive `'2` diff --git a/src/test/ui/cfg/cfg-panic-abort.rs b/src/test/ui/cfg/cfg-panic-abort.rs new file mode 100644 index 00000000000..9b88eff12ed --- /dev/null +++ b/src/test/ui/cfg/cfg-panic-abort.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: -C panic=abort +// no-prefer-dynamic +#![feature(cfg_panic)] + +#[cfg(panic = "unwind")] +pub fn bad() -> i32 { } + +#[cfg(not(panic = "abort"))] +pub fn bad() -> i32 { } + +#[cfg(panic = "some_imaginary_future_panic_handler")] +pub fn bad() -> i32 { } + +#[cfg(panic = "abort")] +pub fn main() { } diff --git a/src/test/ui/cfg/cfg-panic.rs b/src/test/ui/cfg/cfg-panic.rs new file mode 100644 index 00000000000..dbb5932a9bb --- /dev/null +++ b/src/test/ui/cfg/cfg-panic.rs @@ -0,0 +1,18 @@ +// build-pass +// compile-flags: -C panic=unwind +// ignore-emscripten no panic_unwind implementation +// ignore-wasm32 no panic_unwind implementation +// ignore-wasm64 no panic_unwind implementation +#![feature(cfg_panic)] + +#[cfg(panic = "abort")] +pub fn bad() -> i32 { } + +#[cfg(not(panic = "unwind"))] +pub fn bad() -> i32 { } + +#[cfg(panic = "some_imaginary_future_panic_handler")] +pub fn bad() -> i32 { } + +#[cfg(panic = "unwind")] +pub fn main() { } diff --git a/src/test/ui/chalkify/arithmetic.rs b/src/test/ui/chalkify/arithmetic.rs new file mode 100644 index 00000000000..a20acce4c76 --- /dev/null +++ b/src/test/ui/chalkify/arithmetic.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Z chalk + +fn main() { + 1 + 2; + 3 * 6; + 2 - 5; + 17 / 6; + 23 % 11; + 4 & 6; + 7 | 15; + 4 << 7; + 123 >> 3; + 1 == 2; + 5 != 5; + 6 < 2; + 7 > 11; + 3 <= 1; + 9 >= 14; +} diff --git a/src/test/ui/chalkify/trait-objects.rs b/src/test/ui/chalkify/trait-objects.rs new file mode 100644 index 00000000000..13d9e6a6578 --- /dev/null +++ b/src/test/ui/chalkify/trait-objects.rs @@ -0,0 +1,13 @@ +// check-pass +// compile-flags: -Z chalk + +use std::fmt::Display; + +fn main() { + let d: &dyn Display = &mut 3; + // FIXME(chalk) should be able to call d.to_string() as well, but doing so + // requires Chalk to be able to prove trait object well-formed goals. + (&d).to_string(); + let f: &dyn Fn(i32) -> _ = &|x| x + x; + f(2); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs b/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs new file mode 100644 index 00000000000..533fe55b45b --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs @@ -0,0 +1,31 @@ +// run-pass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +pub trait BlockCipher { + const BLOCK_SIZE: usize; +} + +struct FooCipher; +impl BlockCipher for FooCipher { + const BLOCK_SIZE: usize = 64; +} + +struct BarCipher; +impl BlockCipher for BarCipher { + const BLOCK_SIZE: usize = 32; +} + +pub struct Block<C>(C); + +pub fn test<C: BlockCipher, const M: usize>() +where + [u8; M - C::BLOCK_SIZE]: Sized, +{ + let _ = [0; M - C::BLOCK_SIZE]; +} + +fn main() { + test::<FooCipher, 128>(); + test::<BarCipher, 64>(); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs new file mode 100644 index 00000000000..05049d9c2a6 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs @@ -0,0 +1,16 @@ +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +use std::mem::size_of; +use std::marker::PhantomData; + +struct Foo<T>(PhantomData<T>); + +fn test<T>() -> [u8; size_of::<T>()] { + [0; size_of::<Foo<T>>()] + //~^ ERROR unconstrained generic constant +} + +fn main() { + test::<u32>(); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr new file mode 100644 index 00000000000..1f6dddb04e5 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr @@ -0,0 +1,14 @@ +error: unconstrained generic constant + --> $DIR/different-fn.rs:10:9 + | +LL | [0; size_of::<Foo<T>>()] + | ^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a `where` bound for this expression + --> $DIR/different-fn.rs:10:9 + | +LL | [0; size_of::<Foo<T>>()] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/min_const_generics/macro-fail.rs b/src/test/ui/const-generics/min_const_generics/macro-fail.rs new file mode 100644 index 00000000000..7f16f2f33de --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/macro-fail.rs @@ -0,0 +1,48 @@ +#![feature(min_const_generics)] + +struct Example<const N: usize>; + +macro_rules! external_macro { + () => {{ + //~^ ERROR expected type + const X: usize = 1337; + X + }} +} + +trait Marker<const N: usize> {} +impl<const N: usize> Marker<N> for Example<N> {} + +fn make_marker() -> impl Marker<gimme_a_const!(marker)> { + //~^ ERROR wrong number of const + //~| ERROR wrong number of type + Example::<gimme_a_const!(marker)> + //~^ ERROR wrong number of const + //~| ERROR wrong number of type +} + +fn from_marker(_: impl Marker<{ + #[macro_export] + macro_rules! inline { () => {{ 3 }} }; inline!() +}>) {} + +fn main() { + let _ok = Example::<{ + #[macro_export] + macro_rules! gimme_a_const { + ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + //~^ ERROR expected type + //~| ERROR expected type + }; + gimme_a_const!(run) + }>; + + let _fail = Example::<external_macro!()>; + //~^ ERROR wrong number of const + //~| ERROR wrong number of type + + let _fail = Example::<gimme_a_const!()>; + //~^ ERROR wrong number of const + //~| ERROR wrong number of type + //~| ERROR unexpected end of macro invocation +} diff --git a/src/test/ui/const-generics/min_const_generics/macro-fail.stderr b/src/test/ui/const-generics/min_const_generics/macro-fail.stderr new file mode 100644 index 00000000000..fe7a4a5c382 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/macro-fail.stderr @@ -0,0 +1,107 @@ +error: expected type, found `{` + --> $DIR/macro-fail.rs:33:27 + | +LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { + | ---------------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation +... +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected type, found `{` + --> $DIR/macro-fail.rs:33:27 + | +LL | Example::<gimme_a_const!(marker)> + | ---------------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation +... +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected type, found `{` + --> $DIR/macro-fail.rs:6:10 + | +LL | () => {{ + | __________^ +LL | | +LL | | const X: usize = 1337; +LL | | X +LL | | }} + | |___^ expected type +... +LL | let _fail = Example::<external_macro!()>; + | ----------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected end of macro invocation + --> $DIR/macro-fail.rs:44:25 + | +LL | macro_rules! gimme_a_const { + | -------------------------- when calling this macro +... +LL | let _fail = Example::<gimme_a_const!()>; + | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments + +error[E0107]: wrong number of const arguments: expected 1, found 0 + --> $DIR/macro-fail.rs:16:26 + | +LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/macro-fail.rs:16:33 + | +LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { + | ^^^^^^^^^^^^^^^^^^^^^^ unexpected type argument + +error[E0107]: wrong number of const arguments: expected 1, found 0 + --> $DIR/macro-fail.rs:19:3 + | +LL | Example::<gimme_a_const!(marker)> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/macro-fail.rs:19:13 + | +LL | Example::<gimme_a_const!(marker)> + | ^^^^^^^^^^^^^^^^^^^^^^ unexpected type argument + +error[E0107]: wrong number of const arguments: expected 1, found 0 + --> $DIR/macro-fail.rs:40:15 + | +LL | let _fail = Example::<external_macro!()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/macro-fail.rs:40:25 + | +LL | let _fail = Example::<external_macro!()>; + | ^^^^^^^^^^^^^^^^^ unexpected type argument + +error[E0107]: wrong number of const arguments: expected 1, found 0 + --> $DIR/macro-fail.rs:44:15 + | +LL | let _fail = Example::<gimme_a_const!()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/macro-fail.rs:44:25 + | +LL | let _fail = Example::<gimme_a_const!()>; + | ^^^^^^^^^^^^^^^^ unexpected type argument + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/min_const_generics/macro.rs b/src/test/ui/const-generics/min_const_generics/macro.rs new file mode 100644 index 00000000000..85ecce551d4 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/macro.rs @@ -0,0 +1,57 @@ +// run-pass +#![feature(min_const_generics)] + +struct Example<const N: usize>; + +macro_rules! external_macro { + () => {{ + const X: usize = 1337; + X + }} +} + +trait Marker<const N: usize> {} +impl<const N: usize> Marker<N> for Example<N> {} + +fn make_marker() -> impl Marker<{ + #[macro_export] + macro_rules! const_macro { () => {{ 3 }} }; inline!() +}> { + Example::<{ const_macro!() }> +} + +fn from_marker(_: impl Marker<{ + #[macro_export] + macro_rules! inline { () => {{ 3 }} }; inline!() +}>) {} + +fn main() { + let _ok = Example::<{ + #[macro_export] + macro_rules! gimme_a_const { + ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + }; + gimme_a_const!(run) + }>; + + let _ok = Example::<{ external_macro!() }>; + + let _ok: [_; gimme_a_const!(blah)] = [0,0,0]; + let _ok: [[u8; gimme_a_const!(blah)]; gimme_a_const!(blah)]; + let _ok: [u8; gimme_a_const!(blah)]; + + let _ok: [u8; { + #[macro_export] + macro_rules! const_two { () => {{ 2 }} }; + const_two!() + }]; + + let _ok = [0; { + #[macro_export] + macro_rules! const_three { () => {{ 3 }} }; + const_three!() + }]; + let _ok = [0; const_three!()]; + + from_marker(make_marker()); +} diff --git a/src/test/ui/consts/const-block-non-item-statement.rs b/src/test/ui/consts/const-block-non-item-statement.rs index 9aec8552695..07970b457a3 100644 --- a/src/test/ui/consts/const-block-non-item-statement.rs +++ b/src/test/ui/consts/const-block-non-item-statement.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass enum Foo { Bar = { let x = 1; 3 } diff --git a/src/test/ui/consts/const-fn-destructuring-arg.rs b/src/test/ui/consts/const-fn-destructuring-arg.rs index d2c89cb54a0..ea5c9ddc7ce 100644 --- a/src/test/ui/consts/const-fn-destructuring-arg.rs +++ b/src/test/ui/consts/const-fn-destructuring-arg.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass const fn i((a, b): (u32, u32)) -> u32 { a + b diff --git a/src/test/ui/consts/const_let_assign.rs b/src/test/ui/consts/const_let_assign.rs index 343fcb4859b..b83acfb73cf 100644 --- a/src/test/ui/consts/const_let_assign.rs +++ b/src/test/ui/consts/const_let_assign.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass struct S(i32); diff --git a/src/test/ui/consts/const_let_assign2.rs b/src/test/ui/consts/const_let_assign2.rs index 4787c1750d2..28265c85dd1 100644 --- a/src/test/ui/consts/const_let_assign2.rs +++ b/src/test/ui/consts/const_let_assign2.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass pub struct AA { pub data: [u8; 10], diff --git a/src/test/ui/consts/control-flow/assert.panic.stderr b/src/test/ui/consts/control-flow/assert.const_panic.stderr index 03662a35209..03662a35209 100644 --- a/src/test/ui/consts/control-flow/assert.panic.stderr +++ b/src/test/ui/consts/control-flow/assert.const_panic.stderr diff --git a/src/test/ui/consts/control-flow/assert.rs b/src/test/ui/consts/control-flow/assert.rs index 30cd31ee8a7..90017fee193 100644 --- a/src/test/ui/consts/control-flow/assert.rs +++ b/src/test/ui/consts/control-flow/assert.rs @@ -1,14 +1,14 @@ // Test that `assert` works when `const_panic` is enabled. -// revisions: stock panic +// revisions: stock const_panic -#![cfg_attr(panic, feature(const_panic))] +#![cfg_attr(const_panic, feature(const_panic))] const _: () = assert!(true); //[stock]~^ ERROR panicking in constants is unstable const _: () = assert!(false); //[stock]~^ ERROR panicking in constants is unstable -//[panic]~^^ ERROR any use of this value will cause an error +//[const_panic]~^^ ERROR any use of this value will cause an error fn main() {} diff --git a/src/test/ui/default-alloc-error-hook.rs b/src/test/ui/default-alloc-error-hook.rs index 40f61c2b7d5..6871977c798 100644 --- a/src/test/ui/default-alloc-error-hook.rs +++ b/src/test/ui/default-alloc-error-hook.rs @@ -16,5 +16,5 @@ fn main() { let me = env::current_exe().unwrap(); let output = Command::new(&me).arg("next").output().unwrap(); assert!(!output.status.success(), "{:?} is a success", output.status); - assert_eq!(str::from_utf8(&output.stderr).unwrap(), "memory allocation of 42 bytes failed"); + assert_eq!(str::from_utf8(&output.stderr).unwrap(), "memory allocation of 42 bytes failed\n"); } diff --git a/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.rs b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.rs new file mode 100644 index 00000000000..adecd0ff291 --- /dev/null +++ b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.rs @@ -0,0 +1,7 @@ +#![feature(destructuring_assignment)] + +fn main() { + let mut x = &0; + let mut y = &0; + (x, y) = &(1, 2); //~ ERROR mismatched types +} diff --git a/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr new file mode 100644 index 00000000000..e6161fdfa24 --- /dev/null +++ b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/default-match-bindings-forbidden.rs:6:5 + | +LL | (x, y) = &(1, 2); + | ^^^^^^ ------- this expression has type `&({integer}, {integer})` + | | + | expected reference, found tuple + | + = note: expected type `&({integer}, {integer})` + found tuple `(_, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/destructuring-assignment/note-unsupported.rs b/src/test/ui/destructuring-assignment/note-unsupported.rs index 876c9efea26..e0cb9dc9158 100644 --- a/src/test/ui/destructuring-assignment/note-unsupported.rs +++ b/src/test/ui/destructuring-assignment/note-unsupported.rs @@ -3,23 +3,24 @@ struct S { x: u8, y: u8 } fn main() { let (a, b) = (1, 2); - (a, b) = (3, 4); //~ ERROR invalid left-hand side of assignment + (a, b) = (3, 4); //~ ERROR destructuring assignments are unstable (a, b) += (3, 4); //~ ERROR invalid left-hand side of assignment - //~^ ERROR binary assignment operation `+=` cannot be applied + //~| ERROR binary assignment operation `+=` cannot be applied [a, b] = [3, 4]; //~ ERROR invalid left-hand side of assignment [a, b] += [3, 4]; //~ ERROR invalid left-hand side of assignment - //~^ ERROR binary assignment operation `+=` cannot be applied + //~| ERROR binary assignment operation `+=` cannot be applied let s = S { x: 3, y: 4 }; S { x: a, y: b } = s; //~ ERROR invalid left-hand side of assignment S { x: a, y: b } += s; //~ ERROR invalid left-hand side of assignment - //~^ ERROR binary assignment operation `+=` cannot be applied + //~| ERROR binary assignment operation `+=` cannot be applied - S { x: a, ..s } = S { x: 3, y: 4 }; //~ ERROR invalid left-hand side of assignment + S { x: a, ..s } = S { x: 3, y: 4 }; + //~^ ERROR invalid left-hand side of assignment let c = 3; - ((a, b), c) = ((3, 4), 5); //~ ERROR invalid left-hand side of assignment + ((a, b), c) = ((3, 4), 5); //~ ERROR destructuring assignments are unstable } diff --git a/src/test/ui/destructuring-assignment/note-unsupported.stderr b/src/test/ui/destructuring-assignment/note-unsupported.stderr index d4e25930d22..c5543fab825 100644 --- a/src/test/ui/destructuring-assignment/note-unsupported.stderr +++ b/src/test/ui/destructuring-assignment/note-unsupported.stderr @@ -1,4 +1,4 @@ -error[E0070]: invalid left-hand side of assignment +error[E0658]: destructuring assignments are unstable --> $DIR/note-unsupported.rs:6:12 | LL | (a, b) = (3, 4); @@ -6,8 +6,19 @@ LL | (a, b) = (3, 4); | | | cannot assign to this expression | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error[E0658]: destructuring assignments are unstable + --> $DIR/note-unsupported.rs:25:17 + | +LL | ((a, b), c) = ((3, 4), 5); + | ----------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable error[E0368]: binary assignment operation `+=` cannot be applied to type `({integer}, {integer})` --> $DIR/note-unsupported.rs:7:5 @@ -24,9 +35,6 @@ LL | (a, b) += (3, 4); | ------ ^^ | | | cannot assign to this expression - | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 error[E0070]: invalid left-hand side of assignment --> $DIR/note-unsupported.rs:10:12 @@ -35,9 +43,6 @@ LL | [a, b] = [3, 4]; | ------ ^ | | | cannot assign to this expression - | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 error[E0368]: binary assignment operation `+=` cannot be applied to type `[{integer}; 2]` --> $DIR/note-unsupported.rs:11:5 @@ -54,9 +59,6 @@ LL | [a, b] += [3, 4]; | ------ ^^ | | | cannot assign to this expression - | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 error[E0070]: invalid left-hand side of assignment --> $DIR/note-unsupported.rs:16:22 @@ -65,9 +67,6 @@ LL | S { x: a, y: b } = s; | ---------------- ^ | | | cannot assign to this expression - | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 error[E0368]: binary assignment operation `+=` cannot be applied to type `S` --> $DIR/note-unsupported.rs:17:5 @@ -86,9 +85,6 @@ LL | S { x: a, y: b } += s; | ---------------- ^^ | | | cannot assign to this expression - | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 error[E0070]: invalid left-hand side of assignment --> $DIR/note-unsupported.rs:20:21 @@ -97,22 +93,8 @@ LL | S { x: a, ..s } = S { x: 3, y: 4 }; | --------------- ^ | | | cannot assign to this expression - | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 - -error[E0070]: invalid left-hand side of assignment - --> $DIR/note-unsupported.rs:24:17 - | -LL | ((a, b), c) = ((3, 4), 5); - | ----------- ^ - | | - | cannot assign to this expression - | - = note: destructuring assignments are not currently supported - = note: for more information, see https://github.com/rust-lang/rfcs/issues/372 error: aborting due to 11 previous errors -Some errors have detailed explanations: E0067, E0070, E0368. +Some errors have detailed explanations: E0067, E0070, E0368, E0658. For more information about an error, try `rustc --explain E0067`. diff --git a/src/test/ui/destructuring-assignment/tuple_destructure.rs b/src/test/ui/destructuring-assignment/tuple_destructure.rs new file mode 100644 index 00000000000..16aafc4693f --- /dev/null +++ b/src/test/ui/destructuring-assignment/tuple_destructure.rs @@ -0,0 +1,37 @@ +// run-pass + +#![feature(destructuring_assignment)] + +fn main() { + let (mut a, mut b); + (a, b) = (0, 1); + assert_eq!((a, b), (0, 1)); + (b, a) = (a, b); + assert_eq!((a, b), (1, 0)); + (a, .., b) = (1, 2); + assert_eq!((a, b), (1, 2)); + (.., a) = (1, 2); + assert_eq!((a, b), (2, 2)); + (..) = (3, 4); + assert_eq!((a, b), (2, 2)); + (b, ..) = (5, 6, 7); + assert_eq!(b, 5); + + // Test for a non-Copy type (String): + let (mut c, mut d); + (c, d) = ("c".to_owned(), "d".to_owned()); + assert_eq!(c, "c"); + assert_eq!(d, "d"); + (d, c) = (c, d); + assert_eq!(c, "d"); + assert_eq!(d, "c"); + + // Test nesting/parentheses: + ((a, b)) = (0, 1); + assert_eq!((a, b), (0, 1)); + (((a, b)), (c)) = ((2, 3), d); + assert_eq!((a, b), (2, 3)); + assert_eq!(c, "c"); + ((a, .., b), .., (..)) = ((4, 5), ()); + assert_eq!((a, b), (4, 5)); +} diff --git a/src/test/ui/destructuring-assignment/tuple_destructure_fail.rs b/src/test/ui/destructuring-assignment/tuple_destructure_fail.rs new file mode 100644 index 00000000000..b76f4968e62 --- /dev/null +++ b/src/test/ui/destructuring-assignment/tuple_destructure_fail.rs @@ -0,0 +1,10 @@ +#![feature(destructuring_assignment)] + +const C: i32 = 1; + +fn main() { + let (mut a, mut b); + (a, .., b, ..) = (0, 1); //~ ERROR `..` can only be used once per tuple pattern + (a, a, b) = (1, 2); //~ ERROR mismatched types + (C, ..) = (0,1); //~ ERROR invalid left-hand side of assignment +} diff --git a/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr new file mode 100644 index 00000000000..a60e1cb1eec --- /dev/null +++ b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr @@ -0,0 +1,31 @@ +error: `..` can only be used once per tuple pattern + --> $DIR/tuple_destructure_fail.rs:7:16 + | +LL | (a, .., b, ..) = (0, 1); + | -- ^^ can only be used once per tuple pattern + | | + | previously used here + +error[E0308]: mismatched types + --> $DIR/tuple_destructure_fail.rs:8:5 + | +LL | (a, a, b) = (1, 2); + | ^^^^^^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 3 elements + | + = note: expected type `({integer}, {integer})` + found tuple `(_, _, _)` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_destructure_fail.rs:9:13 + | +LL | (C, ..) = (0,1); + | - ^ + | | + | cannot assign to this expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0070, E0308. +For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/destructuring-assignment/warn-unused-duplication.rs b/src/test/ui/destructuring-assignment/warn-unused-duplication.rs new file mode 100644 index 00000000000..c1c5c2cd3ce --- /dev/null +++ b/src/test/ui/destructuring-assignment/warn-unused-duplication.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(destructuring_assignment)] + +#![warn(unused_assignments)] + +fn main() { + let mut a; + // Assignment occurs left-to-right. + // However, we emit warnings when this happens, so it is clear that this is happening. + (a, a) = (0, 1); //~ WARN value assigned to `a` is never read + assert_eq!(a, 1); + + // We can't always tell when a variable is being assigned to twice, which is why we don't try + // to emit an error, which would be fallible. + let mut x = 1; + (*foo(&mut x), *foo(&mut x)) = (5, 6); + assert_eq!(x, 6); +} + +fn foo<'a>(x: &'a mut u32) -> &'a mut u32 { + x +} diff --git a/src/test/ui/destructuring-assignment/warn-unused-duplication.stderr b/src/test/ui/destructuring-assignment/warn-unused-duplication.stderr new file mode 100644 index 00000000000..b87ef6f1571 --- /dev/null +++ b/src/test/ui/destructuring-assignment/warn-unused-duplication.stderr @@ -0,0 +1,15 @@ +warning: value assigned to `a` is never read + --> $DIR/warn-unused-duplication.rs:11:6 + | +LL | (a, a) = (0, 1); + | ^ + | +note: the lint level is defined here + --> $DIR/warn-unused-duplication.rs:5:9 + | +LL | #![warn(unused_assignments)] + | ^^^^^^^^^^^^^^^^^^ + = help: maybe it is overwritten before being read? + +warning: 1 warning emitted + diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.rs b/src/test/ui/feature-gates/feature-gate-cfg-panic.rs new file mode 100644 index 00000000000..1508374d942 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-panic.rs @@ -0,0 +1,11 @@ +#[cfg(panic = "unwind")] +//~^ ERROR `cfg(panic)` is experimental and subject to change +fn foo() -> bool { true } +#[cfg(not(panic = "unwind"))] +//~^ ERROR `cfg(panic)` is experimental and subject to change +fn foo() -> bool { false } + + +fn main() { + assert!(foo()); +} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr new file mode 100644 index 00000000000..ea5cd54fa90 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr @@ -0,0 +1,21 @@ +error[E0658]: `cfg(panic)` is experimental and subject to change + --> $DIR/feature-gate-cfg-panic.rs:1:7 + | +LL | #[cfg(panic = "unwind")] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #77443 <https://github.com/rust-lang/rust/issues/77443> for more information + = help: add `#![feature(cfg_panic)]` to the crate attributes to enable + +error[E0658]: `cfg(panic)` is experimental and subject to change + --> $DIR/feature-gate-cfg-panic.rs:4:11 + | +LL | #[cfg(not(panic = "unwind"))] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #77443 <https://github.com/rust-lang/rust/issues/77443> for more information + = help: add `#![feature(cfg_panic)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-destructuring_assignment.rs b/src/test/ui/feature-gates/feature-gate-destructuring_assignment.rs new file mode 100644 index 00000000000..e7801f0e8ec --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-destructuring_assignment.rs @@ -0,0 +1,4 @@ +fn main() { + let (a, b) = (0, 1); + (a, b) = (2, 3); //~ ERROR destructuring assignments are unstable +} diff --git a/src/test/ui/feature-gates/feature-gate-destructuring_assignment.stderr b/src/test/ui/feature-gates/feature-gate-destructuring_assignment.stderr new file mode 100644 index 00000000000..62e71decb32 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-destructuring_assignment.stderr @@ -0,0 +1,14 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/feature-gate-destructuring_assignment.rs:3:12 + | +LL | (a, b) = (2, 3); + | ------ ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs index 7490632110c..9348bb46dfe 100644 --- a/src/test/ui/fmt/format-args-capture.rs +++ b/src/test/ui/fmt/format-args-capture.rs @@ -1,13 +1,16 @@ // run-pass -// ignore-wasm32 -// ignore-wasm64 #![feature(format_args_capture)] +#![feature(cfg_panic)] fn main() { named_argument_takes_precedence_to_captured(); - panic_with_single_argument_does_not_get_formatted(); - panic_with_multiple_arguments_is_formatted(); formatting_parameters_can_be_captured(); + + #[cfg(panic = "unwind")] + { + panic_with_single_argument_does_not_get_formatted(); + panic_with_multiple_arguments_is_formatted(); + } } fn named_argument_takes_precedence_to_captured() { @@ -22,6 +25,7 @@ fn named_argument_takes_precedence_to_captured() { assert_eq!(&s, "positional-named-captured"); } +#[cfg(panic = "unwind")] fn panic_with_single_argument_does_not_get_formatted() { // panic! with a single argument does not perform string formatting. // RFC #2795 suggests that this may need to change so that captured arguments are formatted. @@ -34,6 +38,7 @@ fn panic_with_single_argument_does_not_get_formatted() { assert_eq!(msg.downcast_ref::<&str>(), Some(&"{foo}")) } +#[cfg(panic = "unwind")] fn panic_with_multiple_arguments_is_formatted() { let foo = "captured"; diff --git a/src/test/ui/issues/issue-68696-catch-during-unwind.rs b/src/test/ui/issues/issue-68696-catch-during-unwind.rs index d042bed225d..f25a78f59cd 100644 --- a/src/test/ui/issues/issue-68696-catch-during-unwind.rs +++ b/src/test/ui/issues/issue-68696-catch-during-unwind.rs @@ -4,8 +4,7 @@ // entering the catch_unwind. // // run-pass -// ignore-wasm no panic support -// ignore-emscripten no panic support +#![feature(cfg_panic)] use std::panic::catch_unwind; @@ -19,6 +18,7 @@ impl Drop for Guard { } fn main() { + #[cfg(panic = "unwind")] let _ = catch_unwind(|| { let _guard = Guard::default(); panic!(); diff --git a/src/test/ui/issues/issue-76547.nll.stderr b/src/test/ui/issues/issue-76547.nll.stderr new file mode 100644 index 00000000000..2456d6a1474 --- /dev/null +++ b/src/test/ui/issues/issue-76547.nll.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/issue-76547.rs:19:14 + | +LL | async fn fut(bufs: &mut [&mut [u8]]) { + | ^^^^ - - let's call the lifetime of this reference `'2` + | | | + | | let's call the lifetime of this reference `'1` + | assignment requires that `'1` must outlive `'2` + +error: lifetime may not live long enough + --> $DIR/issue-76547.rs:33:15 + | +LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { + | ^^^^ - - let's call the lifetime of this reference `'2` + | | | + | | let's call the lifetime of this reference `'1` + | assignment requires that `'1` must outlive `'2` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issues/issue-76547.rs b/src/test/ui/issues/issue-76547.rs new file mode 100644 index 00000000000..5b3ee5b95c4 --- /dev/null +++ b/src/test/ui/issues/issue-76547.rs @@ -0,0 +1,38 @@ +// Test for diagnostic improvement issue #76547 +// edition:2018 + +use std::{ + future::Future, + task::{Context, Poll} +}; +use std::pin::Pin; + +pub struct ListFut<'a>(&'a mut [&'a mut [u8]]); +impl<'a> Future for ListFut<'a> { + type Output = (); + + fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> { + unimplemented!() + } +} + +async fn fut(bufs: &mut [&mut [u8]]) { + ListFut(bufs).await + //~^ ERROR lifetime mismatch +} + +pub struct ListFut2<'a>(&'a mut [&'a mut [u8]]); +impl<'a> Future for ListFut2<'a> { + type Output = i32; + + fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> { + unimplemented!() + } +} + +async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { + ListFut2(bufs).await + //~^ ERROR lifetime mismatch +} + +fn main() {} diff --git a/src/test/ui/issues/issue-76547.stderr b/src/test/ui/issues/issue-76547.stderr new file mode 100644 index 00000000000..9bfb0f28028 --- /dev/null +++ b/src/test/ui/issues/issue-76547.stderr @@ -0,0 +1,25 @@ +error[E0623]: lifetime mismatch + --> $DIR/issue-76547.rs:20:13 + | +LL | async fn fut(bufs: &mut [&mut [u8]]) { + | --------- - + | | | + | | this `async fn` implicitly returns an `impl Future<Output = ()>` + | this parameter and the returned future are declared with different lifetimes... +LL | ListFut(bufs).await + | ^^^^ ...but data from `bufs` is held across an await point here + +error[E0623]: lifetime mismatch + --> $DIR/issue-76547.rs:34:14 + | +LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { + | --------- --- + | | | + | | this `async fn` implicitly returns an `impl Future<Output = i32>` + | this parameter and the returned future are declared with different lifetimes... +LL | ListFut2(bufs).await + | ^^^^ ...but data from `bufs` is held across an await point here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/macros/issue-78892-substitution-in-statement-attr.rs b/src/test/ui/macros/issue-78892-substitution-in-statement-attr.rs new file mode 100644 index 00000000000..9d1fae7a234 --- /dev/null +++ b/src/test/ui/macros/issue-78892-substitution-in-statement-attr.rs @@ -0,0 +1,14 @@ +// check-pass + +// regression test for #78892 + +macro_rules! mac { + ($lint_name:ident) => {{ + #[allow($lint_name)] + let _ = (); + }}; +} + +fn main() { + mac!(dead_code) +} diff --git a/src/test/ui/nll/issue-58053.stderr b/src/test/ui/nll/issue-58053.stderr index 297681ff403..e41ee8a8970 100644 --- a/src/test/ui/nll/issue-58053.stderr +++ b/src/test/ui/nll/issue-58053.stderr @@ -2,9 +2,9 @@ error: lifetime may not live long enough --> $DIR/issue-58053.rs:6:33 | LL | let f = |x: &i32| -> &i32 { x }; - | - ---- ^ returning this value requires that `'1` must outlive `'2` + | - - ^ returning this value requires that `'1` must outlive `'2` | | | - | | return type of closure is &'2 i32 + | | let's call the lifetime of this reference `'2` | let's call the lifetime of this reference `'1` error: lifetime may not live long enough diff --git a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs index 97a405b6999..30f3781bf77 100644 --- a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs +++ b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs @@ -1,4 +1,4 @@ -// Regression test; used to ICE with 'visit_mac disabled by default' due to a +// Regression test; used to ICE with 'visit_mac_call disabled by default' due to a // `MutVisitor` in `fn make_all_value_bindings_mutable` (`parse/parser/pat.rs`). macro_rules! mac1 { diff --git a/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs index 49de70ae013..72d82da4534 100644 --- a/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs +++ b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs @@ -1,7 +1,7 @@ // Test related to #22779. In this case, the impl is an inherent impl, // so it doesn't have to match any trait, so no error results. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(dead_code)] struct MySlice<'a, T:'a>(&'a mut [T]); diff --git a/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs index 4ce5daf3842..68056370c44 100644 --- a/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs +++ b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs @@ -1,7 +1,7 @@ // Test related to #22779, but where the `'a:'b` relation // appears in the trait too. No error here. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass trait Tr<'a, T> { fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b; diff --git a/src/test/ui/regions/region-object-lifetime-1.rs b/src/test/ui/regions/region-object-lifetime-1.rs index e58bd31d9cb..ddf3be690dd 100644 --- a/src/test/ui/regions/region-object-lifetime-1.rs +++ b/src/test/ui/regions/region-object-lifetime-1.rs @@ -1,7 +1,7 @@ // Various tests related to testing how region inference works // with respect to the object receivers. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(warnings)] trait Foo { diff --git a/src/test/ui/regions/region-object-lifetime-3.rs b/src/test/ui/regions/region-object-lifetime-3.rs index c3c7c51767d..0536fa2a20f 100644 --- a/src/test/ui/regions/region-object-lifetime-3.rs +++ b/src/test/ui/regions/region-object-lifetime-3.rs @@ -1,7 +1,7 @@ // Various tests related to testing how region inference works // with respect to the object receivers. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(warnings)] trait Foo { diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs index dcad2e81a54..a481a9cc5fe 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs @@ -2,7 +2,7 @@ // "projection gap": in this test, we know that `T: 'x`, and that is // enough to conclude that `T::Foo: 'x`. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(dead_code)] #![allow(unused_variables)] diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs index ff2e10804ae..a627cbbd88f 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs @@ -2,7 +2,7 @@ // "projection gap": in this test, we know that `T::Foo: 'x`, and that // is (naturally) enough to conclude that `T::Foo: 'x`. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(dead_code)] #![allow(unused_variables)] diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs index 3596bf7e8c2..5158c289340 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs @@ -2,7 +2,7 @@ // "projection gap": in this test, we know that `T: 'x`, and that // is (naturally) enough to conclude that `T: 'x`. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(dead_code)] #![allow(unused_variables)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs index fc4d1618401..15deaba5638 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs index d716cb9c55b..7767c13c825 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs index 39eb0842d3f..37415994210 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs index 561cad790f0..2e7f198d8c7 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs index e1287c34bac..45155c72166 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs index 0d59f44584c..bba8b244524 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs index cf0d96ba7ed..220d2e83cc0 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs index 069fc5dd008..9ddcdb649d8 100644 --- a/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs +++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs @@ -3,7 +3,7 @@ // // Rule OutlivesNominalType from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-outlives-projection-hrtype.rs b/src/test/ui/regions/regions-outlives-projection-hrtype.rs index e7fe7b6c16d..5f9700df1cb 100644 --- a/src/test/ui/regions/regions-outlives-projection-hrtype.rs +++ b/src/test/ui/regions/regions-outlives-projection-hrtype.rs @@ -5,7 +5,7 @@ // `'r` is bound, that leads to badness. This test checks that // everything works. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(dead_code)] trait TheTrait { diff --git a/src/test/ui/regions/regions-outlives-projection-trait-def.rs b/src/test/ui/regions/regions-outlives-projection-trait-def.rs index 928ed4baaa0..5c37a585a40 100644 --- a/src/test/ui/regions/regions-outlives-projection-trait-def.rs +++ b/src/test/ui/regions/regions-outlives-projection-trait-def.rs @@ -1,7 +1,7 @@ // Test that `<F as Foo<'a>>::Type: 'b`, where `trait Foo<'a> { Type: // 'a; }`, does not require that `F: 'b`. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(dead_code)] trait SomeTrait<'a> { diff --git a/src/test/ui/regions/regions-outlives-scalar.rs b/src/test/ui/regions/regions-outlives-scalar.rs index 5d0ed999380..ce34ffcc858 100644 --- a/src/test/ui/regions/regions-outlives-scalar.rs +++ b/src/test/ui/regions/regions-outlives-scalar.rs @@ -1,7 +1,7 @@ // Test that scalar values outlive all regions. // Rule OutlivesScalar from RFC 1214. -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(dead_code)] struct Foo<'a> { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr index 37297032632..e6846fb4049 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr @@ -2,25 +2,28 @@ error[E0623]: lifetime mismatch --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 | LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } - | ---- ---- ^ ...but data from `f` is returned here - | | - | this parameter and the return type are declared with different lifetimes... + | ---- ---- ^ ...but data from `f` is held across an await point here + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &Foo>` + | this parameter and the returned future are declared with different lifetimes... error[E0623]: lifetime mismatch --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:82 | LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - | ----- ----------------- ^ ...but data from `f` is returned here - | | - | this parameter and the return type are declared with different lifetimes... + | ----- ----------------- ^ ...but data from `f` is held across an await point here + | | | + | | this `async fn` implicitly returns an `impl Future<Output = (Pin<&Foo>, &Foo)>` + | this parameter and the returned future are declared with different lifetimes... error[E0623]: lifetime mismatch --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 | LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | ----- --- ^^^ ...but data from `arg` is returned here - | | - | this parameter and the return type are declared with different lifetimes... + | ----- --- ^^^ ...but data from `arg` is held across an await point here + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &()>` + | this parameter and the returned future are declared with different lifetimes... error: aborting due to 3 previous errors diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr index badd973c37f..3221d270850 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.stderr +++ b/src/test/ui/self/elision/lt-ref-self-async.stderr @@ -3,60 +3,66 @@ error[E0623]: lifetime mismatch | LL | async fn ref_self(&self, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:19:9 | LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:23:9 | LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:27:9 | LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:31:9 | LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:35:9 | LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr index 73d942a83f8..b6ca986923d 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.stderr +++ b/src/test/ui/self/elision/ref-mut-self-async.stderr @@ -3,60 +3,66 @@ error[E0623]: lifetime mismatch | LL | async fn ref_self(&mut self, f: &u32) -> &u32 { | --------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:19:9 | LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { | --------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:23:9 | LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { | --------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:27:9 | LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { | --------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:31:9 | LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { | --------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:35:9 | LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { | --------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr index 7d613c57448..eda15d76390 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.stderr +++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr @@ -3,50 +3,55 @@ error[E0623]: lifetime mismatch | LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { | ----------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:17:9 | LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { | ----------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:21:9 | LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { | ----------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:25:9 | LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { | ----------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:29:9 | LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { | ----------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr index bda958241b6..b42caa88c6f 100644 --- a/src/test/ui/self/elision/ref-self-async.stderr +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -3,70 +3,77 @@ error[E0623]: lifetime mismatch | LL | async fn ref_self(&self, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:29:9 | LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:33:9 | LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:37:9 | LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:41:9 | LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:45:9 | LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { | ----- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:49:9 | LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { | ----- --- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u8>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error: aborting due to 7 previous errors diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr index fc85450c4a7..599becd3080 100644 --- a/src/test/ui/self/elision/ref-struct-async.stderr +++ b/src/test/ui/self/elision/ref-struct-async.stderr @@ -3,50 +3,55 @@ error[E0623]: lifetime mismatch | LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { | ------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:17:9 | LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { | ------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:21:9 | LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { | ------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:25:9 | LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { | ------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:29:9 | LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { | ------- ---- - | | - | this parameter and the return type are declared with different lifetimes... + | | | + | | this `async fn` implicitly returns an `impl Future<Output = &u32>` + | this parameter and the returned future are declared with different lifetimes... LL | f - | ^ ...but data from `f` is returned here + | ^ ...but data from `f` is held across an await point here error: aborting due to 5 previous errors diff --git a/src/test/ui/test-attrs/test-allow-fail-attr.rs b/src/test/ui/test-attrs/test-allow-fail-attr.rs index 1a478460efc..29ce9f7c2e9 100644 --- a/src/test/ui/test-attrs/test-allow-fail-attr.rs +++ b/src/test/ui/test-attrs/test-allow-fail-attr.rs @@ -1,11 +1,12 @@ // run-pass -// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #![feature(allow_fail)] +#![feature(cfg_panic)] #[test] #[allow_fail] fn test1() { + #[cfg(not(panic = "abort"))] panic!(); } diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 9a8f2404e4a..687354dc6ae 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -155,6 +155,7 @@ static TARGETS: &[&str] = &[ ]; static DOCS_TARGETS: &[&str] = &[ + "aarch64-unknown-linux-gnu", "i686-apple-darwin", "i686-pc-windows-gnu", "i686-pc-windows-msvc", diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 32c2562ee95..5a4264f9b5c 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -3089,7 +3089,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { } } -/// Detect the occurences of calls to `iter` or `into_iter` for the +/// Detect the occurrences of calls to `iter` or `into_iter` for the /// given identifier fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> { let mut visitor = IterFunctionVisitor { diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index 485888fa944..6b175490cc8 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -1,6 +1,6 @@ use crate::utils::{span_lint, span_lint_and_then}; use rustc_ast::ast::{ - Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, MacCall, Pat, PatKind, + Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind, }; use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -150,9 +150,6 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { _ => walk_pat(self, pat), } } - fn visit_mac(&mut self, _mac: &MacCall) { - // do not check macs - } } #[must_use] @@ -357,9 +354,6 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { fn visit_item(&mut self, _: &Item) { // do not recurse into inner items } - fn visit_mac(&mut self, _mac: &MacCall) { - // do not check macs - } } impl EarlyLintPass for NonExpressiveNames { |
