diff --git a/Cargo.lock b/Cargo.lock index 9b6f75d8cb01f..7092e498e937e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", - "anstyle-parse", + "anstyle-parse 0.2.7", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse 1.0.0", "anstyle-query", "anstyle-wincon", "colorchoice", @@ -112,6 +127,15 @@ dependencies = [ "utf8parse", ] +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + [[package]] name = "anstyle-query" version = "1.1.5" @@ -129,7 +153,7 @@ checksum = "26b9ec8c976eada1b0f9747a3d7cc4eae3bef10613e443746e7487f26c872fde" dependencies = [ "anstyle", "anstyle-lossy", - "anstyle-parse", + "anstyle-parse 0.2.7", "html-escape", "unicode-width 0.2.2", ] @@ -147,9 +171,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "ar_archive_writer" @@ -373,9 +397,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytecheck" @@ -610,9 +634,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -630,11 +654,11 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "anstream", + "anstream 1.0.0", "anstyle", "clap_lex", "strsim", @@ -642,9 +666,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -654,15 +678,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "clippy" version = "0.1.98" dependencies = [ - "anstream", + "anstream 0.6.21", "askama", "cargo_metadata 0.23.1", "clippy_config", @@ -1337,7 +1361,7 @@ version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ - "anstream", + "anstream 0.6.21", "anstyle", "env_filter", "jiff", @@ -1696,11 +1720,6 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "foldhash 0.2.0", - "serde", - "serde_core", -] [[package]] name = "hashbrown" @@ -1709,6 +1728,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" dependencies = [ "foldhash 0.2.0", + "serde", + "serde_core", ] [[package]] @@ -2208,9 +2229,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "lexopt" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa0e2a1fcbe2f6be6c42e342259976206b383122fc152e872795338b5a3f3a7" +checksum = "803ec87c9cfb29b9d2633f20cba1f488db3fd53f2158b1024cbefb47ba05d413" [[package]] name = "libc" @@ -3114,9 +3135,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -3959,7 +3980,7 @@ name = "rustc_errors" version = "0.0.0" dependencies = [ "annotate-snippets 0.12.16", - "anstream", + "anstream 0.6.21", "anstyle", "derive_setters", "rustc_ast", @@ -5409,9 +5430,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.110" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -6024,9 +6045,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" @@ -6221,9 +6242,9 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter-provider" -version = "43.0.0" +version = "44.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93759d6fd0db242718bdcc6e4626eff8b0f3124ee7e58e47177a59f561baf164" +checksum = "2211ca2d69a88055eefb06bad741dde3180c9d4020f7e42fea72caba83f9c10c" [[package]] name = "wasip2" @@ -6290,9 +6311,9 @@ dependencies = [ [[package]] name = "wasm-component-ld" -version = "0.5.22" +version = "0.5.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216ca7b603f362831b31db4e2cdea1fa3609edd7177792fa64f62a80e10aa917" +checksum = "ee72c06c556db23aca2d29e1e183d96efdffa7110b24915629a5091de600a894" dependencies = [ "anyhow", "clap", @@ -6301,12 +6322,12 @@ dependencies = [ "libc", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.246.2", + "wasmparser 0.252.0", "wat", "windows-sys 0.61.2", "winsplit", - "wit-component 0.246.2", - "wit-parser 0.246.2", + "wit-component 0.252.0", + "wit-parser 0.252.0", ] [[package]] @@ -6338,12 +6359,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.246.2" +version = "0.252.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61fb705ce81adde29d2a8e99d87995e39a6e927358c91398f374474746070ef7" +checksum = "8185ae345fa5687c054626ff9a50e7089797a343d9904d1dc9820eb4c4d3196f" dependencies = [ "leb128fmt", - "wasmparser 0.246.2", + "wasmparser 0.252.0", ] [[package]] @@ -6360,14 +6381,14 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.246.2" +version = "0.252.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e4c2aa916c425dcca61a6887d3e135acdee2c6d0ed51fd61c08d41ddaf62b1" +checksum = "2b7e08e02a3cd55bf778009d4cd6faae50da011f293644daf78a531a32d6d142" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.246.2", - "wasmparser 0.246.2", + "wasm-encoder 0.252.0", + "wasmparser 0.252.0", ] [[package]] @@ -6404,12 +6425,12 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.246.2" +version = "0.252.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71cde4757396defafd25417cfb36aa3161027d06d865b0c24baaae229aac005d" +checksum = "d3eb099dcadcde5be9eef55e3a337128efd4e44b4c93122487e4d2e4e1c6627c" dependencies = [ "bitflags", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "indexmap", "semver", "serde", @@ -6417,22 +6438,22 @@ dependencies = [ [[package]] name = "wast" -version = "246.0.2" +version = "252.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3fe8e3bf88ad96d031b4181ddbd64634b17cb0d06dfc3de589ef43591a9a62" +checksum = "942a3449d6a593fccc111a6241c8df52bda168af30e40bf9580d4394d7374c65" dependencies = [ "bumpalo", "leb128fmt", "memchr", "unicode-width 0.2.2", - "wasm-encoder 0.246.2", + "wasm-encoder 0.252.0", ] [[package]] name = "wat" -version = "1.246.2" +version = "1.252.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd7fda1199b94fff395c2d19a153f05dbe7807630316fa9673367666fd2ad8c" +checksum = "c72a4ba7088f7bac94cf516e49882bdf97068904a563768cf249efc839ec42cb" dependencies = [ "wast", ] @@ -6868,9 +6889,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.246.2" +version = "0.252.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1936c26cb24b93dc36bf78fb5dc35c55cd37f66ecdc2d2663a717d9fb3ee951e" +checksum = "76db0662b590f45d33d0e363fa13539a5a1eecd35d5a12fe208c335461c1053d" dependencies = [ "anyhow", "bitflags", @@ -6879,10 +6900,10 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.246.2", - "wasm-metadata 0.246.2", - "wasmparser 0.246.2", - "wit-parser 0.246.2", + "wasm-encoder 0.252.0", + "wasm-metadata 0.252.0", + "wasmparser 0.252.0", + "wit-parser 0.252.0", ] [[package]] @@ -6905,12 +6926,12 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.246.2" +version = "0.252.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd979042b5ff288607ccf3b314145435453f20fc67173195f91062d2289b204d" +checksum = "4266bea110371c620ccf3201c5023676046bc4556e5c7cfb5d500bda5ebc162d" dependencies = [ "anyhow", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "id-arena", "indexmap", "log", @@ -6918,8 +6939,8 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "unicode-xid", - "wasmparser 0.246.2", + "unicode-ident", + "wasmparser 0.252.0", ] [[package]] diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index f1a1abf0e635e..45dd7c15526a8 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -370,10 +370,10 @@ fn bounds_from_generic_predicates<'tcx>( let mut projections_str = vec![]; for projection in &projections { let p = projection.skip_binder(); - if bound == tcx.parent(p.projection_term.def_id()) + if bound == p.projection_term.trait_def_id(tcx) && p.projection_term.self_ty() == ty { - let name = tcx.item_name(p.projection_term.def_id()); + let name = tcx.item_name(p.projection_term.expect_projection_def_id()); projections_str.push(format!("{} = {}", name, p.term)); } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index cbb82271b5c99..4fca6b93f1fff 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1633,10 +1633,8 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: let pred_binder = proj .map_bound(|pred| { pred.term.as_const().map(|ct| { - let assoc_const_ty = tcx - .type_of(pred.projection_term.def_id()) - .instantiate(tcx, pred.projection_term.args) - .skip_norm_wip(); + let assoc_const_ty = + pred.projection_term.expect_ct().type_of(tcx).skip_norm_wip(); ty::ClauseKind::ConstArgHasType(ct, assoc_const_ty) }) }) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 35ab34c6c0e4d..48b281851d3db 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -15,7 +15,6 @@ //! crate as a kind of pass. This should eventually be factored away. use std::cell::Cell; -use std::ops::ControlFlow; use std::{assert_matches, iter}; use rustc_abi::{ExternAbi, Size}; @@ -24,13 +23,12 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, Diagnostic, E0228, ErrorGuaranteed, Level, StashKey, }; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; -use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ @@ -1636,20 +1634,6 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id)); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE - } else if tcx.features().generic_const_args() { - // Only anon consts that are the RHS of a const item can be GCA. - // Note: We can't just check tcx.parent because it needs to be EXACTLY - // the RHS, not just part of the RHS. - if !is_anon_const_rhs_of_const_item(tcx, def) { - return ty::AnonConstKind::MCG; - } - - let body = tcx.hir_body_owned_by(def); - let mut visitor = GCAParamVisitor(tcx); - match visitor.visit_body(body) { - ControlFlow::Break(UsesParam) => ty::AnonConstKind::GCA, - ControlFlow::Continue(()) => ty::AnonConstKind::MCG, - } } else if tcx.features().min_generic_const_args() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { @@ -1667,49 +1651,6 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin } } -fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false }; - let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. }) - | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. }) - | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(_, Some(ct_rhs)), .. - })) = grandparent_node - else { - return false; - }; - let hir::ConstItemRhs::TypeConst(hir::ConstArg { - kind: hir::ConstArgKind::Anon(rhs_anon), .. - }) = ct_rhs - else { - return false; - }; - def_id == rhs_anon.def_id -} - -struct GCAParamVisitor<'tcx>(TyCtxt<'tcx>); - -struct UsesParam; - -impl<'tcx> Visitor<'tcx> for GCAParamVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - type Result = ControlFlow; - - fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { - self.0 - } - - fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow { - if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) = - path.res - { - return ControlFlow::Break(UsesParam); - } - - intravisit::walk_path(self, path) - } -} - #[instrument(level = "debug", skip(tcx), ret)] fn const_of_item<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 94bd2b1d2a056..64f12fd6644c5 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -97,8 +97,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { match tcx.anon_const_kind(def_id) { // Stable: anon consts are not able to use any generic parameters... ty::AnonConstKind::MCG => None, - // GCA anon consts inherit their parent's generics. - ty::AnonConstKind::GCA => Some(parent_did), // we provide generics to repeat expr counts as a backwards compatibility hack. #76200 ty::AnonConstKind::RepeatExprCount => Some(parent_did), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 4dba70cbd56b0..4b2e51f74b973 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -494,9 +494,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => { - let ty = projection_term.map_bound(|alias| { - tcx.type_of(alias.def_id()).instantiate(tcx, alias.args).skip_norm_wip() - }); + let ty = projection_term + .map_bound(|alias| alias.expect_ct().type_of(tcx).skip_norm_wip()); let ty = check_assoc_const_binding_type( self, constraint.ident, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index b8cdd67519bef..c387855838779 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -487,9 +487,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(mgca): code duplication with other places we lower // the rhs' of associated const bindings let ty = projection_term.map_bound(|alias| { - tcx.type_of(alias.def_id()) - .instantiate(tcx, alias.args) - .skip_norm_wip() + alias.expect_ct().type_of(tcx).skip_norm_wip() }); let ty = super::bounds::check_assoc_const_binding_type( self, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index bc3e526a362a8..61bde9e7e39b8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -409,7 +409,7 @@ impl<'tcx> ForbidParamUsesFolder<'tcx> { } ForbidParamContext::ConstArgument => { if self.tcx.features().generic_const_args() { - "generic parameters in const blocks are only allowed as the direct value of a `type const`" + "generic parameters in const blocks are not allowed; use a named `const` item instead" } else { "generic parameters may not be used in const operations" } @@ -535,9 +535,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None } } - ty::AnonConstKind::GCE - | ty::AnonConstKind::GCA - | ty::AnonConstKind::RepeatExprCount => None, + ty::AnonConstKind::GCE | ty::AnonConstKind::RepeatExprCount => None, } } @@ -1357,9 +1355,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { LowerTypeRelativePathMode::Type(permit_variants), )? { TypeRelativePath::AssocItem(alias_term) => { - let ty = alias_term.expect_ty().to_ty(tcx); + let alias_ty = alias_term.expect_ty(); + let def_id = alias_ty.kind.def_id(); + let ty = alias_ty.to_ty(tcx); let ty = self.check_param_uses_if_mcg(ty, span, false); - Ok((ty, tcx.def_kind(alias_term.def_id()), alias_term.def_id())) + Ok((ty, tcx.def_kind(def_id), def_id)) } TypeRelativePath::Variant { adt, variant_did } => { let adt = self.check_param_uses_if_mcg(adt, span, false); @@ -1392,8 +1392,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { LowerTypeRelativePathMode::Const, )? { TypeRelativePath::AssocItem(alias_term) => { - self.require_type_const_attribute(alias_term.def_id(), span)?; - let ct = Const::new_unevaluated(tcx, alias_term.expect_ct()); + let alias_ct = alias_term.expect_ct(); + if let Some(def_id) = alias_ct.kind.opt_def_id() { + self.require_type_const_attribute(def_id, span)?; + } + let ct = Const::new_unevaluated(tcx, alias_ct); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 763d2a27e6cc0..570d33aaf20e0 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -1056,7 +1056,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The `Future` trait has only one associated item, `Output`, // so check that this is what we see. let output_assoc_item = self.tcx.associated_item_def_ids(trait_def_id)[0]; - if output_assoc_item != predicate.projection_term.def_id() { + if output_assoc_item != predicate.def_id() { span_bug!( cause_span, "projecting associated item `{:?}` from future, which is not Output `{:?}`", diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index c3a5a8a5d818d..d600b5fb1b0d3 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -22,7 +22,7 @@ impl<'tcx> InferCtxt<'tcx> { ) -> Term<'tcx> { debug_assert!(!self.next_trait_solver()); - let span = self.tcx.def_span(alias_term.def_id()); + let span = self.tcx.def_span(alias_term.expect_projection_def_id()); let infer_var = if alias_term.kind.is_type() { self.next_ty_var(span).into() } else { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index f646a558266e2..3fb929aa92216 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -130,11 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { return; } - let proj_ty = Ty::new_projection_from_args( - cx.tcx, - proj.projection_term.def_id(), - proj.projection_term.args, - ); + let proj_ty = proj.projection_term.expect_ty().to_ty(cx.tcx); // For every instance of the projection type in the bounds, // replace them with the term we're assigning to the associated // type in our opaque type. @@ -149,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // with `impl Send: OtherTrait`. for (assoc_pred, assoc_pred_span) in cx .tcx - .explicit_item_bounds(proj.projection_term.def_id()) + .explicit_item_bounds(proj.def_id()) .iter_instantiated_copied(cx.tcx, proj.projection_term.args) .map(Unnormalized::skip_norm_wip) { diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 18f93e050e745..51572e1ec7719 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -53,6 +53,14 @@ impl<'tcx> TyCtxt<'tcx> { } } + // Ensure closure shims have the optimization properties of their closure applied to them. + if let InstanceKind::ClosureOnceShim { call_once: _, closure, track_caller: _ } = + instance_kind + { + let closure_attrs = self.codegen_fn_attrs(closure); + attrs.to_mut().optimize = closure_attrs.optimize; + } + attrs } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index fbe22ecc06e47..cdf321b1c5af3 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -351,7 +351,7 @@ macro_rules! make_mir_visitor { | ty::InstanceKind::ReifyShim(_def_id, _) | ty::InstanceKind::Virtual(_def_id, _) | ty::InstanceKind::ThreadLocalShim(_def_id) - | ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ } + | ty::InstanceKind::ClosureOnceShim { call_once: _def_id, closure: _, track_caller: _ } | ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, receiver_by_ref: _, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 81cd3efffc9d4..8dda3603df9df 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -98,8 +98,8 @@ impl<'tcx> TypeError<'tcx> { .into(), TypeError::ProjectionMismatched(ref values) => format!( "expected `{}`, found `{}`", - tcx.def_path_str(values.expected), - tcx.def_path_str(values.found) + tcx.alias_term_kind_def_path_str(values.expected), + tcx.alias_term_kind_def_path_str(values.found) ) .into(), TypeError::ExistentialMismatch(ref values) => report_maybe_different( @@ -309,4 +309,17 @@ impl<'tcx> TyCtxt<'tcx> { Err(_) => regular, } } + + pub fn alias_term_kind_def_path_str(self, alias: ty::AliasTermKind<'tcx>) -> String { + match alias { + ty::AliasTermKind::ProjectionTy { def_id } + | ty::AliasTermKind::InherentTy { def_id } + | ty::AliasTermKind::OpaqueTy { def_id } + | ty::AliasTermKind::FreeTy { def_id } + | ty::AliasTermKind::AnonConst { def_id } + | ty::AliasTermKind::ProjectionConst { def_id } + | ty::AliasTermKind::FreeConst { def_id } + | ty::AliasTermKind::InherentConst { def_id } => self.def_path_str(def_id), + } + } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 386ae428bbbd9..f85355330d6b8 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -122,7 +122,7 @@ pub enum InstanceKind<'tcx> { /// /// This generates a body that will just borrow the (owned) self type, /// and dispatch to the `FnMut::call_mut` instance for the closure. - ClosureOnceShim { call_once: DefId, track_caller: bool }, + ClosureOnceShim { call_once: DefId, closure: DefId, track_caller: bool }, /// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once` /// @@ -250,7 +250,7 @@ impl<'tcx> InstanceKind<'tcx> { | InstanceKind::Virtual(def_id, _) | InstanceKind::Intrinsic(def_id) | InstanceKind::ThreadLocalShim(def_id) - | InstanceKind::ClosureOnceShim { call_once: def_id, track_caller: _ } + | InstanceKind::ClosureOnceShim { call_once: def_id, closure: _, track_caller: _ } | ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id: def_id, receiver_by_ref: _, @@ -313,7 +313,9 @@ impl<'tcx> InstanceKind<'tcx> { InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => { tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } - InstanceKind::ClosureOnceShim { call_once: _, track_caller } => track_caller, + InstanceKind::ClosureOnceShim { call_once: _, closure: _, track_caller } => { + track_caller + } _ => false, } } @@ -766,7 +768,8 @@ impl<'tcx> Instance<'tcx> { .def_id; let track_caller = tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER); - let def = ty::InstanceKind::ClosureOnceShim { call_once, track_caller }; + let def = + ty::InstanceKind::ClosureOnceShim { call_once, closure: closure_did, track_caller }; let self_ty = Ty::new_closure(tcx, closure_did, args); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fc7e8fd768c9b..1926930333629 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1344,17 +1344,18 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { fn pretty_print_inherent_projection( &mut self, - alias_ty: ty::AliasTerm<'tcx>, + alias_term: ty::AliasTerm<'tcx>, ) -> Result<(), PrintError> { - let def_key = self.tcx().def_key(alias_ty.def_id()); + let alias_def_id = alias_term.expect_inherent_def_id(); + let def_key = self.tcx().def_key(alias_def_id); self.print_path_with_generic_args( |p| { p.print_path_with_simple( - |p| p.print_path_with_qualified(alias_ty.self_ty(), None), + |p| p.print_path_with_qualified(alias_term.self_ty(), None), &def_key.disambiguated_data, ) }, - &alias_ty.args[1..], + &alias_term.args[1..], ) } @@ -3157,7 +3158,9 @@ define_print! { ty::AliasTerm<'tcx> { match self.kind { - ty::AliasTermKind::InherentTy {..} | ty::AliasTermKind::InherentConst {..} => p.pretty_print_inherent_projection(*self)?, + ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } => { + p.pretty_print_inherent_projection(*self)?; + } ty::AliasTermKind::ProjectionTy { def_id } => { if !(p.should_print_verbose() || with_reduced_queries()) && p.tcx().is_impl_trait_in_trait(def_id) diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index dede4a31d88fa..6bb70cee7603a 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -62,7 +62,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< ty::InstanceKind::ReifyShim(def_id, _) => { build_call_shim(tcx, instance, None, CallKind::Direct(def_id)) } - ty::InstanceKind::ClosureOnceShim { call_once: _, track_caller: _ } => { + ty::InstanceKind::ClosureOnceShim { call_once: _, closure: _, track_caller: _ } => { let fn_mut = tcx.require_lang_item(LangItem::FnMut, DUMMY_SP); let call_mut = tcx .associated_items(fn_mut) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 660f1ec706aa8..2464d607f20ad 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -925,10 +925,7 @@ where // show up in the bounds, but just ones that come from substituting // `Self` with the dyn type. let proj = proj.with_self_ty(cx, trait_ref.self_ty()); - replace_projection_with - .entry(proj.def_id().into()) - .or_default() - .push(bound.rebind(proj)); + replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj)); } } @@ -952,7 +949,7 @@ struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate, param_env: I::ParamEnv, self_ty: I::Ty, - mapping: &'a HashMap>>>, + mapping: &'a HashMap>>>, nested: Vec>, } @@ -966,7 +963,7 @@ where source_projection: ty::Binder>, target_projection: ty::AliasTerm, ) -> bool { - source_projection.item_def_id() == target_projection.def_id() + source_projection.item_def_id() == target_projection.expect_projection_def_id() && self .ecx .probe(|_| ProbeKind::ProjectionCompatibility) @@ -990,7 +987,7 @@ where return Ok(None); } - let Some(replacements) = self.mapping.get(&alias_term.def_id()) else { + let Some(replacements) = self.mapping.get(&alias_term.expect_projection_def_id()) else { return Ok(None); }; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c053f106155dc..e1713df023680 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1240,7 +1240,17 @@ where // // Alternatively we could modify `Equate` for this case by adding another // variant to `StructurallyRelateAliases`. - let identity_args = self.fresh_args_for_item(alias.def_id()); + let def_id = match alias.kind { + ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(), + ty::AliasTermKind::InherentTy { def_id } => def_id.into(), + ty::AliasTermKind::OpaqueTy { def_id } => def_id.into(), + ty::AliasTermKind::FreeTy { def_id } => def_id.into(), + ty::AliasTermKind::AnonConst { def_id } => def_id.into(), + ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(), + ty::AliasTermKind::FreeConst { def_id } => def_id.into(), + ty::AliasTermKind::InherentConst { def_id } => def_id.into(), + }; + let identity_args = self.fresh_args_for_item(def_id); let rigid_ctor = alias.with_args(cx, identity_args); let ctor_term = rigid_ctor.to_term(cx); let obligations = self.delegate.eq_structurally_relating_aliases( diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index 38197c8c72de2..1813bd720cbb7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -14,7 +14,6 @@ where pub(super) fn normalize_anon_const( &mut self, goal: Goal>, - def_id: I::UnevaluatedConstId, ) -> QueryResultOrRerunNonErased { let uv = goal.predicate.alias.expect_ct(); self.evaluate_const_and_instantiate_normalizes_to_term(goal, uv) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs index ad050b69425c5..22d8634c2ff89 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -25,7 +25,7 @@ where // Check where clauses self.add_goals( GoalSource::Misc, - cx.predicates_of(free_alias.def_id()) + cx.predicates_of(free_alias.expect_free_def_id().into()) .iter_instantiated(cx, free_alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 85d079e84073e..9864b92ad57df 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -19,11 +19,10 @@ where pub(super) fn normalize_inherent_associated_term( &mut self, goal: Goal>, - def_id: I::InherentAssocTermId, ) -> QueryResultOrRerunNonErased { let cx = self.cx(); let inherent = goal.predicate.alias; - + let def_id = inherent.expect_inherent_def_id(); let impl_def_id = cx.inherent_alias_term_parent(def_id); let impl_args = self.fresh_args_for_item(impl_def_id.into()); diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 4f403bbeefed2..b85a19045aef2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -39,19 +39,14 @@ where ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => { self.normalize_associated_term(goal) } - ty::AliasTermKind::InherentTy { def_id } => { - self.normalize_inherent_associated_term(goal, def_id.into()) + ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } => { + self.normalize_inherent_associated_term(goal) } - ty::AliasTermKind::InherentConst { def_id } => { - self.normalize_inherent_associated_term(goal, def_id.into()) - } - ty::AliasTermKind::OpaqueTy { def_id } => self.normalize_opaque_type(goal, def_id), + ty::AliasTermKind::OpaqueTy { .. } => self.normalize_opaque_type(goal), ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => { - self.normalize_free_alias(goal).map_err(Into::into) - } - ty::AliasTermKind::AnonConst { def_id } => { - self.normalize_anon_const(goal, def_id).map_err(Into::into) + self.normalize_free_alias(goal) } + ty::AliasTermKind::AnonConst { .. } => self.normalize_anon_const(goal), } } @@ -150,8 +145,7 @@ where if let Some(ct) = term.as_const() { let cx = self.cx(); let alias = goal.predicate.alias; - let expected_ty = - cx.type_of(alias.def_id()).instantiate(cx, alias.args).skip_norm_wip(); + let expected_ty = alias.expect_ct().type_of(cx).skip_norm_wip(); self.add_goal( GoalSource::Misc, goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), @@ -199,8 +193,13 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { + let alias_def_id = match goal.predicate.alias.kind { + ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(), + ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(), + _ => return Err(NoSolution), + }; if let Some(projection_pred) = assumption.as_projection_clause() - && projection_pred.item_def_id() == goal.predicate.def_id() + && projection_pred.item_def_id() == alias_def_id && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.alias.args, projection_pred.skip_binder().projection_term.args, @@ -229,7 +228,7 @@ where // FIXME: We don't need these, since these are the type's own WF obligations. ecx.add_goals( GoalSource::AliasWellFormed, - cx.own_predicates_of(goal.predicate.def_id()) + cx.own_predicates_of(goal.predicate.alias.expect_projection_def_id().into()) .iter_instantiated(cx, goal.predicate.alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), @@ -268,6 +267,7 @@ where ) -> Result, NoSolutionOrRerunNonErased> { let cx = ecx.cx(); + let alias_def_id = goal.predicate.alias.expect_projection_def_id(); let goal_trait_ref = goal.predicate.alias.trait_ref(cx); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify( @@ -311,7 +311,7 @@ where // see tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs. ecx.add_goals( GoalSource::AliasWellFormed, - cx.own_predicates_of(goal.predicate.def_id()) + cx.own_predicates_of(alias_def_id.into()) .iter_instantiated(cx, goal.predicate.alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), @@ -327,53 +327,57 @@ where ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }; - let target_item_def_id = match ecx.fetch_eligible_assoc_item( - goal_trait_ref, - goal.predicate.def_id().try_into().unwrap(), - impl_def_id, - ) { - FetchEligibleAssocItemResponse::Found(target_item_def_id) => target_item_def_id, - FetchEligibleAssocItemResponse::NotFound(tm) => { - match tm { - // In case the associated item is hidden due to specialization, - // normalizing this associated item is always ambiguous. Treating - // the associated item as rigid would be incomplete and allow for - // overlapping impls, see #105782. - // - // As this ambiguity is unavoidable we emit a nested ambiguous - // goal instead of using `Certainty::AMBIGUOUS`. This allows us to - // return the nested goals to the parent `AliasRelate` goal. This - // would be relevant if any of the nested goals refer to the `term`. - // This is not the case here and we only prefer adding an ambiguous - // nested goal for consistency. - ty::TypingMode::Coherence => { - ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous)); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - .map_err(Into::into); - } - // Outside of coherence, we treat the associated item as rigid instead. - ty::TypingMode::Typeck { .. } - | ty::TypingMode::PostTypeckUntilBorrowck { .. } - | ty::TypingMode::PostBorrowck { .. } - | ty::TypingMode::PostAnalysis - | ty::TypingMode::Codegen => { - ecx.structurally_instantiate_normalizes_to_term( - goal, - goal.predicate.alias, - ); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - .map_err(Into::into); - } - }; - } - FetchEligibleAssocItemResponse::Err(guar) => return error_response(ecx, guar), - FetchEligibleAssocItemResponse::NotFoundBecauseErased => { - ecx.opaque_accesses.rerun_always(RerunReason::FetchEligibleAssocItem)?; - return Err(NoSolution.into()); - } - }; + let target_item_def_id = + match ecx.fetch_eligible_assoc_item(goal_trait_ref, alias_def_id, impl_def_id) { + FetchEligibleAssocItemResponse::Found(target_item_def_id) => target_item_def_id, + FetchEligibleAssocItemResponse::NotFound(tm) => { + match tm { + // In case the associated item is hidden due to specialization, + // normalizing this associated item is always ambiguous. Treating + // the associated item as rigid would be incomplete and allow for + // overlapping impls, see #105782. + // + // As this ambiguity is unavoidable we emit a nested ambiguous + // goal instead of using `Certainty::AMBIGUOUS`. This allows us to + // return the nested goals to the parent `AliasRelate` goal. This + // would be relevant if any of the nested goals refer to the `term`. + // This is not the case here and we only prefer adding an ambiguous + // nested goal for consistency. + ty::TypingMode::Coherence => { + ecx.add_goal( + GoalSource::Misc, + goal.with(cx, PredicateKind::Ambiguous), + ); + return ecx + .evaluate_added_goals_and_make_canonical_response( + Certainty::Yes, + ) + .map_err(Into::into); + } + // Outside of coherence, we treat the associated item as rigid instead. + ty::TypingMode::Typeck { .. } + | ty::TypingMode::PostTypeckUntilBorrowck { .. } + | ty::TypingMode::PostBorrowck { .. } + | ty::TypingMode::PostAnalysis + | ty::TypingMode::Codegen => { + ecx.structurally_instantiate_normalizes_to_term( + goal, + goal.predicate.alias, + ); + return ecx + .evaluate_added_goals_and_make_canonical_response( + Certainty::Yes, + ) + .map_err(Into::into); + } + }; + } + FetchEligibleAssocItemResponse::Err(guar) => return error_response(ecx, guar), + FetchEligibleAssocItemResponse::NotFoundBecauseErased => { + ecx.opaque_accesses.rerun_always(RerunReason::FetchEligibleAssocItem)?; + return Err(NoSolution.into()); + } + }; if !cx.has_item_definition(target_item_def_id) { // If the impl is missing an item, it's either because the user forgot to @@ -569,7 +573,7 @@ where goal_kind: ty::ClosureKind, ) -> Result, NoSolutionOrRerunNonErased> { let cx = ecx.cx(); - let def_id = goal.predicate.def_id().try_into().unwrap(); + let def_id = goal.predicate.alias.expect_projection_ty_def_id(); let env_region = match goal_kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), @@ -631,7 +635,7 @@ where coroutine_return_ty.into(), ) } else { - panic!("no such associated type in `AsyncFn*`: {:?}", goal.predicate.def_id()) + panic!("no such associated type in `AsyncFn*`: {:?}", def_id) }; let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx); @@ -707,7 +711,10 @@ where ) -> Result, NoSolutionOrRerunNonErased> { let cx = ecx.cx(); let metadata_def_id = cx.require_projection_lang_item(SolverProjectionLangItem::Metadata); - assert_eq!(Into::::into(metadata_def_id), goal.predicate.def_id()); + assert_eq!( + ty::AliasTermKind::ProjectionTy { def_id: metadata_def_id }, + goal.predicate.alias.kind + ); let metadata_ty = match goal.predicate.self_ty().kind() { ty::Bool | ty::Char @@ -931,7 +938,7 @@ where } let coroutine = args.as_coroutine(); - let def_id = goal.predicate.def_id().try_into().unwrap(); + let def_id = goal.predicate.alias.expect_projection_ty_def_id(); let term = if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineReturn) { @@ -939,7 +946,7 @@ where } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineYield) { coroutine.yield_ty().into() } else { - panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id()) + panic!("unexpected associated item `{:?}` for `{self_ty:?}`", def_id) }; Self::probe_and_consider_implied_clause( @@ -1060,8 +1067,8 @@ where else { return Err(NoSolution.into()); }; - let ty = match ecx.cx().as_projection_lang_item(goal.predicate.def_id().try_into().unwrap()) - { + let def_id = goal.predicate.alias.expect_projection_ty_def_id(); + let ty = match ecx.cx().as_projection_lang_item(def_id) { Some(SolverProjectionLangItem::FieldBase) => base, Some(SolverProjectionLangItem::FieldType) => ty, _ => panic!("unexpected associated type {:?} in `Field`", goal.predicate), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 83469c4897aa1..2e56e98f8c9be 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -17,11 +17,11 @@ where pub(super) fn normalize_opaque_type( &mut self, goal: Goal>, - def_id: I::OpaqueTyId, ) -> QueryResultOrRerunNonErased { let cx = self.cx(); let opaque_ty = goal.predicate.alias; let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); + let def_id = opaque_ty.expect_opaque_ty_def_id(); match self.typing_mode() { TypingMode::Coherence => { @@ -113,10 +113,9 @@ where .map_err(Into::into) } TypingMode::PostBorrowck { defined_opaque_types } => { - let Some(def_id) = opaque_ty - .def_id() + let Some(def_id) = def_id .as_local() - .filter(|&def_id| defined_opaque_types.contains(&def_id)) + .filter(|&def_id| defined_opaque_types.contains(&def_id.into())) else { self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); return self @@ -146,15 +145,13 @@ where .map_err(Into::into) } TypingMode::ErasedNotCoherence(MayBeErased) => { - let def_id = opaque_ty.def_id().as_local(); - // If we have a local defid, in other typing modes we check whether // this is the defining scope, and otherwise treat it as rigid. // However, in `ErasedNotcoherence` we *always* treat it as rigid. // This is the same as other modes if def_id is None, but wrong if we do have a DefId. // So, if we have one, we register in the EvalCtxt that we may need that defid. // We might then decide to rerun in the correct typing mode. - if let Some(def_id) = def_id { + if let Some(def_id) = def_id.as_local() { self.opaque_accesses.rerun_if_opaque_in_opaque_type_storage( RerunReason::NormalizeOpaqueType, def_id, diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 7c9e7c584d238..4218c21f508d3 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -47,10 +47,18 @@ impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> { cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::AliasTerm { args, kind, .. } = self; - crate::ty::AliasTerm { - def_id: tables.alias_def(kind.def_id()), - args: args.stable(tables, cx), - } + // rustc_public must change its API once we introduce a variant without a def_id. + let def_id = match *kind { + ty::AliasTermKind::ProjectionTy { def_id } + | ty::AliasTermKind::InherentTy { def_id } + | ty::AliasTermKind::OpaqueTy { def_id } + | ty::AliasTermKind::FreeTy { def_id } + | ty::AliasTermKind::AnonConst { def_id } + | ty::AliasTermKind::ProjectionConst { def_id } + | ty::AliasTermKind::FreeConst { def_id } + | ty::AliasTermKind::InherentConst { def_id } => def_id, + }; + crate::ty::AliasTerm { def_id: tables.alias_def(def_id), args: args.stable(tables, cx) } } } @@ -475,8 +483,8 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( fields.iter().map(|ty| ty.stable(tables, cx)).collect(), )), - ty::Alias(_alias_ty) => { - todo!() + ty::Alias(alias_ty) => { + TyKind::Alias(alias_ty.kind.stable(tables, cx), alias_ty.stable(tables, cx)) } ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables, cx)), ty::Bound(ty::BoundVarIndexKind::Canonical, _) => { diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 4bcc7a5eb02e8..2baf423e296d6 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -389,7 +389,7 @@ pub(crate) struct SelfInConstGenericTy { #[derive(Diagnostic)] #[diag( "{$is_gca -> - [true] generic parameters in const blocks are only allowed as the direct value of a `type const` + [true] generic parameters in const blocks are not allowed; use a named `const` item instead *[false] generic parameters may not be used in const operations }" )] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index c9e2312895820..8ecb675243503 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .kind() .map_bound(|kind| match kind { ty::ClauseKind::Projection(projection_predicate) - if projection_predicate.projection_term.def_id() == item_def_id => + if projection_predicate.def_id() == item_def_id => { projection_predicate.term.as_type() } @@ -1473,7 +1473,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")), ValuePairs::Aliases(ExpectedFound { expected, .. }) => { - (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id()))) + let def_id = match expected.kind { + ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(), + ty::AliasTermKind::InherentTy { def_id } => def_id.into(), + ty::AliasTermKind::OpaqueTy { def_id } => def_id.into(), + ty::AliasTermKind::FreeTy { def_id } => def_id.into(), + ty::AliasTermKind::AnonConst { def_id } => def_id.into(), + ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(), + ty::AliasTermKind::FreeConst { def_id } => def_id.into(), + ty::AliasTermKind::InherentConst { def_id } => def_id.into(), + }; + (false, Mismatch::Fixed(self.tcx.def_descr(def_id))) } ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), ValuePairs::ExistentialTraitRef(_) => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 108262d507ef7..318808ffc69d9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -577,10 +577,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return e; } - if let Err(guar) = self - .tcx - .ensure_result() - .coherent_trait(self.tcx.parent(data.projection_term.def_id())) + if let Err(guar) = + self.tcx.ensure_result().coherent_trait(self.tcx.parent(data.def_id())) { // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 32b4d4948f761..051604c94c445 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1817,11 +1817,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_ty: ty::Term<'tcx>, long_ty_path: &mut Option, ) -> Option<(String, Span, Option)> { + let projection_def_id = projection_term.expect_projection_def_id(); let trait_def_id = projection_term.trait_def_id(self.tcx); let self_ty = projection_term.self_ty(); with_forced_trimmed_paths! { - if self.tcx.is_lang_item(projection_term.def_id(), LangItem::FnOnceOutput) { + if self.tcx.is_lang_item(projection_def_id, LangItem::FnOnceOutput) { let (span, closure_span) = if let ty::Closure(def_id, _) = *self_ty.kind() { let def_span = self.tcx.def_span(def_id); if let Some(local_def_id) = def_id.as_local() @@ -3745,14 +3746,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::ConstKind::Unevaluated(uv) => { let mut err = self.dcx().struct_span_err(span, "unconstrained generic constant"); + let const_span = uv.kind.def_span(self.tcx); let const_ty = uv.type_of(self.tcx).skip_norm_wip(); let cast = if const_ty != self.tcx.types.usize { " as usize" } else { "" }; let msg = "try adding a `where` bound"; - if let Some(def_id) = uv.kind.opt_def_id() - && let const_span = self.tcx.def_span(def_id) - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(const_span) - { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(const_span) { let code = format!("[(); {snippet}{cast}]:"); let suggestion_def_id = if let ObligationCauseCode::CompareImplItem { trait_item_def_id, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 6cc3c797391fe..6594fac09af76 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1493,7 +1493,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() && self .tcx - .is_lang_item(proj.projection_term.def_id(), LangItem::FnOnceOutput) + .is_lang_item(proj.def_id(), LangItem::FnOnceOutput) // args tuple will always be args[1] && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() { @@ -1537,7 +1537,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() && self .tcx - .is_lang_item(proj.projection_term.def_id(), LangItem::FnOnceOutput) + .is_lang_item(proj.def_id(), LangItem::FnOnceOutput) && proj.projection_term.self_ty() == found // args tuple will always be args[1] && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() @@ -6425,12 +6425,12 @@ fn point_at_assoc_type_restriction( return; }; let Some(name) = tcx - .opt_rpitit_info(proj.projection_term.def_id()) + .opt_rpitit_info(proj.def_id()) .and_then(|data| match data { ty::ImplTraitInTraitData::Trait { fn_def_id, .. } => Some(tcx.item_name(fn_def_id)), ty::ImplTraitInTraitData::Impl { .. } => None, }) - .or_else(|| tcx.opt_item_name(proj.projection_term.def_id())) + .or_else(|| tcx.opt_item_name(proj.def_id())) else { return; }; diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 49cc2833cd978..e44aacb70c0ee 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -753,7 +753,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref, ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) if matches!( - infcx.tcx.def_kind(proj.projection_term.def_id()), + infcx.tcx.def_kind(proj.def_id()), DefKind::AssocTy | DefKind::AssocConst { .. } ) => { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 678f1ee96abbb..5ddfaf361940c 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -688,8 +688,7 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } - Some((_, ty::AnonConstKind::GCA)) - | Some((_, ty::AnonConstKind::MCG)) + Some((_, ty::AnonConstKind::MCG)) | Some((_, ty::AnonConstKind::NonTypeSystem)) | None => { // We are only dealing with "truly" generic/uninferred constants here: diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 7f44d48641bf5..6dc378718d639 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -304,6 +304,8 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { ); } + let def_id = free.expect_free_def_id(); + // We don't replace bound vars in the generic arguments of the free alias with // placeholders. This doesn't cause any issues as instantiating parameters with // bound variables is special-cased to rewrite the debruijn index to be higher @@ -321,7 +323,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { self.obligations.extend( infcx .tcx - .predicates_of(free.def_id()) + .predicates_of(def_id) .instantiate_own(infcx.tcx, free.args) .map(|(pred, span)| (pred.skip_norm_wip(), span)) .map(|(mut predicate, span)| { @@ -333,8 +335,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { ); } let mut cause = self.cause.clone(); - cause - .map_code(|code| ObligationCauseCode::TypeAlias(code, span, free.def_id())); + cause.map_code(|code| ObligationCauseCode::TypeAlias(code, span, def_id)); Obligation::new(infcx.tcx, cause, self.param_env, predicate) }), ); @@ -342,7 +343,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { let res: ty::Term<'tcx> = if free.kind.is_type() { infcx .tcx - .type_of(free.def_id()) + .type_of(def_id) .instantiate(infcx.tcx, free.args) .skip_norm_wip() .fold_with(self) @@ -350,7 +351,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { } else { infcx .tcx - .const_of_item(free.def_id()) + .const_of_item(def_id) .instantiate(infcx.tcx, free.args) .skip_norm_wip() .fold_with(self) @@ -360,7 +361,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { // obligation to ensure the const value's type matches the declared type. if let Some(ct) = res.as_const() { let expected_ty = - infcx.tcx.type_of(free.def_id()).instantiate(infcx.tcx, free.args).skip_norm_wip(); + infcx.tcx.type_of(def_id).instantiate(infcx.tcx, free.args).skip_norm_wip(); self.obligations.push(Obligation::with_depth( infcx.tcx, self.cause.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 819c0988c0416..cc802a6342807 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -543,7 +543,8 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( ); // Register the obligations arising from the impl and from the associated type itself. - let predicates = tcx.predicates_of(alias_term.def_id()).instantiate(tcx, args); + let def_id = alias_term.expect_inherent_def_id(); + let predicates = tcx.predicates_of(def_id).instantiate(tcx, args); for (predicate, span) in predicates { let predicate = normalize_with_depth_to( selcx, @@ -561,7 +562,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( // cause code, inherent projections will be printed with identity instantiation in // diagnostics which is not ideal. // Consider creating separate cause codes for this specific situation. - ObligationCauseCode::WhereClause(alias_term.def_id(), span), + ObligationCauseCode::WhereClause(def_id, span), ); obligations.push(Obligation::with_depth( @@ -574,9 +575,9 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( } let term: Term<'tcx> = if alias_term.kind.is_type() { - tcx.type_of(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() + tcx.type_of(def_id).instantiate(tcx, args).skip_norm_wip().into() } else { - tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() + tcx.const_of_item(def_id).instantiate(tcx, args).skip_norm_wip().into() }; push_const_arg_has_type_obligation( @@ -586,7 +587,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( depth + 1, param_env, term, - alias_term.def_id(), + def_id, args, ); @@ -610,7 +611,8 @@ pub fn compute_inherent_assoc_term_args<'a, 'b, 'tcx>( ) -> ty::GenericArgsRef<'tcx> { let tcx = selcx.tcx(); - let impl_def_id = tcx.parent(alias_term.def_id()); + let alias_def_id = alias_term.expect_inherent_def_id(); + let impl_def_id = tcx.parent(alias_def_id); let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id); let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(); @@ -788,7 +790,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( let Some(clause) = clause.as_projection_clause() else { return ControlFlow::Continue(()); }; - if clause.item_def_id() != obligation.predicate.def_id() { + if clause.item_def_id() != obligation.predicate.expect_projection_def_id() { return ControlFlow::Continue(()); } @@ -856,7 +858,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( }; let env_predicates = data .projection_bounds() - .filter(|bound| bound.item_def_id() == obligation.predicate.def_id()) + .filter(|bound| bound.item_def_id() == obligation.predicate.expect_projection_def_id()) .map(|p| p.with_self_ty(tcx, object_ty).upcast(tcx)); assemble_candidates_from_predicates( @@ -887,7 +889,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( let bound_predicate = predicate.kind(); if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() { let data = bound_predicate.rebind(data); - if data.item_def_id() != obligation.predicate.def_id() { + if data.item_def_id() != obligation.predicate.expect_projection_def_id() { continue; } @@ -978,7 +980,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( match specialization_graph::assoc_def( selcx.tcx(), impl_data.impl_def_id, - obligation.predicate.def_id(), + obligation.predicate.expect_projection_def_id(), ) { Ok(node_item) => { if node_item.is_final() { @@ -1184,7 +1186,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( } _ if tcx.trait_is_auto(trait_ref.def_id) => { tcx.dcx().span_delayed_bug( - tcx.def_span(obligation.predicate.def_id()), + tcx.def_span(obligation.predicate.expect_projection_def_id()), "associated types not allowed on auto traits", ); false @@ -1366,15 +1368,16 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( coroutine_sig, ); - let ty = if tcx.is_lang_item(obligation.predicate.def_id(), LangItem::CoroutineReturn) { + let def_id = obligation.predicate.expect_projection_def_id(); + let ty = if tcx.is_lang_item(def_id, LangItem::CoroutineReturn) { return_ty - } else if tcx.is_lang_item(obligation.predicate.def_id(), LangItem::CoroutineYield) { + } else if tcx.is_lang_item(def_id, LangItem::CoroutineYield) { yield_ty } else { span_bug!( - tcx.def_span(obligation.predicate.def_id()), + tcx.def_span(def_id), "unexpected associated type: `Coroutine::{}`", - tcx.item_name(obligation.predicate.def_id()), + tcx.item_name(def_id), ); }; @@ -1420,7 +1423,10 @@ fn confirm_future_candidate<'cx, 'tcx>( coroutine_sig, ); - debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id()).name(), sym::Output); + debug_assert_eq!( + tcx.associated_item(obligation.predicate.expect_projection_def_id()).name(), + sym::Output + ); let predicate = ty::ProjectionPredicate { projection_term: obligation.predicate.with_args(tcx, trait_ref.args), @@ -1462,7 +1468,10 @@ fn confirm_iterator_candidate<'cx, 'tcx>( gen_sig, ); - debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id()).name(), sym::Item); + debug_assert_eq!( + tcx.associated_item(obligation.predicate.expect_projection_def_id()).name(), + sym::Item + ); let predicate = ty::ProjectionPredicate { projection_term: obligation.predicate.with_args(tcx, trait_ref.args), @@ -1504,7 +1513,10 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( gen_sig, ); - debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id()).name(), sym::Item); + debug_assert_eq!( + tcx.associated_item(obligation.predicate.expect_projection_def_id()).name(), + sym::Item + ); let ty::Adt(_poll_adt, args) = *yield_ty.kind() else { bug!(); @@ -1531,7 +1543,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); - let item_def_id = obligation.predicate.def_id(); + let item_def_id = obligation.predicate.expect_projection_def_id(); let trait_def_id = tcx.parent(item_def_id); let args = tcx.mk_args(&[self_ty.into()]); let (term, obligations) = if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) { @@ -1756,7 +1768,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( ty::ClosureKind::Fn | ty::ClosureKind::FnMut => obligation.predicate.args.region_at(2), ty::ClosureKind::FnOnce => tcx.lifetimes.re_static, }; - let item_name = tcx.item_name(obligation.predicate.def_id()); + let item_name = tcx.item_name(obligation.predicate.expect_projection_def_id()); let poly_cache_entry = match *self_ty.kind() { ty::CoroutineClosure(def_id, args) => { @@ -2015,7 +2027,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source; - let assoc_item_id = obligation.predicate.def_id(); + let assoc_item_id = obligation.predicate.expect_projection_def_id(); let trait_def_id = tcx.impl_trait_id(impl_def_id); let param_env = obligation.param_env; @@ -2113,9 +2125,8 @@ fn assoc_term_own_obligations<'cx, 'tcx>( nested: &mut PredicateObligations<'tcx>, ) { let tcx = selcx.tcx(); - let predicates = tcx - .predicates_of(obligation.predicate.def_id()) - .instantiate_own(tcx, obligation.predicate.args); + let def_id = obligation.predicate.expect_projection_def_id(); + let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, obligation.predicate.args); for (predicate, span) in predicates { let normalized = normalize_with_depth_to( selcx, @@ -2137,7 +2148,7 @@ fn assoc_term_own_obligations<'cx, 'tcx>( ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObligationCauseCode::WhereClause(obligation.predicate.def_id(), span), + ObligationCauseCode::WhereClause(def_id, span), ) }; nested.push(Obligation::with_depth( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cc138a9dd34c6..6e55b901bfadf 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1770,7 +1770,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { env_predicate: PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidates: bool, ) -> ProjectionMatchesProjection { - debug_assert_eq!(obligation.predicate.def_id(), env_predicate.item_def_id()); + let def_id = obligation.predicate.expect_projection_def_id(); + debug_assert_eq!(def_id, env_predicate.item_def_id()); let mut nested_obligations = PredicateObligations::new(); let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars( @@ -1806,7 +1807,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); if is_match { - let generics = self.tcx().generics_of(obligation.predicate.def_id()); + let generics = self.tcx().generics_of(def_id); // FIXME(generic_associated_types): Addresses aggressive inference in #92917. // If this type is a GAT, and of the GAT args resolve to something new, // that means that we must have newly inferred something about the GAT. diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index c458a1cd15c3e..8eec1d85a0ea0 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -182,7 +182,7 @@ pub fn clause_obligations<'tcx>( wf.add_wf_preds_for_term(ty.into()); } ty::ClauseKind::Projection(t) => { - wf.add_wf_preds_for_alias_term(t.projection_term); + wf.add_wf_preds_for_projection_term(t.projection_term); wf.add_wf_preds_for_term(t.term); } ty::ClauseKind::ConstArgHasType(ct, ty) => { @@ -453,9 +453,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } - /// Pushes the obligations required for an alias (except inherent) to be WF - /// into `self.out`. - fn add_wf_preds_for_alias_term(&mut self, data: ty::AliasTerm<'tcx>) { + /// Pushes the obligations required for a projection to be WF into `self.out`. + fn add_wf_preds_for_projection_term(&mut self, data: ty::AliasTerm<'tcx>) { // A projection is well-formed if // // (a) its predicates hold (*) @@ -477,7 +476,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // `i32: Clone` // `i32: Copy` // ] - let obligations = self.nominal_obligations(data.def_id(), data.args); + let obligations = self.nominal_obligations(data.expect_projection_def_id(), data.args); self.out.extend(obligations); self.add_wf_preds_for_projection_args(data.args); @@ -506,7 +505,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.recursion_depth, &mut self.out, ); - let obligations = self.nominal_obligations(data.def_id(), args); + let def_id = data.expect_inherent_def_id(); + let obligations = self.nominal_obligations(def_id, args); self.out.extend(obligations); } @@ -1005,7 +1005,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { .map_bound(|p| { p.term.as_const().map(|ct| { let assoc_const_ty = tcx - .type_of(p.projection_term.def_id()) + .type_of(p.def_id()) .instantiate(tcx, p.projection_term.args) .skip_norm_wip(); ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType( diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 1505fd20bbdb1..88a72d52eb8e2 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -29,7 +29,7 @@ fn const_arg_has_type_obligation<'tcx>( goal: ty::AliasTerm<'tcx>, ) -> Option> { let ct = normalized_term.as_const()?; - let expected_ty = tcx.type_of(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip(); + let expected_ty = goal.expect_ct().type_of(tcx).skip_norm_wip(); Some(traits::Obligation::new( tcx, ObligationCause::dummy(), @@ -63,7 +63,7 @@ fn normalize_canonicalized_projection<'tcx>( tcx, param_env, normalized_term, - goal.into(), + goal, )); ocx.register_obligations(obligations); // #112047: With projections and opaques, we are able to create opaques that @@ -100,7 +100,8 @@ fn normalize_canonicalized_free_alias<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, |ocx, ParamEnvAnd { param_env, value: goal }| { - let obligations = tcx.predicates_of(goal.def_id()).instantiate_own(tcx, goal.args).map( + let def_id = goal.expect_free_def_id(); + let obligations = tcx.predicates_of(def_id).instantiate_own(tcx, goal.args).map( |(predicate, span)| { traits::Obligation::new( tcx, @@ -112,15 +113,15 @@ fn normalize_canonicalized_free_alias<'tcx>( ); ocx.register_obligations(obligations); let normalized_term: ty::Term<'tcx> = if goal.kind.is_type() { - tcx.type_of(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() + tcx.type_of(def_id).instantiate(tcx, goal.args).skip_norm_wip().into() } else { - tcx.const_of_item(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() + tcx.const_of_item(def_id).instantiate(tcx, goal.args).skip_norm_wip().into() }; ocx.register_obligations(const_arg_has_type_obligation( tcx, param_env, normalized_term, - goal.into(), + goal, )); Ok(NormalizationResult { normalized_term }) }, @@ -151,7 +152,7 @@ fn normalize_canonicalized_inherent_projection<'tcx>( tcx, param_env, normalized_term, - goal.into(), + goal, )); ocx.register_obligations(obligations); diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index ddcdca9e2370d..b3a33b775ad10 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -289,9 +289,6 @@ pub enum AnonConstKind { GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters MCG, - /// `feature(generic_const_args)` anon consts are allowed to use arbitrary - /// generic parameters in scope, but only if they syntactically reference them. - GCA, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters /// but must not depend on the actual instantiation. See #76200 for more information RepeatExprCount, diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index 15fbd985d9630..aa4785439813f 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -47,7 +47,7 @@ pub enum TypeError { /// type). CyclicTy(I::Ty), CyclicConst(I::Const), - ProjectionMismatched(ExpectedFound), + ProjectionMismatched(ExpectedFound>), ExistentialMismatch(ExpectedFound), ConstMismatch(ExpectedFound), diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index a8830b80493e6..a7f7c2fa44358 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -537,7 +537,7 @@ impl ty::Binder> { } #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] -#[derive(Lift_Generic, GenericTypeVisitable)] +#[derive(Lift_Generic, TypeVisitable_Generic, GenericTypeVisitable)] #[cfg_attr( feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext) @@ -612,20 +612,6 @@ impl AliasTermKind { | AliasTermKind::FreeConst { .. } => false, } } - - // FIXME(#156181): replace with explicit matches - pub fn def_id(self) -> I::DefId { - match self { - AliasTermKind::ProjectionTy { def_id } => def_id.into(), - AliasTermKind::InherentTy { def_id } => def_id.into(), - AliasTermKind::OpaqueTy { def_id } => def_id.into(), - AliasTermKind::FreeTy { def_id } => def_id.into(), - AliasTermKind::AnonConst { def_id } => def_id.into(), - AliasTermKind::ProjectionConst { def_id } => def_id.into(), - AliasTermKind::FreeConst { def_id } => def_id.into(), - AliasTermKind::InherentConst { def_id } => def_id.into(), - } - } } impl From> for AliasTermKind { @@ -695,7 +681,19 @@ impl AliasTerm { kind: AliasTermKind, args: I::GenericArgs, ) -> AliasTerm { - interner.debug_assert_args_compatible(kind.def_id(), args); + if cfg!(debug_assertions) { + let def_id = match kind { + AliasTermKind::ProjectionTy { def_id } => def_id.into(), + AliasTermKind::InherentTy { def_id } => def_id.into(), + AliasTermKind::OpaqueTy { def_id } => def_id.into(), + AliasTermKind::FreeTy { def_id } => def_id.into(), + AliasTermKind::AnonConst { def_id } => def_id.into(), + AliasTermKind::ProjectionConst { def_id } => def_id.into(), + AliasTermKind::FreeConst { def_id } => def_id.into(), + AliasTermKind::InherentConst { def_id } => def_id.into(), + }; + interner.debug_assert_args_compatible(def_id, args); + } AliasTerm { kind, args, _use_alias_term_new_instead: () } } @@ -747,11 +745,6 @@ impl AliasTerm { ty::UnevaluatedConst { kind, args: self.args, _use_unevaluated_const_new_instead: () } } - // FIXME: replace with explicit matches - pub fn def_id(self) -> I::DefId { - self.kind.def_id() - } - pub fn to_term(self, interner: I) -> I::Term { let alias_ty = |kind| { Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, kind, self.args)).into() @@ -786,9 +779,24 @@ impl AliasTerm { pub fn with_args(self, interner: I, args: I::GenericArgs) -> Self { Self::new_from_args(interner, self.kind, args) } + + pub fn expect_projection_ty_def_id(self) -> I::TraitAssocTyId { + match self.kind { + AliasTermKind::ProjectionTy { def_id } => def_id, + kind => panic!("expected projection ty, found {kind:?}"), + } + } + + pub fn expect_opaque_ty_def_id(self) -> I::OpaqueTyId { + match self.kind { + AliasTermKind::OpaqueTy { def_id } => def_id, + kind => panic!("expected opaque ty, found {kind:?}"), + } + } } /// The following methods work only with (trait) associated term projections. +// FIXME: Replace by an impl on Alias impl AliasTerm { pub fn self_ty(self) -> I::Ty { self.args.type_at(0) @@ -802,23 +810,14 @@ impl AliasTerm { ) } - fn projection_def_id(self) -> Option { + pub fn expect_projection_def_id(self) -> I::TraitAssocTermId { match self.kind { - AliasTermKind::ProjectionTy { def_id } => Some(def_id.into()), - AliasTermKind::ProjectionConst { def_id } => Some(def_id.into()), - AliasTermKind::InherentTy { .. } - | AliasTermKind::OpaqueTy { .. } - | AliasTermKind::FreeTy { .. } - | AliasTermKind::AnonConst { .. } - | AliasTermKind::FreeConst { .. } - | AliasTermKind::InherentConst { .. } => None, + AliasTermKind::ProjectionTy { def_id } => def_id.into(), + AliasTermKind::ProjectionConst { def_id } => def_id.into(), + kind => panic!("expected projection alias, found {kind:?}"), } } - fn expect_projection_def_id(self) -> I::TraitAssocTermId { - self.projection_def_id().expect("expected a projection") - } - pub fn trait_def_id(self, interner: I) -> I::TraitId { interner.projection_parent(self.expect_projection_def_id()) } @@ -851,7 +850,16 @@ impl AliasTerm { } /// The following methods work only with inherent associated term projections. +// FIXME: Replace by an impl on Alias impl AliasTerm { + pub fn expect_inherent_def_id(self) -> I::InherentAssocTermId { + match self.kind { + AliasTermKind::InherentTy { def_id } => def_id.into(), + AliasTermKind::InherentConst { def_id } => def_id.into(), + kind => panic!("expected inherent alias, found {kind:?}"), + } + } + /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that. /// /// Does the following transformation: @@ -875,6 +883,18 @@ impl AliasTerm { } } +/// The following methods work only with free term aliases. +// FIXME: Replace by an impl on Alias +impl AliasTerm { + pub fn expect_free_def_id(self) -> I::FreeTermAliasId { + match self.kind { + AliasTermKind::FreeTy { def_id } => def_id.into(), + AliasTermKind::FreeConst { def_id } => def_id.into(), + kind => panic!("expected free alias, found {kind:?}"), + } + } +} + impl From> for AliasTerm { fn from(ty: ty::AliasTy) -> Self { AliasTerm { @@ -956,9 +976,9 @@ impl ty::Binder> { /// /// Note that this is not the `DefId` of the `TraitRef` containing this /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. - pub fn item_def_id(&self) -> I::DefId { + pub fn item_def_id(&self) -> I::TraitAssocTermId { // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().projection_term.def_id() + self.skip_binder().def_id() } } @@ -995,10 +1015,6 @@ impl NormalizesTo { pub fn trait_def_id(self, interner: I) -> I::TraitId { self.alias.trait_def_id(interner) } - - pub fn def_id(self) -> I::DefId { - self.alias.def_id() - } } impl fmt::Debug for NormalizesTo { diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 73870378f5ca0..1ce09d7d5b5e8 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -214,10 +214,7 @@ impl Relate for ty::AliasTy { b: ty::AliasTy, ) -> RelateResult> { if a.kind.def_id() != b.kind.def_id() { - Err(TypeError::ProjectionMismatched(ExpectedFound::new( - a.kind.def_id(), - b.kind.def_id(), - ))) + Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.kind.into(), b.kind.into()))) } else { let cx = relation.cx(); let args = if let Some(variances) = cx.opt_alias_variances(a.kind) { @@ -259,13 +256,13 @@ impl Relate for ty::AliasTerm { a: ty::AliasTerm, b: ty::AliasTerm, ) -> RelateResult> { - if a.def_id() != b.def_id() { - Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.def_id(), b.def_id()))) + if a.kind != b.kind { + Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.kind, b.kind))) } else { let args = match a.kind { - ty::AliasTermKind::OpaqueTy { .. } => relate_args_with_variances( + ty::AliasTermKind::OpaqueTy { def_id } => relate_args_with_variances( relation, - relation.cx().variances_of(a.def_id()), + relation.cx().variances_of(def_id.into()), a.args, b.args, )?, @@ -292,8 +289,8 @@ impl Relate for ty::ExistentialProjection { ) -> RelateResult> { if a.def_id != b.def_id { Err(TypeError::ProjectionMismatched(ExpectedFound::new( - a.def_id.into(), - b.def_id.into(), + relation.cx().alias_term_kind_from_def_id(a.def_id.into()), + relation.cx().alias_term_kind_from_def_id(b.def_id.into()), ))) } else { let term = relation.relate_with_variance( diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 2c6b9568bba58..8866c763927b3 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -333,12 +333,12 @@ impl AccessedOpaques { pub fn rerun_if_opaque_in_opaque_type_storage( &mut self, reason: RerunReason, - defid: I::LocalDefId, + defid: I::LocalOpaqueTyId, ) -> Result<(), RerunNonErased> { debug!("set rerun if opaque type {defid:?} in storage"); self.update(AccessedOpaques { reason: Some(reason), - rerun: RerunCondition::OpaqueInStorage(SmallCopyList::new(defid)), + rerun: RerunCondition::OpaqueInStorage(SmallCopyList::new(defid.into())), }) } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 53141aabacc45..744bd41d1139e 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1023,6 +1023,7 @@ pub auto trait Unpin {} // will likely eventually be deprecated, and all new code should be using `UnsafePinned` instead. #[stable(feature = "pin", since = "1.33.0")] #[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[rustc_diagnostic_item = "PhantomPinned"] pub struct PhantomPinned; #[stable(feature = "pin", since = "1.33.0")] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0c164ada82876..4f6cee62f4721 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -567,7 +567,7 @@ fn projection_to_path_segment<'tcx>( proj: ty::Binder<'tcx, ty::AliasTerm<'tcx>>, cx: &mut DocContext<'tcx>, ) -> PathSegment { - let def_id = proj.skip_binder().def_id(); + let def_id = proj.skip_binder().expect_projection_def_id(); let generics = cx.tcx.generics_of(def_id); PathSegment { name: cx.tcx.item_name(def_id), diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 6ec4aaf282238..2b7f9c4dbb7fa 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -36,7 +36,7 @@ use tracing::{debug, info}; use self::rust::HirCollector; use crate::config::{MergeDoctests, Options as RustdocOptions, OutputFormat}; -use crate::html::markdown::{ErrorCodes, Ignore, LangString, MdRelLine}; +use crate::html::markdown::{CodeLineMapping, ErrorCodes, Ignore, LangString, MdRelLine}; use crate::lint::init_lints; /// Type used to display times (compilation and total) information for merged doctests. @@ -940,6 +940,7 @@ pub(crate) struct ScrapedDocTest { text: String, name: String, span: Span, + code_mappings: Vec, global_crate_attrs: Vec, } @@ -951,6 +952,7 @@ impl ScrapedDocTest { langstr: LangString, text: String, span: Span, + code_mappings: Vec, global_crate_attrs: Vec, ) -> Self { let mut item_path = logical_path.join("::"); @@ -963,7 +965,7 @@ impl ScrapedDocTest { filename.display(RemapPathScopeComponents::DOCUMENTATION) ); - Self { filename, line, langstr, text, name, span, global_crate_attrs } + Self { filename, line, langstr, text, name, span, code_mappings, global_crate_attrs } } fn edition(&self, opts: &RustdocOptions) -> Edition { self.langstr.edition.unwrap_or(opts.edition) @@ -984,7 +986,13 @@ impl ScrapedDocTest { } pub(crate) trait DocTestVisitor { - fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine); + fn visit_test( + &mut self, + test: String, + config: LangString, + rel_line: MdRelLine, + code_mappings: Vec, + ); fn visit_header(&mut self, _name: &str, _level: u32) {} } @@ -1055,6 +1063,7 @@ impl CreateRunnableDocTests { .test_id(test_id) .lang_str(&scraped_test.langstr) .span(scraped_test.span) + .code_mappings(&scraped_test.code_mappings) .build(dcx); let is_standalone = !doctest.can_be_merged || self.rustdoc_options.no_capture @@ -1228,7 +1237,13 @@ fn doctest_run_fn( #[cfg(test)] // used in tests impl DocTestVisitor for Vec { - fn visit_test(&mut self, _test: String, _config: LangString, rel_line: MdRelLine) { + fn visit_test( + &mut self, + _test: String, + _config: LangString, + rel_line: MdRelLine, + _code_mappings: Vec, + ) { self.push(1 + rel_line.offset()); } } diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 7dd738abca433..ac82829fa662e 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -16,10 +16,10 @@ use rustc_session::parse::ParseSess; use rustc_span::edition::{DEFAULT_EDITION, Edition}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; -use rustc_span::{DUMMY_SP, FileName, Span, kw}; +use rustc_span::{DUMMY_SP, FileName, InnerSpan, Span, kw}; use tracing::debug; -use super::GlobalTestOptions; +use super::{CodeLineMapping, GlobalTestOptions}; use crate::config::MergeDoctests; use crate::display::Joined as _; use crate::html::markdown::LangString; @@ -47,6 +47,7 @@ pub(crate) struct BuildDocTestBuilder<'a> { test_id: Option, lang_str: Option<&'a LangString>, span: Span, + code_mappings: &'a [CodeLineMapping], global_crate_attrs: Vec, } @@ -60,6 +61,7 @@ impl<'a> BuildDocTestBuilder<'a> { test_id: None, lang_str: None, span: DUMMY_SP, + code_mappings: &[], global_crate_attrs: Vec::new(), } } @@ -94,6 +96,12 @@ impl<'a> BuildDocTestBuilder<'a> { self } + #[inline] + pub(crate) fn code_mappings(mut self, code_mappings: &'a [CodeLineMapping]) -> Self { + self.code_mappings = code_mappings; + self + } + #[inline] pub(crate) fn edition(mut self, edition: Edition) -> Self { self.edition = edition; @@ -116,12 +124,13 @@ impl<'a> BuildDocTestBuilder<'a> { test_id, lang_str, span, + code_mappings, global_crate_attrs, } = self; let result = rustc_driver::catch_fatal_errors(|| { rustc_span::create_session_if_not_set_then(edition, |_| { - parse_source(source, &crate_name, dcx, span) + parse_source(source, &crate_name, dcx, span, code_mappings) }) }); @@ -454,6 +463,7 @@ fn parse_source( crate_name: &Option<&str>, parent_dcx: Option>, span: Span, + code_mappings: &[CodeLineMapping], ) -> Result { use rustc_errors::DiagCtxt; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; @@ -504,6 +514,24 @@ fn parse_source( *prev_span_hi = hi; } + fn span_in_doctest_source(span: Span, code_mappings: &[CodeLineMapping]) -> Option { + let extra_len = DOCTEST_CODE_WRAPPER.len(); + let lo = (span.lo().0 as usize).checked_sub(extra_len)?; + let hi = (span.hi().0 as usize).checked_sub(extra_len)?; + if hi < lo { + return None; + } + code_mappings.iter().find_map(|mapping| { + if mapping.generated.start <= lo && hi <= mapping.generated.end { + let start = lo - mapping.generated.start; + let end = hi - mapping.generated.start; + Some(mapping.original.from_inner(InnerSpan::new(start, end))) + } else { + None + } + }) + } + fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool { let mut is_extern_crate = false; if !info.has_global_allocator @@ -574,6 +602,7 @@ fn parse_source( } } let mut has_non_items = false; + let mut first_non_item_span = None; for stmt in &body.stmts { let mut is_extern_crate = false; match stmt.kind { @@ -611,8 +640,12 @@ fn parse_source( return Err(()); } has_non_items = true; + first_non_item_span.get_or_insert(stmt.span); + } + StmtKind::Let(_) | StmtKind::Semi(_) | StmtKind::Empty => { + has_non_items = true; + first_non_item_span.get_or_insert(stmt.span); } - StmtKind::Let(_) | StmtKind::Semi(_) | StmtKind::Empty => has_non_items = true, } // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to @@ -638,12 +671,15 @@ fn parse_source( } } if has_non_items { + let warning_span = first_non_item_span + .and_then(|span| span_in_doctest_source(span, code_mappings)) + .unwrap_or(span); if info.has_main_fn && let Some(dcx) = parent_dcx - && !span.is_dummy() + && !warning_span.is_dummy() { dcx.span_warn( - span, + warning_span, "the `main` function of this doctest won't be run as it contains \ expressions at the top level, meaning that the whole doctest code will be \ wrapped in a function", diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index f02e0d6df1983..a994f1d974ae3 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -13,7 +13,9 @@ use super::{ CreateRunnableDocTests, DocTestVisitor, GlobalTestOptions, ScrapedDocTest, generate_args_file, }; use crate::config::Options; -use crate::html::markdown::{ErrorCodes, LangString, MdRelLine, find_testable_code}; +use crate::html::markdown::{ + CodeLineMapping, ErrorCodes, LangString, MdRelLine, find_testable_code, +}; struct MdCollector { tests: Vec, @@ -22,7 +24,13 @@ struct MdCollector { } impl DocTestVisitor for MdCollector { - fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine) { + fn visit_test( + &mut self, + test: String, + config: LangString, + rel_line: MdRelLine, + code_mappings: Vec, + ) { let filename = self.filename.clone(); // First line of Markdown is line 1. let line = 1 + rel_line.offset(); @@ -33,6 +41,7 @@ impl DocTestVisitor for MdCollector { config, test, DUMMY_SP, + code_mappings, Vec::new(), )); } diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index b4397b1f01ffa..d89fb2ae1767b 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -17,7 +17,7 @@ use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span}; use super::{DocTestVisitor, ScrapedDocTest}; use crate::clean::{Attributes, CfgInfo, extract_cfg_from_attrs}; -use crate::html::markdown::{self, ErrorCodes, LangString, MdRelLine}; +use crate::html::markdown::{self, CodeLineMapping, ErrorCodes, LangString, MdRelLine}; struct RustCollector { source_map: Arc, @@ -41,7 +41,13 @@ impl RustCollector { } impl DocTestVisitor for RustCollector { - fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine) { + fn visit_test( + &mut self, + test: String, + config: LangString, + rel_line: MdRelLine, + code_mappings: Vec, + ) { let base_line = self.get_base_line(); let line = base_line + rel_line.offset(); let count = Cell::new(base_line); @@ -69,6 +75,7 @@ impl DocTestVisitor for RustCollector { config, test, span, + code_mappings, self.global_crate_attrs.clone(), )); } @@ -199,7 +206,12 @@ impl HirCollector<'_> { &doc, &mut self.collector, self.codes, - Some(&crate::html::markdown::ExtraInfo::new(self.tcx, def_id, span)), + Some(&crate::html::markdown::ExtraInfo::new( + self.tcx, + def_id, + span, + Some(&attrs.doc_strings), + )), ); } diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index ccc3e55a33122..94ac0765becd4 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -479,6 +479,7 @@ fn get_extracted_doctests(code: &str) -> ExtractedDocTests { code.to_string(), DUMMY_SP, Vec::new(), + Vec::new(), ), &opts, Edition::Edition2018, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b05a831d119cb..6240caf4ad196 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -41,10 +41,10 @@ use rustc_errors::{Diag, DiagMessage}; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; pub(crate) use rustc_resolve::rustdoc::main_body_opts; -use rustc_resolve::rustdoc::may_be_doc_link; use rustc_resolve::rustdoc::pulldown_cmark::{ self, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, }; +use rustc_resolve::rustdoc::{DocFragment, may_be_doc_link, source_span_for_markdown_range}; use rustc_span::edition::Edition; use rustc_span::{Span, Symbol}; use tracing::{debug, trace}; @@ -719,11 +719,17 @@ impl MdRelLine { } } +#[derive(Clone, Debug)] +pub(crate) struct CodeLineMapping { + pub(crate) generated: Range, + pub(crate) original: Span, +} + pub(crate) fn find_testable_code( doc: &str, tests: &mut T, error_codes: ErrorCodes, - extra_info: Option<&ExtraInfo<'_>>, + extra_info: Option<&ExtraInfo<'_, '_>>, ) { find_codes(doc, tests, error_codes, extra_info, false) } @@ -732,7 +738,7 @@ pub(crate) fn find_codes( doc: &str, tests: &mut T, error_codes: ErrorCodes, - extra_info: Option<&ExtraInfo<'_>>, + extra_info: Option<&ExtraInfo<'_, '_>>, include_non_rust: bool, ) { let mut parser = Parser::new_ext(doc, main_body_opts()).into_offset_iter(); @@ -757,15 +763,14 @@ pub(crate) fn find_codes( } let mut test_s = String::new(); + let mut text_events = Vec::new(); - while let Some((Event::Text(s), _)) = parser.next() { + while let Some((Event::Text(s), offset)) = parser.next() { + let start = test_s.len(); test_s.push_str(&s); + text_events.push((start..test_s.len(), offset)); } - let text = test_s - .lines() - .map(|l| map_line(l).for_code()) - .collect::>>() - .join("\n"); + let (text, code_mappings) = map_code_block(doc, &test_s, &text_events, extra_info); nb_lines += doc[prev_offset..offset.start].lines().count(); // If there are characters between the preceding line ending and @@ -775,7 +780,7 @@ pub(crate) fn find_codes( nb_lines -= 1; } let line = MdRelLine::new(nb_lines); - tests.visit_test(text, block_info, line); + tests.visit_test(text, block_info, line, code_mappings); prev_offset = offset.start; } Event::Start(Tag::Heading { level, .. }) => { @@ -791,15 +796,75 @@ pub(crate) fn find_codes( } } -pub(crate) struct ExtraInfo<'tcx> { +fn map_code_block( + doc: &str, + code: &str, + text_events: &[(Range, Range)], + extra_info: Option<&ExtraInfo<'_, '_>>, +) -> (String, Vec) { + let mut text = String::new(); + let mut code_mappings = Vec::new(); + let mut code_line_start = 0; + + for (line_index, line) in code.lines().enumerate() { + if line_index != 0 { + text.push('\n'); + } + + let generated_start = text.len(); + let mapped_line = map_line(line).for_code(); + text.push_str(&mapped_line); + let generated = generated_start..text.len(); + + if mapped_line.as_ref() == line + && let Some(extra_info) = extra_info + && let Some(fragments) = extra_info.fragments + { + let code_line = code_line_start..code_line_start + line.len(); + if let Some(md_range) = markdown_range_for_code_range(text_events, code_line) + && let Some((original, _)) = + source_span_for_markdown_range(extra_info.tcx, doc, &md_range, fragments) + { + code_mappings.push(CodeLineMapping { generated, original }); + } + } + + code_line_start += line.len() + 1; + } + + (text, code_mappings) +} + +fn markdown_range_for_code_range( + text_events: &[(Range, Range)], + code_range: Range, +) -> Option> { + text_events.iter().find_map(|(event_code_range, event_md_range)| { + if event_code_range.start <= code_range.start && code_range.end <= event_code_range.end { + let start = event_md_range.start + code_range.start - event_code_range.start; + let end = event_md_range.start + code_range.end - event_code_range.start; + Some(start..end) + } else { + None + } + }) +} + +pub(crate) struct ExtraInfo<'doc, 'tcx> { def_id: LocalDefId, sp: Span, tcx: TyCtxt<'tcx>, + fragments: Option<&'doc [DocFragment]>, } -impl<'tcx> ExtraInfo<'tcx> { - pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId, sp: Span) -> ExtraInfo<'tcx> { - ExtraInfo { def_id, sp, tcx } +impl<'doc, 'tcx> ExtraInfo<'doc, 'tcx> { + pub(crate) fn new( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sp: Span, + fragments: Option<&'doc [DocFragment]>, + ) -> ExtraInfo<'doc, 'tcx> { + ExtraInfo { def_id, sp, tcx, fragments } } fn error_invalid_codeblock_attr(&self, msg: impl Into) { @@ -890,7 +955,7 @@ pub(crate) struct TagIterator<'a, 'tcx> { inner: Peekable>, data: &'a str, is_in_attribute_block: bool, - extra: Option<&'a ExtraInfo<'tcx>>, + extra: Option<&'a ExtraInfo<'a, 'tcx>>, is_error: bool, } @@ -917,7 +982,7 @@ struct Indices { } impl<'a, 'tcx> TagIterator<'a, 'tcx> { - pub(crate) fn new(data: &'a str, extra: Option<&'a ExtraInfo<'tcx>>) -> Self { + pub(crate) fn new(data: &'a str, extra: Option<&'a ExtraInfo<'a, 'tcx>>) -> Self { Self { inner: data.char_indices().peekable(), data, @@ -1172,7 +1237,7 @@ impl LangString { fn parse( string: &str, allow_error_code_check: ErrorCodes, - extra: Option<&ExtraInfo<'_>>, + extra: Option<&ExtraInfo<'_, '_>>, ) -> Self { let allow_error_code_check = allow_error_code_check.as_bool(); let mut seen_rust_tags = false; @@ -1955,7 +2020,7 @@ pub(crate) struct RustCodeBlock { /// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or /// untagged (and assumed to be rust). -pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec { +pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec { let mut code_blocks = vec![]; if md.is_empty() { diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index a8a9a42df4575..13452539c8295 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -15,7 +15,9 @@ use crate::clean; use crate::clean::utils::inherits_doc_hidden; use crate::clean::*; use crate::core::DocContext; -use crate::html::markdown::{ErrorCodes, Ignore, LangString, MdRelLine, find_testable_code}; +use crate::html::markdown::{ + CodeLineMapping, ErrorCodes, Ignore, LangString, MdRelLine, find_testable_code, +}; use crate::visit::DocVisitor; pub(crate) const CHECK_DOC_TEST_VISIBILITY: Pass = Pass { @@ -47,7 +49,7 @@ pub(crate) struct Tests { } impl crate::doctest::DocTestVisitor for Tests { - fn visit_test(&mut self, _: String, config: LangString, _: MdRelLine) { + fn visit_test(&mut self, _: String, config: LangString, _: MdRelLine, _: Vec) { if config.rust && config.ignore == Ignore::None { self.found_tests += 1; } diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 1c017f9a635c1..b25d081f6ae80 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -21,7 +21,7 @@ use crate::html::markdown::{self, RustCodeBlock}; pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item, dox: &str) { if let Some(def_id) = item.item_id.as_local_def_id() { let sp = item.attr_span(cx.tcx); - let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, def_id, sp); + let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, def_id, sp, None); for code_block in markdown::rust_code_blocks(dox, &extra) { check_rust_syntax(cx, item, dox, code_block); } diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs index 332c19e140b3e..634745422204f 100644 --- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs +++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs @@ -185,6 +185,7 @@ fn check_struct<'tcx>( .filter_map(|field| { if field_accesses.contains(&field.ident.name) || field.ty.basic_res().is_lang_item(cx, LangItem::PhantomData) + || field.ty.basic_res().is_diag_item(cx, sym::PhantomPinned) { None } else { diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs index 64724f7d01d00..92d1bf505bfaf 100644 --- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs +++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs @@ -3,6 +3,7 @@ use clippy_config::types::PubUnderscoreFieldsBehaviour; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::res::{MaybeDef, MaybeResPath}; +use clippy_utils::sym::PhantomPinned; use rustc_hir::{FieldDef, Item, ItemKind, LangItem}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -75,8 +76,9 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields { if field.ident.as_str().starts_with('_') && is_visible(field) // We ignore fields that have `#[doc(hidden)]`. && !is_doc_hidden(cx.tcx.hir_attrs(field.hir_id)) - // We ignore fields that are `PhantomData`. + // We ignore fields that are `PhantomData` and `PhantomPinned`. && !field.ty.basic_res().is_lang_item(cx, LangItem::PhantomData) + && !field.ty.basic_res().is_diag_item(cx, PhantomPinned) { span_lint_hir_and_then( cx, diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index f414c0ac47fa4..59e98cdc7bef8 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -100,6 +100,7 @@ generate! { Path, PathBuf, PathLookup, + PhantomPinned, RangeBounds, RefCellRef, RefCellRefMut, diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index a944e91db0c0e..60d19ecf68bb5 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -712,7 +712,7 @@ fn sig_from_bounds<'tcx>( inputs = Some(i); }, ty::ClauseKind::Projection(p) - if Some(p.projection_term.def_id()) == lang_items.fn_once_output() + if Some(p.projection_term.expect_projection_def_id()) == lang_items.fn_once_output() && p.projection_term.self_ty() == ty => { if output.is_some() { @@ -753,7 +753,9 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option } inputs = Some(i); }, - ty::ClauseKind::Projection(p) if Some(p.projection_term.def_id()) == lang_items.fn_once_output() => { + ty::ClauseKind::Projection(p) + if Some(p.projection_term.expect_projection_def_id()) == lang_items.fn_once_output() => + { if output.is_some() { // Multiple different fn trait impls. Is this even allowed? return None; diff --git a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr index 40112fbf4c743..4632c06f095a3 100644 --- a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr +++ b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr @@ -9,7 +9,7 @@ LL | pub _b: u8, = help: to override `-D warnings` add `#[allow(clippy::pub_underscore_fields)]` error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:23:13 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:24:13 | LL | pub(in crate::inner) _f: Option<()>, | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | pub(in crate::inner) _f: Option<()>, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:28:13 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:29:13 | LL | pub _g: String, | ^^^^^^ @@ -25,7 +25,7 @@ LL | pub _g: String, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:36:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:37:9 | LL | pub _a: usize, | ^^^^^^ @@ -33,7 +33,7 @@ LL | pub _a: usize, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:44:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:45:9 | LL | pub _c: i64, | ^^^^^^ @@ -41,7 +41,7 @@ LL | pub _c: i64, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:48:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:49:9 | LL | pub _e: Option, | ^^^^^^ @@ -49,7 +49,7 @@ LL | pub _e: Option, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:62:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:63:9 | LL | pub(crate) _b: Option, | ^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs index 807469e2d8c5a..5a52cf78821b6 100644 --- a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs +++ b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs @@ -4,7 +4,7 @@ #![warn(clippy::pub_underscore_fields)] -use std::marker::PhantomData; +use std::marker::{PhantomData, PhantomPinned}; pub mod inner { use std::marker; @@ -15,6 +15,7 @@ pub mod inner { //~^ pub_underscore_fields _c: i32, pub _mark: marker::PhantomData, + pub _pinned: marker::PhantomPinned, } mod inner2 { @@ -68,6 +69,7 @@ fn main() { r#pub: bool, _pub: String, pub(crate) _mark: PhantomData, + pub(crate) _pinned: PhantomPinned, } // shouldn't warn when `#[allow]` is used on field level diff --git a/src/tools/clippy/tests/ui/missing_fields_in_debug.rs b/src/tools/clippy/tests/ui/missing_fields_in_debug.rs index 14803b5485a11..b206f4d8f8ce3 100644 --- a/src/tools/clippy/tests/ui/missing_fields_in_debug.rs +++ b/src/tools/clippy/tests/ui/missing_fields_in_debug.rs @@ -2,7 +2,7 @@ #![warn(clippy::missing_fields_in_debug)] use std::fmt; -use std::marker::PhantomData; +use std::marker::{PhantomData, PhantomPinned}; use std::ops::Deref; use std::thread::LocalKey; @@ -179,16 +179,18 @@ mod comment1175473620 { } // https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1175488757 -// PhantomData is an exception and does not need to be included -struct WithPD { +// https://github.com/rust-lang/rust/issues/154888 +// PhantomData & PhantomPinned are exceptions and do not need to be included +struct WithPDPP { a: u8, b: u8, c: PhantomData, + d: PhantomPinned, } -impl fmt::Debug for WithPD { +impl fmt::Debug for WithPDPP { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("WithPD") + f.debug_struct("WithPDPP") .field("a", &self.a) .field("b", &self.b) .finish() diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 99e84b4562f61..ef6c6f0f586ae 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.22" +wasm-component-ld = "0.5.25" diff --git a/tests/codegen-llvm/optimize-closure-shim.rs b/tests/codegen-llvm/optimize-closure-shim.rs new file mode 100644 index 0000000000000..b77656417dfe7 --- /dev/null +++ b/tests/codegen-llvm/optimize-closure-shim.rs @@ -0,0 +1,49 @@ +//! Ensure that `#[optimize]` applied to a closure is inherited by its coercion shim. + +//@ compile-flags: -Copt-level=3 + +#![feature(optimize_attribute)] +#![feature(stmt_expr_attributes)] +#![crate_type = "lib"] + +// CHECK-DAG: define{{.*}}void {{.*}}shim{{.*}}none{{.*}}(){{.*}}#[[ATTR_NONE:[0-9]+]] +// CHECK-DAG: define{{.*}}void {{.*}}shim{{.*}}size{{.*}}(){{.*}}#[[ATTR_SIZE:[0-9]+]] +// CHECK-DAG: define{{.*}}void {{.*}}shim{{.*}}test_passed_directly{{.*}}(){{.*}}#[[ATTR_SIZE]] + +// CHECK-DAG: attributes #[[ATTR_NONE]] = { {{.*}}noinline{{.*}}optnone{{.*}} } +// CHECK-DAG: attributes #[[ATTR_SIZE]] = { {{.*}}optsize{{.*}} } + +extern "C" { + fn side_effect_1(); + fn side_effect_2(); + fn side_effect_3(); +} + +#[no_mangle] +pub fn test_none() -> fn() { + let closure = #[optimize(none)] + || unsafe { side_effect_1() }; + closure +} + +#[no_mangle] +pub fn test_size() -> fn() { + let closure = #[optimize(size)] + || unsafe { side_effect_2() }; + closure +} + +#[no_mangle] +#[inline(never)] +pub fn test_passed_directly() { + f( + #[optimize(size)] + || unsafe { side_effect_3() }, + ); +} + +#[no_mangle] +#[inline(never)] +pub fn f(x: fn()) { + x(); +} diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs index 05e4a348d1190..ee2318b3165cb 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs @@ -1,5 +1,7 @@ // FIXME: if/when the output of the test harness can be tested on its own, this test should be // adapted to use that, and that normalize line can go away +// Regression test for #157371. The warning for a trailing semicolon after an item should +// point inside the doctest, not at unrelated source following the documentation. //@ compile-flags:--test //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" @@ -7,13 +9,16 @@ //@ check-pass /// +/// /// /// ```rust -//~^ WARN the `main` function of this doctest won't be run /// struct S {}; +//~^ WARN the `main` function of this doctest won't be run /// /// fn main() { /// assert_eq!(0, 1); /// } /// ``` -mod m {} +mod m { + // This line should not be highlighted by the doctest warning. +} diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr index cffda43ba1c94..1ea193a731e9d 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr @@ -1,8 +1,8 @@ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function - --> $DIR/failed-doctest-extra-semicolon-on-item.rs:11:1 + --> $DIR/failed-doctest-extra-semicolon-on-item.rs:15:16 | -LL | /// ```rust - | ^^^^^^^^^^^ +LL | /// struct S {}; + | ^ warning: 1 warning emitted diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout index 1068b98cb0fbb..bcb13c84cfa33 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout @@ -1,6 +1,6 @@ running 1 test -test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... ok +test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 14) ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/doctest/main-alongside-stmts.rs b/tests/rustdoc-ui/doctest/main-alongside-stmts.rs index 595de13393293..73297d8ab915c 100644 --- a/tests/rustdoc-ui/doctest/main-alongside-stmts.rs +++ b/tests/rustdoc-ui/doctest/main-alongside-stmts.rs @@ -23,7 +23,7 @@ //! assert!(false); //! } //! ``` -//~v WARN the `main` function of this doctest won't be run +//~vvv WARN the `main` function of this doctest won't be run //! //! ``` //! let x = 2; diff --git a/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr b/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr index b7a5421f8f737..6e6055cff317e 100644 --- a/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr +++ b/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr @@ -5,10 +5,10 @@ LL | //! ``` | ^^^^^^^ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function - --> $DIR/main-alongside-stmts.rs:27:1 + --> $DIR/main-alongside-stmts.rs:29:5 | -LL | //! - | ^^^ +LL | //! let x = 2; + | ^^^^^^^^^^ warning: 2 warnings emitted diff --git a/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.rs b/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.rs new file mode 100644 index 0000000000000..15fa684c74b65 --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.rs @@ -0,0 +1,37 @@ +// Regression test for #157371. +// The warning for a top-level expression in a doctest should point at the stray +// semicolon inside the doctest, not at unrelated source below the doc comment. + +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +/// This part creates the doctest with a stray `;`. +/// +/// ``` +/// #[derive(Debug, PartialEq)] +/// struct Type { +/// left: i32, +/// right: i32, +/// }; // <- Stray `;`. +//~^ WARN the `main` function of this doctest won't be run +/// +/// fn main() { +/// let x = Type { +/// left: 10, +/// right: 20, +/// }; +/// assert_eq!( +/// x, +/// Type { +/// left: 10, +/// right: 20, +/// }, +/// ); +/// } +/// ``` +pub fn add(left: u64, right: u64) -> u64 { + // This code is completely unrelated to the doctest. + left + right +} diff --git a/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.stderr b/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.stderr new file mode 100644 index 0000000000000..1aa1bfcc323bd --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.stderr @@ -0,0 +1,8 @@ +warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function + --> $DIR/main-warning-span-outside-doctest-issue-157371.rs:17:6 + | +LL | /// }; // <- Stray `;`. + | ^ + +warning: 1 warning emitted + diff --git a/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.stdout b/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.stdout new file mode 100644 index 0000000000000..c39acc99dbd7f --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-warning-span-outside-doctest-issue-157371.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/main-warning-span-outside-doctest-issue-157371.rs - add (line 12) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/warn-main-not-called.rs b/tests/rustdoc-ui/doctest/warn-main-not-called.rs index ec762486d5d42..78d085275f57f 100644 --- a/tests/rustdoc-ui/doctest/warn-main-not-called.rs +++ b/tests/rustdoc-ui/doctest/warn-main-not-called.rs @@ -8,7 +8,7 @@ // won't be called. //! ``` -//~^ WARN the `main` function of this doctest won't be run +//~vvvvv WARN the `main` function of this doctest won't be run //! macro_rules! bla { //! ($($x:tt)*) => {} //! } @@ -18,7 +18,7 @@ //! ``` //! //! ``` -//~^^ WARN the `main` function of this doctest won't be run +//~v WARN the `main` function of this doctest won't be run //! let x = 12; //! fn main() {} //! ``` diff --git a/tests/rustdoc-ui/doctest/warn-main-not-called.stderr b/tests/rustdoc-ui/doctest/warn-main-not-called.stderr index 5feca6f9175fe..7dc56b0fbf16e 100644 --- a/tests/rustdoc-ui/doctest/warn-main-not-called.stderr +++ b/tests/rustdoc-ui/doctest/warn-main-not-called.stderr @@ -1,14 +1,14 @@ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function - --> $DIR/warn-main-not-called.rs:10:1 + --> $DIR/warn-main-not-called.rs:16:5 | -LL | //! ``` - | ^^^^^^^ +LL | //! let x = 12; + | ^^^^^^^^^^^ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function - --> $DIR/warn-main-not-called.rs:19:1 + --> $DIR/warn-main-not-called.rs:22:5 | -LL | //! - | ^^^ +LL | //! let x = 12; + | ^^^^^^^^^^^ warning: 2 warnings emitted diff --git a/tests/ui/const-generics/gca/basic-different-definitions.rs b/tests/ui/const-generics/gca/basic-different-definitions.rs index ec26f26630a57..bd07cc2d5a26c 100644 --- a/tests/ui/const-generics/gca/basic-different-definitions.rs +++ b/tests/ui/const-generics/gca/basic-different-definitions.rs @@ -6,9 +6,9 @@ #![feature(generic_const_args)] #![expect(incomplete_features)] -type const ADD1: usize = const { N + 1 }; +const ADD1: usize = N + 1; -type const INC: usize = const { N + 1 }; +const INC: usize = N + 1; type const ONE: usize = ADD1::<0>; diff --git a/tests/ui/const-generics/gca/basic.rs b/tests/ui/const-generics/gca/basic.rs index 40c28c3d38c0e..b4ff018dfa483 100644 --- a/tests/ui/const-generics/gca/basic.rs +++ b/tests/ui/const-generics/gca/basic.rs @@ -6,7 +6,7 @@ #![feature(generic_const_args)] #![expect(incomplete_features)] -type const ADD1: usize = const { N + 1 }; +const ADD1: usize = N + 1; type const INC: usize = ADD1::; diff --git a/tests/ui/const-generics/gca/coherence-fail.rs b/tests/ui/const-generics/gca/coherence-fail.rs index 079c8cf63e144..9b92fec952ce9 100644 --- a/tests/ui/const-generics/gca/coherence-fail.rs +++ b/tests/ui/const-generics/gca/coherence-fail.rs @@ -4,14 +4,14 @@ // computing the same value with different constant items but same generic arguments should fail trait Trait1 {} -type const FOO: usize = const { N + 1 }; -type const BAR: usize = const { N + 1 }; +const FOO: usize = N + 1; +const BAR: usize = N + 1; impl Trait1 for [(); FOO::<1>] {} impl Trait1 for [(); BAR::<1>] {} //~^ ERROR conflicting implementations of trait `Trait1` for type `[(); 2]` // computing the same value with the same constant item but different generic arguments should fail -type const DIV2: usize = const { N / 2 }; +const DIV2: usize = N / 2; trait Trait2 {} impl Trait2 for [(); DIV2::<2>] {} impl Trait2 for [(); DIV2::<3>] {} @@ -20,8 +20,8 @@ impl Trait2 for [(); DIV2::<3>] {} // computing the same value with different constant items and different generic arguments should // fail trait Trait3 {} -type const ADD1: usize = const { N + 1 }; -type const SUB1: usize = const { N - 1 }; +const ADD1: usize = N + 1; +const SUB1: usize = N - 1; impl Trait3 for [(); ADD1::<1>] {} impl Trait3 for [(); SUB1::<3>] {} //~^ ERROR conflicting implementations of trait `Trait3` for type `[(); 2]` diff --git a/tests/ui/const-generics/gca/coherence-ok.rs b/tests/ui/const-generics/gca/coherence-ok.rs index 38899badf5f03..1d55c08d3820f 100644 --- a/tests/ui/const-generics/gca/coherence-ok.rs +++ b/tests/ui/const-generics/gca/coherence-ok.rs @@ -5,7 +5,7 @@ // computing different values with the same type const item should be fine -type const ADD1: usize = const { N + 1 }; +const ADD1: usize = N + 1; trait Trait {} diff --git a/tests/ui/const-generics/gca/gca-anon-const-rejected.rs b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs new file mode 100644 index 0000000000000..297beba7eb539 --- /dev/null +++ b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs @@ -0,0 +1,9 @@ +//@ compile-flags: -Znext-solver +// Test that anonymous const blocks using generic parameters are rejected +// under `generic_const_args`. Users should use named const items instead: +// `const FOO: usize = N + 1;` +#![feature(generic_const_args, min_generic_const_args, generic_const_items)] + +type const FOO: usize = const { N + 1 }; //~ ERROR generic parameters in const blocks are not allowed; use a named `const` item instead + +fn main() {} diff --git a/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr b/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr new file mode 100644 index 0000000000000..45ba264b53a39 --- /dev/null +++ b/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr @@ -0,0 +1,10 @@ +error: generic parameters in const blocks are not allowed; use a named `const` item instead + --> $DIR/gca-anon-const-rejected.rs:7:49 + | +LL | type const FOO: usize = const { N + 1 }; + | ^ + | + = help: consider factoring the expression into a `type const` item and use it as the const argument instead + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca/generic-param-rhs.rs b/tests/ui/const-generics/gca/generic-param-rhs.rs index ea6e2d7398b57..19a57347a9056 100644 --- a/tests/ui/const-generics/gca/generic-param-rhs.rs +++ b/tests/ui/const-generics/gca/generic-param-rhs.rs @@ -5,6 +5,6 @@ fn foo() {} fn bar() { foo::(); - //~^ ERROR: generic parameters in const blocks are only allowed as the direct value of a `type const` + //~^ ERROR: generic parameters in const blocks are not allowed; use a named `const` item instead } fn main(){} diff --git a/tests/ui/const-generics/gca/generic-param-rhs.stderr b/tests/ui/const-generics/gca/generic-param-rhs.stderr index ca0ce899b8b0d..e4b5e76dbabf3 100644 --- a/tests/ui/const-generics/gca/generic-param-rhs.stderr +++ b/tests/ui/const-generics/gca/generic-param-rhs.stderr @@ -1,4 +1,4 @@ -error: generic parameters in const blocks are only allowed as the direct value of a `type const` +error: generic parameters in const blocks are not allowed; use a named `const` item instead --> $DIR/generic-param-rhs.rs:7:19 | LL | foo::(); diff --git a/tests/ui/const-generics/gca/rhs-but-not-root.rs b/tests/ui/const-generics/gca/rhs-but-not-root.rs index 61762a2851356..9c068bf02b756 100644 --- a/tests/ui/const-generics/gca/rhs-but-not-root.rs +++ b/tests/ui/const-generics/gca/rhs-but-not-root.rs @@ -6,7 +6,7 @@ // Anon consts must be the root of the RHS to be GCA. type const FOO: usize = ID::; -//~^ ERROR generic parameters in const blocks are only allowed as the direct value of a `type const` +//~^ ERROR generic parameters in const blocks are not allowed; use a named `const` item instead type const ID: usize = N; fn main() {} diff --git a/tests/ui/const-generics/gca/rhs-but-not-root.stderr b/tests/ui/const-generics/gca/rhs-but-not-root.stderr index 06f5ae248ac14..7d6f9ae479547 100644 --- a/tests/ui/const-generics/gca/rhs-but-not-root.stderr +++ b/tests/ui/const-generics/gca/rhs-but-not-root.stderr @@ -1,4 +1,4 @@ -error: generic parameters in const blocks are only allowed as the direct value of a `type const` +error: generic parameters in const blocks are not allowed; use a named `const` item instead --> $DIR/rhs-but-not-root.rs:8:54 | LL | type const FOO: usize = ID::;