From 0126f7f3a924da2da84d9645cf02d90e9aae214d Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Tue, 6 Sep 2022 14:23:03 -0400 Subject: [PATCH 01/27] Allow lint passes to be bound by `TyCtxt` --- compiler/rustc_lint/src/context.rs | 28 +- compiler/rustc_lint/src/late.rs | 15 +- compiler/rustc_lint/src/lib.rs | 43 +- compiler/rustc_lint/src/passes.rs | 2 +- .../auxiliary/issue-40001-plugin.rs | 2 +- .../auxiliary/lint-for-crate-rpass.rs | 6 +- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 2 +- .../auxiliary/lint-group-plugin-test.rs | 2 +- src/tools/clippy/clippy_dev/src/new_lint.rs | 6 +- src/tools/clippy/clippy_lints/src/lib.rs | 414 +++++++++--------- 10 files changed, 274 insertions(+), 246 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 9a163cf207e97..7ca6ec5d96234 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -50,6 +50,10 @@ use std::cell::Cell; use std::iter; use std::slice; +type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync; +type LateLintPassFactory = + dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::Send + sync::Sync; + /// Information about the registered lints. /// /// This is basically the subset of `Context` that we can @@ -64,11 +68,11 @@ pub struct LintStore { /// interior mutability, we don't enforce this (and lints should, in theory, /// be compatible with being constructed more than once, though not /// necessarily in a sane manner. This is safe though.) - pub pre_expansion_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, - pub early_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, - pub late_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, + pub pre_expansion_passes: Vec>, + pub early_passes: Vec>, + pub late_passes: Vec>, /// This is unique in that we construct them per-module, so not once. - pub late_module_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, + pub late_module_passes: Vec>, /// Lints indexed by name. by_name: FxHashMap, @@ -186,14 +190,20 @@ impl LintStore { pub fn register_late_pass( &mut self, - pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, + pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + + 'static + + sync::Send + + sync::Sync, ) { self.late_passes.push(Box::new(pass)); } pub fn register_late_mod_pass( &mut self, - pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, + pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + + 'static + + sync::Send + + sync::Sync, ) { self.late_module_passes.push(Box::new(pass)); } @@ -558,7 +568,7 @@ pub trait LintPassObject: Sized {} impl LintPassObject for EarlyLintPassObject {} -impl LintPassObject for LateLintPassObject {} +impl LintPassObject for LateLintPassObject<'_> {} pub trait LintContext: Sized { type PassObject: LintPassObject; @@ -949,8 +959,8 @@ impl<'a> EarlyContext<'a> { } } -impl LintContext for LateContext<'_> { - type PassObject = LateLintPassObject; +impl<'tcx> LintContext for LateContext<'tcx> { + type PassObject = LateLintPassObject<'tcx>; /// Gets the overall compiler `Session` object. fn sess(&self) -> &Session { diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 8a336844dc2fa..66dc3ed59a384 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -306,12 +306,12 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas } } -struct LateLintPassObjects<'a> { - lints: &'a mut [LateLintPassObject], +struct LateLintPassObjects<'a, 'tcx> { + lints: &'a mut [LateLintPassObject<'tcx>], } #[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for LateLintPassObjects<'_> { +impl LintPass for LateLintPassObjects<'_, '_> { fn name(&self) -> &'static str { panic!() } @@ -329,7 +329,7 @@ macro_rules! expand_late_lint_pass_impl_methods { macro_rules! late_lint_pass_impl { ([], [$hir:tt], $methods:tt) => { - impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_> { + impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> { expand_late_lint_pass_impl_methods!([$hir], $methods); } }; @@ -382,7 +382,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( late_lint_mod_pass(tcx, module_def_id, builtin_lints); let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect(); + unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); if !passes.is_empty() { late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); @@ -418,7 +418,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) } fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { - let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::>(); + let mut passes = + unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::>(); if !tcx.sess.opts.unstable_opts.no_interleave_lints { if !passes.is_empty() { @@ -434,7 +435,7 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints } let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect(); + unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); for pass in &mut passes { tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run( diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 370a75cf70069..e0e6f1a8c080c 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -260,26 +260,41 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { ) } - macro_rules! register_pass { + macro_rules! register_early_pass { ($method:ident, $ty:ident, $constructor:expr) => { store.register_lints(&$ty::get_lints()); store.$method(|| Box::new($constructor)); }; } - macro_rules! register_passes { + macro_rules! register_late_pass { + ($method:ident, $ty:ident, $constructor:expr) => { + store.register_lints(&$ty::get_lints()); + store.$method(|_| Box::new($constructor)); + }; + } + + macro_rules! register_early_passes { + ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( + $( + register_early_pass!($method, $passes, $constructor); + )* + ) + } + + macro_rules! register_late_passes { ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( $( - register_pass!($method, $passes, $constructor); + register_late_pass!($method, $passes, $constructor); )* ) } if no_interleave_lints { - pre_expansion_lint_passes!(register_passes, register_pre_expansion_pass); - early_lint_passes!(register_passes, register_early_pass); - late_lint_passes!(register_passes, register_late_pass); - late_lint_mod_passes!(register_passes, register_late_mod_pass); + pre_expansion_lint_passes!(register_early_passes, register_pre_expansion_pass); + early_lint_passes!(register_early_passes, register_early_pass); + late_lint_passes!(register_late_passes, register_late_pass); + late_lint_mod_passes!(register_late_passes, register_late_mod_pass); } else { store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); @@ -510,19 +525,19 @@ fn register_internals(store: &mut LintStore) { store.register_lints(&LintPassImpl::get_lints()); store.register_early_pass(|| Box::new(LintPassImpl)); store.register_lints(&DefaultHashTypes::get_lints()); - store.register_late_pass(|| Box::new(DefaultHashTypes)); + store.register_late_pass(|_| Box::new(DefaultHashTypes)); store.register_lints(&QueryStability::get_lints()); - store.register_late_pass(|| Box::new(QueryStability)); + store.register_late_pass(|_| Box::new(QueryStability)); store.register_lints(&ExistingDocKeyword::get_lints()); - store.register_late_pass(|| Box::new(ExistingDocKeyword)); + store.register_late_pass(|_| Box::new(ExistingDocKeyword)); store.register_lints(&TyTyKind::get_lints()); - store.register_late_pass(|| Box::new(TyTyKind)); + store.register_late_pass(|_| Box::new(TyTyKind)); store.register_lints(&Diagnostics::get_lints()); - store.register_late_pass(|| Box::new(Diagnostics)); + store.register_late_pass(|_| Box::new(Diagnostics)); store.register_lints(&BadOptAccess::get_lints()); - store.register_late_pass(|| Box::new(BadOptAccess)); + store.register_late_pass(|_| Box::new(BadOptAccess)); store.register_lints(&PassByValue::get_lints()); - store.register_late_pass(|| Box::new(PassByValue)); + store.register_late_pass(|_| Box::new(PassByValue)); // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and // these lints will trigger all of the time - change this once migration to diagnostic structs diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 90c554c2e040b..666e61b85acfc 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -244,4 +244,4 @@ macro_rules! declare_combined_early_lint_pass { /// A lint pass boxed up as a trait object. pub type EarlyLintPassObject = Box; -pub type LateLintPassObject = Box LateLintPass<'tcx> + sync::Send + 'static>; +pub type LateLintPassObject<'tcx> = Box + sync::Send + 'tcx>; diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 802b867a301aa..03ad3ca826146 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -21,7 +21,7 @@ use rustc_span::source_map; #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]); - reg.lint_store.register_late_pass(|| Box::new(MissingAllowedAttrPass)); + reg.lint_store.register_late_pass(|_| Box::new(MissingAllowedAttrPass)); } declare_lint! { diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index bc153faa8925a..a3b570ad8c40c 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -74,7 +74,7 @@ fn __rustc_plugin_registrar(reg: &mut Registry) { &CRATE_NOT_GREY, &CRATE_NOT_GREEN, ]); - reg.lint_store.register_late_pass(|| Box::new(PassOkay)); - reg.lint_store.register_late_pass(|| Box::new(PassRedBlue)); - reg.lint_store.register_late_pass(|| Box::new(PassGreyGreen)); + reg.lint_store.register_late_pass(|_| Box::new(PassOkay)); + reg.lint_store.register_late_pass(|_| Box::new(PassRedBlue)); + reg.lint_store.register_late_pass(|_| Box::new(PassGreyGreen)); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 29d0abfbe5388..0b1534939b778 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -39,5 +39,5 @@ impl<'tcx> LateLintPass<'tcx> for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]); - reg.lint_store.register_late_pass(|| Box::new(Pass)); + reg.lint_store.register_late_pass(|_| Box::new(Pass)); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs index 691cfb97d9218..2d41b5f30e975 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]); - reg.lint_store.register_late_pass(|| Box::new(Pass)); + reg.lint_store.register_late_pass(|_| Box::new(Pass)); reg.lint_store.register_group( true, "lint_me", diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index be05e67d724df..331b76484b8a5 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -120,15 +120,17 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let new_lint = if enable_msrv { format!( - "store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n ", + "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv)));\n ", lint_pass = lint.pass, + ctor_arg = if lint.pass == "late" { "_" } else { "" }, module_name = lint.name, camel_name = to_camel_case(lint.name), ) } else { format!( - "store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n ", + "store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n ", lint_pass = lint.pass, + ctor_arg = if lint.pass == "late" { "_" } else { "" }, module_name = lint.name, camel_name = to_camel_case(lint.name), ) diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index dfdaf90f09f48..c70aa79ac8dcf 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -523,7 +523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: #[cfg(feature = "internal")] { if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { - store.register_late_pass(|| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new())); + store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new())); return; } } @@ -533,69 +533,69 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: { store.register_early_pass(|| Box::new(utils::internal_lints::ClippyLintsInternal)); store.register_early_pass(|| Box::new(utils::internal_lints::ProduceIce)); - store.register_late_pass(|| Box::new(utils::internal_lints::CollapsibleCalls)); - store.register_late_pass(|| Box::new(utils::internal_lints::CompilerLintFunctions::new())); - store.register_late_pass(|| Box::new(utils::internal_lints::IfChainStyle)); - store.register_late_pass(|| Box::new(utils::internal_lints::InvalidPaths)); - store.register_late_pass(|| Box::new(utils::internal_lints::InterningDefinedSymbol::default())); - store.register_late_pass(|| Box::new(utils::internal_lints::LintWithoutLintPass::default())); - store.register_late_pass(|| Box::new(utils::internal_lints::MatchTypeOnDiagItem)); - store.register_late_pass(|| Box::new(utils::internal_lints::OuterExpnDataPass)); - store.register_late_pass(|| Box::new(utils::internal_lints::MsrvAttrImpl)); + store.register_late_pass(|_| Box::new(utils::internal_lints::CollapsibleCalls)); + store.register_late_pass(|_| Box::new(utils::internal_lints::CompilerLintFunctions::new())); + store.register_late_pass(|_| Box::new(utils::internal_lints::IfChainStyle)); + store.register_late_pass(|_| Box::new(utils::internal_lints::InvalidPaths)); + store.register_late_pass(|_| Box::new(utils::internal_lints::InterningDefinedSymbol::default())); + store.register_late_pass(|_| Box::new(utils::internal_lints::LintWithoutLintPass::default())); + store.register_late_pass(|_| Box::new(utils::internal_lints::MatchTypeOnDiagItem)); + store.register_late_pass(|_| Box::new(utils::internal_lints::OuterExpnDataPass)); + store.register_late_pass(|_| Box::new(utils::internal_lints::MsrvAttrImpl)); } let arithmetic_allowed = conf.arithmetic_allowed.clone(); - store.register_late_pass(move || Box::new(operators::arithmetic::Arithmetic::new(arithmetic_allowed.clone()))); - store.register_late_pass(|| Box::new(utils::dump_hir::DumpHir)); - store.register_late_pass(|| Box::new(utils::author::Author)); + store.register_late_pass(move |_| Box::new(operators::arithmetic::Arithmetic::new(arithmetic_allowed.clone()))); + store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir)); + store.register_late_pass(|_| Box::new(utils::author::Author)); let await_holding_invalid_types = conf.await_holding_invalid_types.clone(); - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(await_holding_invalid::AwaitHolding::new( await_holding_invalid_types.clone(), )) }); - store.register_late_pass(|| Box::new(serde_api::SerdeApi)); + store.register_late_pass(|_| Box::new(serde_api::SerdeApi)); let vec_box_size_threshold = conf.vec_box_size_threshold; let type_complexity_threshold = conf.type_complexity_threshold; let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(types::Types::new( vec_box_size_threshold, type_complexity_threshold, avoid_breaking_exported_api, )) }); - store.register_late_pass(|| Box::new(booleans::NonminimalBool)); - store.register_late_pass(|| Box::new(enum_clike::UnportableVariant)); - store.register_late_pass(|| Box::new(float_literal::FloatLiteral)); - store.register_late_pass(|| Box::new(ptr::Ptr)); - store.register_late_pass(|| Box::new(needless_bool::NeedlessBool)); - store.register_late_pass(|| Box::new(needless_bool::BoolComparison)); - store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach)); - store.register_late_pass(|| Box::new(misc::MiscLints)); - store.register_late_pass(|| Box::new(eta_reduction::EtaReduction)); - store.register_late_pass(|| Box::new(mut_mut::MutMut)); - store.register_late_pass(|| Box::new(mut_reference::UnnecessaryMutPassed)); - store.register_late_pass(|| Box::new(len_zero::LenZero)); - store.register_late_pass(|| Box::new(attrs::Attributes)); - store.register_late_pass(|| Box::new(blocks_in_if_conditions::BlocksInIfConditions)); - store.register_late_pass(|| Box::new(unicode::Unicode)); - store.register_late_pass(|| Box::new(uninit_vec::UninitVec)); - store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd)); - store.register_late_pass(|| Box::new(strings::StringAdd)); - store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn)); - store.register_late_pass(|| Box::new(implicit_saturating_sub::ImplicitSaturatingSub)); - store.register_late_pass(|| Box::new(default_numeric_fallback::DefaultNumericFallback)); - store.register_late_pass(|| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor)); - store.register_late_pass(|| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); + store.register_late_pass(|_| Box::new(booleans::NonminimalBool)); + store.register_late_pass(|_| Box::new(enum_clike::UnportableVariant)); + store.register_late_pass(|_| Box::new(float_literal::FloatLiteral)); + store.register_late_pass(|_| Box::new(ptr::Ptr)); + store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool)); + store.register_late_pass(|_| Box::new(needless_bool::BoolComparison)); + store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach)); + store.register_late_pass(|_| Box::new(misc::MiscLints)); + store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction)); + store.register_late_pass(|_| Box::new(mut_mut::MutMut)); + store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed)); + store.register_late_pass(|_| Box::new(len_zero::LenZero)); + store.register_late_pass(|_| Box::new(attrs::Attributes)); + store.register_late_pass(|_| Box::new(blocks_in_if_conditions::BlocksInIfConditions)); + store.register_late_pass(|_| Box::new(unicode::Unicode)); + store.register_late_pass(|_| Box::new(uninit_vec::UninitVec)); + store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd)); + store.register_late_pass(|_| Box::new(strings::StringAdd)); + store.register_late_pass(|_| Box::new(implicit_return::ImplicitReturn)); + store.register_late_pass(|_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub)); + store.register_late_pass(|_| Box::new(default_numeric_fallback::DefaultNumericFallback)); + store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor)); + store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports)); let msrv = read_msrv(conf, sess); let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; let allow_expect_in_tests = conf.allow_expect_in_tests; let allow_unwrap_in_tests = conf.allow_unwrap_in_tests; - store.register_late_pass(move || Box::new(approx_const::ApproxConstant::new(msrv))); - store.register_late_pass(move || { + store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv))); + store.register_late_pass(move |_| { Box::new(methods::Methods::new( avoid_breaking_exported_api, msrv, @@ -603,74 +603,74 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: allow_unwrap_in_tests, )) }); - store.register_late_pass(move || Box::new(matches::Matches::new(msrv))); + store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv))); store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv))); - store.register_late_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv))); - store.register_late_pass(move || Box::new(manual_strip::ManualStrip::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv))); store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv))); store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv))); - store.register_late_pass(move || Box::new(checked_conversions::CheckedConversions::new(msrv))); - store.register_late_pass(move || Box::new(mem_replace::MemReplace::new(msrv))); - store.register_late_pass(move || Box::new(ranges::Ranges::new(msrv))); - store.register_late_pass(move || Box::new(from_over_into::FromOverInto::new(msrv))); - store.register_late_pass(move || Box::new(use_self::UseSelf::new(msrv))); - store.register_late_pass(move || Box::new(missing_const_for_fn::MissingConstForFn::new(msrv))); - store.register_late_pass(move || Box::new(needless_question_mark::NeedlessQuestionMark)); - store.register_late_pass(move || Box::new(casts::Casts::new(msrv))); + store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv))); + store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv))); + store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv))); + store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv))); + store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv))); + store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv))); + store.register_late_pass(move |_| Box::new(needless_question_mark::NeedlessQuestionMark)); + store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv))); store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv))); - store.register_late_pass(|| Box::new(size_of_in_element_count::SizeOfInElementCount)); - store.register_late_pass(|| Box::new(same_name_method::SameNameMethod)); + store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount)); + store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod)); let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(index_refutable_slice::IndexRefutableSlice::new( max_suggested_slice_pattern_length, msrv, )) }); - store.register_late_pass(|| Box::new(shadow::Shadow::default())); - store.register_late_pass(|| Box::new(unit_types::UnitTypes)); - store.register_late_pass(|| Box::new(loops::Loops)); - store.register_late_pass(|| Box::new(main_recursion::MainRecursion::default())); - store.register_late_pass(|| Box::new(lifetimes::Lifetimes)); - store.register_late_pass(|| Box::new(entry::HashMapPass)); - store.register_late_pass(|| Box::new(minmax::MinMaxPass)); - store.register_late_pass(|| Box::new(zero_div_zero::ZeroDiv)); - store.register_late_pass(|| Box::new(mutex_atomic::Mutex)); - store.register_late_pass(|| Box::new(needless_update::NeedlessUpdate)); - store.register_late_pass(|| Box::new(needless_borrowed_ref::NeedlessBorrowedRef)); - store.register_late_pass(|| Box::new(borrow_deref_ref::BorrowDerefRef)); - store.register_late_pass(|| Box::new(no_effect::NoEffect)); - store.register_late_pass(|| Box::new(temporary_assignment::TemporaryAssignment)); - store.register_late_pass(move || Box::new(transmute::Transmute::new(msrv))); + store.register_late_pass(|_| Box::new(shadow::Shadow::default())); + store.register_late_pass(|_| Box::new(unit_types::UnitTypes)); + store.register_late_pass(|_| Box::new(loops::Loops)); + store.register_late_pass(|_| Box::new(main_recursion::MainRecursion::default())); + store.register_late_pass(|_| Box::new(lifetimes::Lifetimes)); + store.register_late_pass(|_| Box::new(entry::HashMapPass)); + store.register_late_pass(|_| Box::new(minmax::MinMaxPass)); + store.register_late_pass(|_| Box::new(zero_div_zero::ZeroDiv)); + store.register_late_pass(|_| Box::new(mutex_atomic::Mutex)); + store.register_late_pass(|_| Box::new(needless_update::NeedlessUpdate)); + store.register_late_pass(|_| Box::new(needless_borrowed_ref::NeedlessBorrowedRef)); + store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef)); + store.register_late_pass(|_| Box::new(no_effect::NoEffect)); + store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment)); + store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv))); let cognitive_complexity_threshold = conf.cognitive_complexity_threshold; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(cognitive_complexity::CognitiveComplexity::new( cognitive_complexity_threshold, )) }); let too_large_for_stack = conf.too_large_for_stack; - store.register_late_pass(move || Box::new(escape::BoxedLocal { too_large_for_stack })); - store.register_late_pass(move || Box::new(vec::UselessVec { too_large_for_stack })); - store.register_late_pass(|| Box::new(panic_unimplemented::PanicUnimplemented)); - store.register_late_pass(|| Box::new(strings::StringLitAsBytes)); - store.register_late_pass(|| Box::new(derive::Derive)); - store.register_late_pass(|| Box::new(derivable_impls::DerivableImpls)); - store.register_late_pass(|| Box::new(drop_forget_ref::DropForgetRef)); - store.register_late_pass(|| Box::new(empty_enum::EmptyEnum)); - store.register_late_pass(|| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); - store.register_late_pass(|| Box::new(regex::Regex)); - store.register_late_pass(|| Box::new(copies::CopyAndPaste)); - store.register_late_pass(|| Box::new(copy_iterator::CopyIterator)); - store.register_late_pass(|| Box::new(format::UselessFormat)); - store.register_late_pass(|| Box::new(swap::Swap)); - store.register_late_pass(|| Box::new(overflow_check_conditional::OverflowCheckConditional)); - store.register_late_pass(|| Box::new(new_without_default::NewWithoutDefault::default())); + store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack })); + store.register_late_pass(move |_| Box::new(vec::UselessVec { too_large_for_stack })); + store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented)); + store.register_late_pass(|_| Box::new(strings::StringLitAsBytes)); + store.register_late_pass(|_| Box::new(derive::Derive)); + store.register_late_pass(|_| Box::new(derivable_impls::DerivableImpls)); + store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef)); + store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum)); + store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); + store.register_late_pass(|_| Box::new(regex::Regex)); + store.register_late_pass(|_| Box::new(copies::CopyAndPaste)); + store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator)); + store.register_late_pass(|_| Box::new(format::UselessFormat)); + store.register_late_pass(|_| Box::new(swap::Swap)); + store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional)); + store.register_late_pass(|_| Box::new(new_without_default::NewWithoutDefault::default())); let disallowed_names = conf.disallowed_names.iter().cloned().collect::>(); - store.register_late_pass(move || Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone()))); + store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone()))); let too_many_arguments_threshold = conf.too_many_arguments_threshold; let too_many_lines_threshold = conf.too_many_lines_threshold; let large_error_threshold = conf.large_error_threshold; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(functions::Functions::new( too_many_arguments_threshold, too_many_lines_threshold, @@ -678,73 +678,73 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::>(); - store.register_late_pass(move || Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); - store.register_late_pass(|| Box::new(neg_multiply::NegMultiply)); - store.register_late_pass(|| Box::new(mem_forget::MemForget)); - store.register_late_pass(|| Box::new(let_if_seq::LetIfSeq)); - store.register_late_pass(|| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); - store.register_late_pass(|| Box::new(missing_doc::MissingDoc::new())); - store.register_late_pass(|| Box::new(missing_inline::MissingInline)); - store.register_late_pass(move || Box::new(exhaustive_items::ExhaustiveItems)); - store.register_late_pass(|| Box::new(match_result_ok::MatchResultOk)); - store.register_late_pass(|| Box::new(partialeq_ne_impl::PartialEqNeImpl)); - store.register_late_pass(|| Box::new(unused_io_amount::UnusedIoAmount)); + store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); + store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply)); + store.register_late_pass(|_| Box::new(mem_forget::MemForget)); + store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq)); + store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); + store.register_late_pass(|_| Box::new(missing_doc::MissingDoc::new())); + store.register_late_pass(|_| Box::new(missing_inline::MissingInline)); + store.register_late_pass(move |_| Box::new(exhaustive_items::ExhaustiveItems)); + store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk)); + store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl)); + store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount)); let enum_variant_size_threshold = conf.enum_variant_size_threshold; - store.register_late_pass(move || Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold))); - store.register_late_pass(|| Box::new(explicit_write::ExplicitWrite)); - store.register_late_pass(|| Box::new(needless_pass_by_value::NeedlessPassByValue)); + store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold))); + store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite)); + store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue)); let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new( conf.trivial_copy_size_limit, conf.pass_by_value_size_limit, conf.avoid_breaking_exported_api, &sess.target, ); - store.register_late_pass(move || Box::new(pass_by_ref_or_value)); - store.register_late_pass(|| Box::new(ref_option_ref::RefOptionRef)); - store.register_late_pass(|| Box::new(infinite_iter::InfiniteIter)); - store.register_late_pass(|| Box::new(inline_fn_without_body::InlineFnWithoutBody)); - store.register_late_pass(|| Box::new(useless_conversion::UselessConversion::default())); - store.register_late_pass(|| Box::new(implicit_hasher::ImplicitHasher)); - store.register_late_pass(|| Box::new(fallible_impl_from::FallibleImplFrom)); - store.register_late_pass(|| Box::new(question_mark::QuestionMark)); + store.register_late_pass(move |_| Box::new(pass_by_ref_or_value)); + store.register_late_pass(|_| Box::new(ref_option_ref::RefOptionRef)); + store.register_late_pass(|_| Box::new(infinite_iter::InfiniteIter)); + store.register_late_pass(|_| Box::new(inline_fn_without_body::InlineFnWithoutBody)); + store.register_late_pass(|_| Box::new(useless_conversion::UselessConversion::default())); + store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher)); + store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom)); + store.register_late_pass(|_| Box::new(question_mark::QuestionMark)); store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings)); - store.register_late_pass(|| Box::new(suspicious_trait_impl::SuspiciousImpl)); - store.register_late_pass(|| Box::new(map_unit_fn::MapUnit)); - store.register_late_pass(|| Box::new(inherent_impl::MultipleInherentImpl)); - store.register_late_pass(|| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd)); - store.register_late_pass(|| Box::new(unwrap::Unwrap)); - store.register_late_pass(|| Box::new(indexing_slicing::IndexingSlicing)); - store.register_late_pass(|| Box::new(non_copy_const::NonCopyConst)); - store.register_late_pass(|| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); - store.register_late_pass(|| Box::new(redundant_clone::RedundantClone)); - store.register_late_pass(|| Box::new(slow_vector_initialization::SlowVectorInit)); - store.register_late_pass(move || Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api))); - store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants)); - store.register_late_pass(|| Box::new(assertions_on_result_states::AssertionsOnResultStates)); - store.register_late_pass(|| Box::new(inherent_to_string::InherentToString)); + store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl)); + store.register_late_pass(|_| Box::new(map_unit_fn::MapUnit)); + store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl)); + store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd)); + store.register_late_pass(|_| Box::new(unwrap::Unwrap)); + store.register_late_pass(|_| Box::new(indexing_slicing::IndexingSlicing)); + store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst)); + store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); + store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone)); + store.register_late_pass(|_| Box::new(slow_vector_initialization::SlowVectorInit)); + store.register_late_pass(move |_| Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api))); + store.register_late_pass(|_| Box::new(assertions_on_constants::AssertionsOnConstants)); + store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates)); + store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString)); let max_trait_bounds = conf.max_trait_bounds; - store.register_late_pass(move || Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); - store.register_late_pass(|| Box::new(comparison_chain::ComparisonChain)); - store.register_late_pass(|| Box::new(mut_key::MutableKeyType)); + store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); + store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain)); + store.register_late_pass(|_| Box::new(mut_key::MutableKeyType)); store.register_early_pass(|| Box::new(reference::DerefAddrOf)); store.register_early_pass(|| Box::new(double_parens::DoubleParens)); - store.register_late_pass(|| Box::new(format_impl::FormatImpl::new())); + store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new())); store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval)); store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse)); store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne)); store.register_early_pass(|| Box::new(formatting::Formatting)); store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints)); store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall)); - store.register_late_pass(|| Box::new(redundant_closure_call::RedundantClosureCall)); + store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); - store.register_late_pass(|| Box::new(returns::Return)); + store.register_late_pass(|_| Box::new(returns::Return)); store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf)); store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements)); store.register_early_pass(|| Box::new(precedence::Precedence)); - store.register_late_pass(|| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); + store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue)); store.register_early_pass(|| Box::new(redundant_else::RedundantElse)); - store.register_late_pass(|| Box::new(create_dir::CreateDir)); + store.register_late_pass(|_| Box::new(create_dir::CreateDir)); store.register_early_pass(|| Box::new(needless_arbitrary_self_type::NeedlessArbitrarySelfType)); let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions; store.register_early_pass(move || { @@ -759,7 +759,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); let enum_variant_name_threshold = conf.enum_variant_name_threshold; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(enum_variants::EnumVariantNames::new( enum_variant_name_threshold, avoid_breaking_exported_api, @@ -767,23 +767,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments)); let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(upper_case_acronyms::UpperCaseAcronyms::new( avoid_breaking_exported_api, upper_case_acronyms_aggressive, )) }); - store.register_late_pass(|| Box::new(default::Default::default())); - store.register_late_pass(move || Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api))); - store.register_late_pass(|| Box::new(mutable_debug_assertion::DebugAssertWithMutCall)); - store.register_late_pass(|| Box::new(exit::Exit)); - store.register_late_pass(|| Box::new(to_digit_is_some::ToDigitIsSome)); + store.register_late_pass(|_| Box::new(default::Default::default())); + store.register_late_pass(move |_| Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api))); + store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall)); + store.register_late_pass(|_| Box::new(exit::Exit)); + store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome)); let array_size_threshold = conf.array_size_threshold; - store.register_late_pass(move || Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold))); - store.register_late_pass(move || Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold))); - store.register_late_pass(|| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); + store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold))); + store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold))); + store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); store.register_early_pass(|| Box::new(as_conversions::AsConversions)); - store.register_late_pass(|| Box::new(let_underscore::LetUnderscore)); + store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore)); store.register_early_pass(|| Box::new(single_component_path_imports::SingleComponentPathImports)); let max_fn_params_bools = conf.max_fn_params_bools; let max_struct_bools = conf.max_struct_bools; @@ -795,17 +795,17 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap)); let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; - store.register_late_pass(move || Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); - store.register_late_pass(|| Box::new(redundant_pub_crate::RedundantPubCrate::default())); - store.register_late_pass(|| Box::new(unnamed_address::UnnamedAddress)); - store.register_late_pass(move || Box::new(dereference::Dereferencing::new(msrv))); - store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse)); - store.register_late_pass(|| Box::new(future_not_send::FutureNotSend)); - store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex)); - store.register_late_pass(|| Box::new(if_not_else::IfNotElse)); - store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality)); - store.register_late_pass(|| Box::new(manual_async_fn::ManualAsyncFn)); - store.register_late_pass(|| Box::new(panic_in_result_fn::PanicInResultFn)); + store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); + store.register_late_pass(|_| Box::new(redundant_pub_crate::RedundantPubCrate::default())); + store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); + store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv))); + store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); + store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); + store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex)); + store.register_late_pass(|_| Box::new(if_not_else::IfNotElse)); + store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality)); + store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn)); + store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn)); let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; store.register_early_pass(move || { Box::new(non_expressive_names::NonExpressiveNames { @@ -814,92 +814,92 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::>(); store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(¯o_matcher))); - store.register_late_pass(|| Box::new(macro_use::MacroUseImports::default())); - store.register_late_pass(|| Box::new(pattern_type_mismatch::PatternTypeMismatch)); - store.register_late_pass(|| Box::new(unwrap_in_result::UnwrapInResult)); - store.register_late_pass(|| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); - store.register_late_pass(|| Box::new(async_yields_async::AsyncYieldsAsync)); + store.register_late_pass(|_| Box::new(macro_use::MacroUseImports::default())); + store.register_late_pass(|_| Box::new(pattern_type_mismatch::PatternTypeMismatch)); + store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult)); + store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); + store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync)); let disallowed_methods = conf.disallowed_methods.clone(); - store.register_late_pass(move || Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone()))); + store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone()))); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax)); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax)); - store.register_late_pass(|| Box::new(empty_drop::EmptyDrop)); - store.register_late_pass(|| Box::new(strings::StrToString)); - store.register_late_pass(|| Box::new(strings::StringToString)); - store.register_late_pass(|| Box::new(zero_sized_map_values::ZeroSizedMapValues)); - store.register_late_pass(|| Box::new(vec_init_then_push::VecInitThenPush::default())); - store.register_late_pass(|| Box::new(redundant_slicing::RedundantSlicing)); - store.register_late_pass(|| Box::new(from_str_radix_10::FromStrRadix10)); - store.register_late_pass(move || Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv))); - store.register_late_pass(|| Box::new(bool_assert_comparison::BoolAssertComparison)); + store.register_late_pass(|_| Box::new(empty_drop::EmptyDrop)); + store.register_late_pass(|_| Box::new(strings::StrToString)); + store.register_late_pass(|_| Box::new(strings::StringToString)); + store.register_late_pass(|_| Box::new(zero_sized_map_values::ZeroSizedMapValues)); + store.register_late_pass(|_| Box::new(vec_init_then_push::VecInitThenPush::default())); + store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing)); + store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10)); + store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv))); + store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison)); store.register_early_pass(move || Box::new(module_style::ModStyle)); - store.register_late_pass(|| Box::new(unused_async::UnusedAsync)); + store.register_late_pass(|_| Box::new(unused_async::UnusedAsync)); let disallowed_types = conf.disallowed_types.clone(); - store.register_late_pass(move || Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone()))); + store.register_late_pass(move |_| Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone()))); let import_renames = conf.enforced_import_renames.clone(); - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(missing_enforced_import_rename::ImportRename::new( import_renames.clone(), )) }); let scripts = conf.allowed_scripts.clone(); store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts))); - store.register_late_pass(|| Box::new(strlen_on_c_strings::StrlenOnCStrings)); - store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors)); - store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator)); - store.register_late_pass(move || Box::new(manual_assert::ManualAssert)); + store.register_late_pass(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings)); + store.register_late_pass(move |_| Box::new(self_named_constructors::SelfNamedConstructors)); + store.register_late_pass(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator)); + store.register_late_pass(move |_| Box::new(manual_assert::ManualAssert)); let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new( enable_raw_pointer_heuristic_for_send, )) }); - store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); - store.register_late_pass(move || Box::new(format_args::FormatArgs)); - store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray)); + store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); + store.register_late_pass(move |_| Box::new(format_args::FormatArgs)); + store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); - store.register_late_pass(|| Box::new(needless_late_init::NeedlessLateInit)); - store.register_late_pass(|| Box::new(return_self_not_must_use::ReturnSelfNotMustUse)); - store.register_late_pass(|| Box::new(init_numbered_fields::NumberedFields)); + store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit)); + store.register_late_pass(|_| Box::new(return_self_not_must_use::ReturnSelfNotMustUse)); + store.register_late_pass(|_| Box::new(init_numbered_fields::NumberedFields)); store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames)); - store.register_late_pass(move || Box::new(manual_bits::ManualBits::new(msrv))); - store.register_late_pass(|| Box::new(default_union_representation::DefaultUnionRepresentation)); + store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv))); + store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation)); store.register_early_pass(|| Box::new(doc_link_with_quotes::DocLinkWithQuotes)); - store.register_late_pass(|| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default())); + store.register_late_pass(|_| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default())); let allow_dbg_in_tests = conf.allow_dbg_in_tests; - store.register_late_pass(move || Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); + store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); let cargo_ignore_publish = conf.cargo_ignore_publish; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(cargo::Cargo { ignore_publish: cargo_ignore_publish, }) }); store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef)); store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets)); - store.register_late_pass(|| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings)); + store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings)); store.register_early_pass(|| Box::new(pub_use::PubUse)); - store.register_late_pass(|| Box::new(format_push_string::FormatPushString)); + store.register_late_pass(|_| Box::new(format_push_string::FormatPushString)); let max_include_file_size = conf.max_include_file_size; - store.register_late_pass(move || Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size))); - store.register_late_pass(|| Box::new(strings::TrimSplitWhitespace)); - store.register_late_pass(|| Box::new(rc_clone_in_vec_init::RcCloneInVecInit)); + store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size))); + store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace)); + store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit)); store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default())); store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding)); store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv))); - store.register_late_pass(|| Box::new(swap_ptr_to_ref::SwapPtrToRef)); - store.register_late_pass(|| Box::new(mismatching_type_param_order::TypeParamMismatch)); - store.register_late_pass(|| Box::new(read_zero_byte_vec::ReadZeroByteVec)); - store.register_late_pass(|| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); - store.register_late_pass(move || Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv))); - store.register_late_pass(move || Box::new(manual_retain::ManualRetain::new(msrv))); + store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef)); + store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch)); + store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec)); + store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); + store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv))); let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; - store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold))); - store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); - store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports::default())); - store.register_late_pass(|| Box::new(manual_instant_elapsed::ManualInstantElapsed)); - store.register_late_pass(|| Box::new(partialeq_to_none::PartialeqToNone)); - store.register_late_pass(|| Box::new(manual_string_new::ManualStringNew)); - store.register_late_pass(|| Box::new(unused_peekable::UnusedPeekable)); + store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold))); + store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); + store.register_late_pass(|_| Box::new(std_instead_of_core::StdReexports::default())); + store.register_late_pass(|_| Box::new(manual_instant_elapsed::ManualInstantElapsed)); + store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone)); + store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew)); + store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable)); store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments)); // add lints here, do not remove this comment, it's used in `new_lint` } From bdc865d8f7f50482ae67e942a98bd554e51dda30 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 8 Sep 2022 06:15:33 +0900 Subject: [PATCH 02/27] remove unnecessary `PartialOrd` and `Ord` --- .../rustc_borrowck/src/region_infer/mod.rs | 1 - compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_hir/src/def.rs | 2 +- compiler/rustc_lexer/src/lib.rs | 2 +- compiler/rustc_middle/src/mir/syntax.rs | 2 +- compiler/rustc_middle/src/mir/terminator.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 23 ++----------------- 7 files changed, 7 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8dc9368a0b994..de70b17e44ccd 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -135,7 +135,6 @@ pub struct RegionInferenceContext<'tcx> { /// adds a new lower bound to the SCC it is analyzing: so you wind up /// with `'R: 'O` where `'R` is the pick-region and `'O` is the /// minimal viable option. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub(crate) struct AppliedMemberConstraint { /// The SCC that was affected. (The "member region".) /// diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68abdd0bad1ff..b5f0e22f9254a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -456,7 +456,7 @@ struct HandlerInner { } /// A key denoting where from a diagnostic was stashed. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum StashKey { ItemNoType, UnderscoreForArrayLengths, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index d5ac07f1e6315..b44ee02cfe3bb 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -457,7 +457,7 @@ impl PartialRes { /// Different kinds of symbols can coexist even if they share the same textual name. /// Therefore, they each have a separate universe (known as a "namespace"). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Namespace { /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s /// (and, by extension, crates). diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 178366f7d8045..a79c982649afc 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -141,7 +141,7 @@ pub enum TokenKind { Unknown, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum DocStyle { Outer, Inner, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index d7b9d59eced51..b49fd6f645871 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -705,7 +705,7 @@ pub enum TerminatorKind<'tcx> { } /// Information about an assertion failure. -#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)] +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] pub enum AssertKind { BoundsCheck { len: O, index: O }, Overflow(BinOp, O, O), diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 9ccf5aea63ca8..02a9958525b22 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -14,7 +14,7 @@ use std::slice; pub use super::query::*; -#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)] +#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] pub struct SwitchTargets { /// Possible values. The locations to branch to in each case /// are found in the corresponding indices from the `targets` vector. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index a15a0c298a952..f8a3e5b8bb044 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -57,7 +57,7 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; -use std::{cmp, fmt, ptr}; +use std::{fmt, ptr}; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use imports::{Import, ImportKind, ImportResolver, NameResolution}; @@ -163,7 +163,6 @@ enum ImplTraitContext { Universal(LocalDefId), } -#[derive(Eq)] struct BindingError { name: Symbol, origin: BTreeSet, @@ -171,24 +170,6 @@ struct BindingError { could_be_path: bool, } -impl PartialOrd for BindingError { - fn partial_cmp(&self, other: &BindingError) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for BindingError { - fn eq(&self, other: &BindingError) -> bool { - self.name == other.name - } -} - -impl Ord for BindingError { - fn cmp(&self, other: &BindingError) -> cmp::Ordering { - self.name.cmp(&other.name) - } -} - enum ResolutionError<'a> { /// Error E0401: can't use type or const parameters from outer function. GenericParamsFromOuterFunction(Res, HasGenericParams), @@ -845,7 +826,7 @@ impl<'a> NameBinding<'a> { } } -#[derive(Debug, Default, Clone)] +#[derive(Default, Clone)] pub struct ExternPreludeEntry<'a> { extern_crate_item: Option<&'a NameBinding<'a>>, pub introduced_by_item: bool, From 12ac36c6a4d0ec8fff479a20af7799c85d353cbb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 03:04:44 +0000 Subject: [PATCH 03/27] RPITIT placeholder items --- compiler/rustc_hir/src/def.rs | 5 +++++ compiler/rustc_hir/src/hir.rs | 11 +++++++++++ compiler/rustc_hir/src/intravisit.rs | 7 +++++++ compiler/rustc_hir/src/target.rs | 3 +++ compiler/rustc_hir_pretty/src/lib.rs | 4 ++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +++++ compiler/rustc_metadata/src/rmeta/table.rs | 1 + compiler/rustc_middle/src/hir/map/mod.rs | 2 ++ compiler/rustc_monomorphize/src/polymorphize.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 1 + compiler/rustc_passes/src/reachable.rs | 1 + compiler/rustc_privacy/src/lib.rs | 5 +++++ compiler/rustc_resolve/src/build_reduced_graph.rs | 1 + compiler/rustc_resolve/src/late/lifetimes.rs | 3 +++ compiler/rustc_save_analysis/src/lib.rs | 1 + compiler/rustc_save_analysis/src/sig.rs | 5 +++++ compiler/rustc_ty_utils/src/implied_bounds.rs | 1 + compiler/rustc_typeck/src/astconv/mod.rs | 3 +++ compiler/rustc_typeck/src/collect.rs | 5 +++++ compiler/rustc_typeck/src/collect/type_of.rs | 3 +++ src/librustdoc/clean/utils.rs | 4 ++-- 21 files changed, 70 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index d5ac07f1e6315..93bc99b566b04 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -109,6 +109,8 @@ pub enum DefKind { InlineConst, /// Opaque type, aka `impl Trait`. OpaqueTy, + /// A return-position `impl Trait` in a trait definition + ImplTraitPlaceholder, Field, /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, @@ -138,6 +140,7 @@ impl DefKind { panic!("impossible struct constructor") } DefKind::OpaqueTy => "opaque type", + DefKind::ImplTraitPlaceholder => "opaque type in trait", DefKind::TyAlias => "type alias", DefKind::TraitAlias => "trait alias", DefKind::AssocTy => "associated type", @@ -190,6 +193,7 @@ impl DefKind { | DefKind::Variant | DefKind::Trait | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias @@ -254,6 +258,7 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field | DefKind::TyParam diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 50e7c5d2d04c8..3aff259c20436 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2489,6 +2489,12 @@ pub enum OpaqueTyOrigin { TyAlias, } +/// Placeholder representation of an `impl Trait` in a trait. Since this never gets lowered into a `ty::Opaque` of its own, we just keep this as +#[derive(Debug, HashStable_Generic)] +pub struct ImplTraitPlaceholder<'hir> { + pub bounds: GenericBounds<'hir>, +} + /// The various kinds of types recognized by the compiler. #[derive(Debug, HashStable_Generic)] pub enum TyKind<'hir> { @@ -2516,6 +2522,8 @@ pub enum TyKind<'hir> { /// The generic argument list contains the lifetimes (and in the future /// possibly parameters) that are actually bound on the `impl Trait`. OpaqueDef(ItemId, &'hir [GenericArg<'hir>]), + /// The placeholder + ImplTraitInTrait(ItemId), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime, TraitObjectSyntax), @@ -2971,6 +2979,8 @@ pub enum ItemKind<'hir> { TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`. OpaqueTy(OpaqueTy<'hir>), + /// An `impl Trait` in a trait + ImplTraitPlaceholder(ImplTraitPlaceholder<'hir>), /// An enum definition, e.g., `enum Foo {C, D}`. Enum(EnumDef<'hir>, &'hir Generics<'hir>), /// A struct definition, e.g., `struct Foo {x: A}`. @@ -3039,6 +3049,7 @@ impl ItemKind<'_> { ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", ItemKind::Impl(..) => "implementation", + ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait", } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 20ec788463ac0..3e9ab10b1f7e3 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -562,6 +562,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { walk_generics(visitor, generics); walk_list!(visitor, visit_param_bound, bounds); } + ItemKind::ImplTraitPlaceholder(ImplTraitPlaceholder { bounds }) => { + visitor.visit_id(item.hir_id()); + walk_list!(visitor, visit_param_bound, bounds); + } ItemKind::Enum(ref enum_definition, ref generics) => { visitor.visit_generics(generics); // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`. @@ -674,6 +678,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { visitor.visit_nested_item(item_id); walk_list!(visitor, visit_generic_arg, lifetimes); } + TyKind::ImplTraitInTrait(item_id) => { + visitor.visit_nested_item(item_id); + } TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); visitor.visit_array_length(length) diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 78bfd7191dba9..ea23c48cc5359 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -36,6 +36,7 @@ pub enum Target { GlobalAsm, TyAlias, OpaqueTy, + ImplTraitPlaceholder, Enum, Variant, Struct, @@ -80,6 +81,7 @@ impl Target { ItemKind::GlobalAsm(..) => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, ItemKind::OpaqueTy(..) => Target::OpaqueTy, + ItemKind::ImplTraitPlaceholder(..) => Target::ImplTraitPlaceholder, ItemKind::Enum(..) => Target::Enum, ItemKind::Struct(..) => Target::Struct, ItemKind::Union(..) => Target::Union, @@ -157,6 +159,7 @@ impl Target { Target::GlobalAsm => "global asm", Target::TyAlias => "type alias", Target::OpaqueTy => "opaque type", + Target::ImplTraitPlaceholder => "opaque type in trait", Target::Enum => "enum", Target::Variant => "enum variant", Target::Struct => "struct", diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1220755f44b30..a86aec4df58d1 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -327,6 +327,7 @@ impl<'a> State<'a> { self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names); } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), + hir::TyKind::ImplTraitInTrait(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { @@ -608,6 +609,9 @@ impl<'a> State<'a> { state.print_bounds("= impl", real_bounds); }); } + hir::ItemKind::ImplTraitPlaceholder(..) => { + unreachable!("FIXME(RPITIT): I don't think this ever gets called here..."); + } hir::ItemKind::Enum(ref enum_definition, params) => { self.print_enum_def(enum_definition, params, item.ident.name, item.span); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 039486ba02c37..791b053dc98d4 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -847,6 +847,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field => true, DefKind::TyParam @@ -879,6 +880,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Enum | DefKind::Union | DefKind::Impl @@ -967,6 +969,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Trait | DefKind::TraitAlias @@ -1003,6 +1006,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field | DefKind::TyParam @@ -1491,6 +1495,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); + EntryKind::OpaqueTy } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id); diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index d5f151f0ed8e5..e7c1abd126e04 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -90,6 +90,7 @@ fixed_size_enum! { ( AnonConst ) ( InlineConst ) ( OpaqueTy ) + ( ImplTraitPlaceholder ) ( Field ) ( LifetimeParam ) ( GlobalAsm ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 6217bffb8f76c..1a0bea68293e7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -213,6 +213,7 @@ impl<'hir> Map<'hir> { ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, + ItemKind::ImplTraitPlaceholder(..) => DefKind::ImplTraitPlaceholder, ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, @@ -1188,6 +1189,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::GlobalAsm(..) => "global asm", ItemKind::TyAlias(..) => "ty", ItemKind::OpaqueTy(..) => "opaque type", + ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index af4b35db3bace..98156a94ec4b4 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -170,6 +170,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d0b46aa2c4530..bb684e784c58a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -661,6 +661,7 @@ impl CheckAttrVisitor<'_> { | Target::GlobalAsm | Target::TyAlias | Target::OpaqueTy + | Target::ImplTraitPlaceholder | Target::Enum | Target::Variant | Target::Struct diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f7e3fac6b2e20..74c5ccf9cd205 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -235,6 +235,7 @@ impl<'tcx> ReachableContext<'tcx> { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ba69bc23118b2..900a0ed173511 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -600,6 +600,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::ForeignTy | DefKind::Fn | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::AssocFn | DefKind::Trait | DefKind::TyParam @@ -689,6 +690,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) @@ -724,6 +726,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { self.reach(item.def_id, exist_level).generics().predicates().ty(); } } + hir::ItemKind::ImplTraitPlaceholder(..) => { + // FIXME(RPITIT): Do we need to do anything here? + } // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 51e8c24b9c25a..7e646f0cd9d05 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -964,6 +964,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { | DefKind::TyAlias | DefKind::ForeignTy | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::TraitAlias | DefKind::AssocTy, _, diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 101679aa6dc93..b72b033534b98 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -596,6 +596,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } } + hir::ItemKind::ImplTraitPlaceholder(..) => { + // FIXME(RPITIT): We don't need to do anything here, right? + } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) | hir::ItemKind::Struct(_, ref generics) diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 89bca39512f52..ebe44a56449d3 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -685,6 +685,7 @@ impl<'tcx> SaveContext<'tcx> { | HirDefKind::AssocTy | HirDefKind::Trait | HirDefKind::OpaqueTy + | HirDefKind::ImplTraitPlaceholder | HirDefKind::TyParam, def_id, ) => Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }), diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index d1286c9b8b0df..ea9c82b3597d0 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -320,6 +320,10 @@ impl<'hir> Sig for hir::Ty<'hir> { let item = scx.tcx.hir().item(item_id); item.make(offset, Some(item_id.hir_id()), scx) } + hir::TyKind::ImplTraitInTrait(item_id) => { + let item = scx.tcx.hir().item(item_id); + item.make(offset, Some(item_id.hir_id()), scx) + } hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"), } } @@ -562,6 +566,7 @@ impl<'hir> Sig for hir::Item<'hir> { hir::ItemKind::GlobalAsm(_) => Err("global asm"), hir::ItemKind::ExternCrate(_) => Err("extern crate"), hir::ItemKind::OpaqueTy(..) => Err("opaque type"), + hir::ItemKind::ImplTraitPlaceholder(..) => Err("opaque type in trait"), // FIXME should implement this (e.g., pub use). hir::ItemKind::Use(..) => Err("import"), } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index a77ea440aaaea..f0d8c240ea588 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -51,6 +51,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List dyn AstConv<'tcx> + 'o { ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } + hir::TyKind::ImplTraitInTrait(..) => { + span_bug!(ast_ty.span, "not yet implemented") + } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); let ty = self.ast_ty_to_ty_inner(qself, false, true); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e70f728d7dcce..293a32051b9f9 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -815,6 +815,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().predicates_of(def_id); tcx.ensure().explicit_item_bounds(def_id); } + hir::ItemKind::ImplTraitPlaceholder(..) => { + tcx.ensure().generics_of(def_id); + tcx.ensure().predicates_of(def_id); + tcx.ensure().explicit_item_bounds(def_id); + } hir::ItemKind::TyAlias(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index a0280ddca4bd8..ded2ac1308e54 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -336,6 +336,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) } + ItemKind::ImplTraitPlaceholder(..) => { + span_bug!(item.span, "not yet implemented") + } ItemKind::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::Macro(..) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index a9d511ae11e8b..395f213ca87c3 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -511,8 +511,8 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { | Res::Err => return res.def_id(), Res::Def( TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst - | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure - | Generator, + | InlineConst | OpaqueTy | ImplTraitPlaceholder | Field | LifetimeParam | GlobalAsm + | Impl | Closure | Generator, id, ) => return id, }; From f8a0f3a90eb1c2f9b047fa156f7ec7b3a7d6d40b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:03:24 +0000 Subject: [PATCH 04/27] Lower RPITIT to ImplTraitPlaceholder item --- compiler/rustc_ast_lowering/src/lib.rs | 47 ++++++++++++++++++- compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_hir/src/target.rs | 1 + compiler/rustc_middle/src/ty/error.rs | 5 +- compiler/rustc_middle/src/ty/sty.rs | 5 +- compiler/rustc_resolve/src/late/lifetimes.rs | 3 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/project.rs | 5 ++ compiler/rustc_typeck/src/astconv/mod.rs | 5 +- compiler/rustc_typeck/src/collect.rs | 5 ++ .../rustc_typeck/src/collect/item_bounds.rs | 28 +++++++++++ 11 files changed, 99 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e7bbf7dbdec29..55a239aea114a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -238,6 +238,8 @@ enum ImplTraitContext { }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, + /// Return-position `impl Trait` in trait definition + InTrait, /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -306,9 +308,17 @@ enum FnDeclKind { } impl FnDeclKind { - fn impl_trait_return_allowed(&self) -> bool { + fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { match self { FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, + _ => false, + } + } + + fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, _ => false, } } @@ -1322,6 +1332,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut nested_itctx, ) } + ImplTraitContext::InTrait => { + // FIXME(RPITIT): Should we use def_node_id here? + self.lower_impl_trait_in_trait(span, def_node_id, bounds) + } ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1508,6 +1522,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } + #[tracing::instrument(level = "debug", skip(self))] + fn lower_impl_trait_in_trait( + &mut self, + span: Span, + opaque_ty_node_id: NodeId, + bounds: &GenericBounds, + ) -> hir::TyKind<'hir> { + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { + // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT + // FIXME(RPITIT): We _also_ should support this eventually + let hir_bounds = lctx + .lower_param_bounds(bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Trait)); + let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; + let rpitit_item = hir::Item { + def_id: opaque_ty_def_id, + ident: Ident::empty(), + kind: hir::ItemKind::ImplTraitPlaceholder(rpitit_placeholder), + span: lctx.lower_span(span), + vis_span: lctx.lower_span(span.shrink_to_lo()), + }; + hir::OwnerNode::Item(lctx.arena.alloc(rpitit_item)) + }); + hir::TyKind::ImplTraitInTrait(hir::ItemId { def_id: opaque_ty_def_id }) + } + /// Registers a new opaque type with the proper `NodeId`s and /// returns the lowered node-ID for the opaque type. fn generate_opaque_type( @@ -1666,12 +1706,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match decl.output { FnRetTy::Ty(ref ty) => { let mut context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_return_allowed() => { + Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), } } + Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => { + ImplTraitContext::InTrait + } _ => ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f71b3d59e2c04..3b8032040e76c 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -487,6 +487,8 @@ declare_features! ( (incomplete, repr128, "1.16.0", Some(56071), None), /// Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), + /// Allows return-position `impl Trait` in traits. + (incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), /// Allows `extern "rust-cold"`. (active, rust_cold_cc, "1.63.0", Some(97544), None), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index ea23c48cc5359..0e9b05729d29e 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -105,6 +105,7 @@ impl Target { DefKind::GlobalAsm => Target::GlobalAsm, DefKind::TyAlias => Target::TyAlias, DefKind::OpaqueTy => Target::OpaqueTy, + DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder, DefKind::Enum => Target::Enum, DefKind::Struct => Target::Struct, DefKind::Union => Target::Union, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index da564c66a70e1..279c8c8d6d16d 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -2,6 +2,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::diagnostics::suggest_constraining_type_param; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; +use hir::def::DefKind; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_hir as hir; @@ -538,7 +539,7 @@ impl Trait for X { diag.span_label(p_span, "this type parameter"); } } - (ty::Projection(proj_ty), _) => { + (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { self.expected_projection( diag, proj_ty, @@ -547,7 +548,7 @@ impl Trait for X { cause.code(), ); } - (_, ty::Projection(proj_ty)) => { + (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { let msg = format!( "consider constraining the associated type `{}` to `{}`", values.found, values.expected, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9fb91b5fe8700..c5c5d3473418c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -11,6 +11,7 @@ use crate::ty::{ TypeVisitor, }; use crate::ty::{List, ParamEnv}; +use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; @@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> { impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - tcx.parent(self.item_def_id) + let parent = tcx.parent(self.item_def_id); + assert_eq!(tcx.def_kind(parent), DefKind::Trait); + parent } /// Extracts the underlying trait reference and own substs from this projection. diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index b72b033534b98..e9e4f8fc483c5 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -597,7 +597,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } hir::ItemKind::ImplTraitPlaceholder(..) => { - // FIXME(RPITIT): We don't need to do anything here, right? + // FIXME(RPITIT): We don't need to do anything special here, right? + intravisit::walk_item(self, item); } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 75b1dfc856ac7..4fd9e7407ce14 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1183,6 +1183,7 @@ symbols! { require, residual, result, + return_position_impl_trait_in_trait, rhs, rintf32, rintf64, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 76c1ade0680c5..113aebc43eb5f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1425,6 +1425,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { + // Can't assemble candidate from impl for RPITIT + if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { + return; + } + // If we are resolving `>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2bc3218607ad6..d0a74c6c147cb 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2638,8 +2638,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } - hir::TyKind::ImplTraitInTrait(..) => { - span_bug!(ast_ty.span, "not yet implemented") + hir::TyKind::ImplTraitInTrait(item_id) => { + let def_id = item_id.def_id.to_def_id(); + tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id)) } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 293a32051b9f9..5429598871d99 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1600,6 +1600,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // inherit the generics of the item. Some(parent_id.to_def_id()) } + ItemKind::ImplTraitPlaceholder(_) => { + let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id(); + assert_eq!(tcx.def_kind(parent_id), DefKind::AssocFn); + Some(parent_id) + } _ => None, }, _ => None, diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 318e8f581f7c8..fe8d8f54f0477 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -74,6 +74,29 @@ fn opaque_type_bounds<'tcx>( }) } +/// Opaque types don't inherit bounds from their parent: for return position +/// impl trait it isn't possible to write a suitable predicate on the +/// containing function and for type-alias impl trait we don't have a backwards +/// compatibility issue. +fn impl_trait_in_trait_item_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_def_id: DefId, + ast_bounds: &'tcx [hir::GenericBound<'tcx>], + span: Span, +) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + ty::print::with_no_queries!({ + // FIXME(RPITIT): DRY-er code please + let item_ty = + tcx.mk_projection(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); + + let icx = ItemCtxt::new(tcx, opaque_def_id); + let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); + // RPITITs are implicitly sized unless a `?Sized` bound is found + >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) + }) +} + pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: DefId, @@ -90,6 +113,11 @@ pub(super) fn explicit_item_bounds( span, .. }) => opaque_type_bounds(tcx, def_id, bounds, *span), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }), + span, + .. + }) => impl_trait_in_trait_item_bounds(tcx, def_id, bounds, *span), _ => bug!("item_bounds called on {:?}", def_id), } } From 62ed2fe1c6c39ca3d94aee3ae67c8eb9efb0a721 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:41:16 +0000 Subject: [PATCH 05/27] Implement projection for ImplTraitPlaceholder --- compiler/rustc_privacy/src/lib.rs | 4 +- .../src/traits/project.rs | 117 ++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 900a0ed173511..4c7837aa5e8fc 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -2040,7 +2040,9 @@ fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility { // Visibility on them should have no effect, but to avoid the visibility // query failing on some items, we provide it for opaque types as well. | Node::Item(hir::Item { - kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) | hir::ItemKind::OpaqueTy(..), + kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) + | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..), .. }) => ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id()), // Visibilities of trait impl items are inherited from their traits diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 113aebc43eb5f..de18ad393ba7e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -32,6 +32,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable}; +use rustc_middle::ty::DefIdTree; use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -70,6 +71,8 @@ enum ProjectionCandidate<'tcx> { /// From an "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), + + ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>), } enum ProjectionCandidateSet<'tcx> { @@ -1225,6 +1228,8 @@ fn project<'cx, 'tcx>( let mut candidates = ProjectionCandidateSet::None; + assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates); + // Make sure that the following procedures are kept in order. ParamEnv // needs to be first because it has highest priority, and Select checks // the return value of push_candidate which assumes it's ran at last. @@ -1263,6 +1268,48 @@ fn project<'cx, 'tcx>( } } +/// The first thing we have to do is scan through the parameter +/// environment to see whether there are any projection predicates +/// there that can answer this question. +fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, +) { + let tcx = selcx.tcx(); + if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { + let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id); + let trait_def_id = tcx.parent(trait_fn_def_id); + let trait_substs = + obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); + // FIXME(named-returns): Binders + let trait_predicate = + ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs }) + .to_poly_trait_predicate(); + + let _ = + selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) { + Ok(Some(super::ImplSource::UserDefined(data))) => { + candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data)); + Ok(()) + } + Ok(None) => { + candidate_set.mark_ambiguous(); + return Err(()); + } + Ok(Some(_)) => { + // Don't know enough about the impl to provide a useful signature + return Err(()); + } + Err(e) => { + debug!(error = ?e, "selection error"); + candidate_set.mark_error(e); + return Err(()); + } + }); + } +} + /// The first thing we have to do is scan through the parameter /// environment to see whether there are any projection predicates /// there that can answer this question. @@ -1705,6 +1752,9 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } + ProjectionCandidate::ImplTraitInTrait(data) => { + confirm_impl_trait_in_trait_candidate(selcx, obligation, data) + } }; // When checking for cycle during evaluation, we compare predicates with @@ -2067,6 +2117,73 @@ fn confirm_impl_candidate<'cx, 'tcx>( } } +fn confirm_impl_trait_in_trait_candidate<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx> { + let tcx = selcx.tcx(); + let mut obligations = data.nested; + + let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id); + let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else { + return Progress { term: tcx.ty_error().into(), obligations }; + }; + if !leaf_def.item.defaultness(tcx).has_value() { + return Progress { term: tcx.ty_error().into(), obligations }; + } + + let impl_fn_def_id = leaf_def.item.def_id; + let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); + + let sig = tcx + .bound_fn_sig(impl_fn_def_id) + .map_bound(|fn_sig| tcx.liberate_late_bound_regions(impl_fn_def_id, fn_sig)) + .subst(tcx, impl_fn_substs); + + let cause = ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + super::ItemObligation(impl_fn_def_id), + ); + let predicates = normalize_with_depth_to( + selcx, + obligation.param_env, + cause.clone(), + obligation.recursion_depth + 1, + tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs), + &mut obligations, + ); + obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map( + |(pred, span)| { + Obligation::with_depth( + ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + if span.is_dummy() { + super::ItemObligation(impl_fn_def_id) + } else { + super::BindingObligation(impl_fn_def_id, span) + }, + ), + obligation.recursion_depth + 1, + obligation.param_env, + pred, + ) + }, + )); + + let ty = super::normalize_to( + selcx, + obligation.param_env, + cause.clone(), + sig.output(), + &mut obligations, + ); + + Progress { term: ty.into(), obligations } +} + // Get obligations corresponding to the predicates from the where-clause of the // associated type itself. // Note: `feature(generic_associated_types)` is required to write such From 582efcc7ea79346c21dd5e55d80ab720395e0ddd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:41:20 +0000 Subject: [PATCH 06/27] Rustdoc support --- src/librustdoc/clean/mod.rs | 10 ++++++++++ src/librustdoc/formats/item_type.rs | 1 + src/librustdoc/passes/collect_intra_doc_links.rs | 4 ++-- src/librustdoc/visit_ast.rs | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 980a1485b59b7..2be89a0fb370f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1500,6 +1500,16 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T unreachable!() } } + TyKind::ImplTraitInTrait(item_id) => { + let item = cx.tcx.hir().item(item_id); + if let hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }) = + item.kind + { + ImplTrait(bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) + } else { + unreachable!() + } + } TyKind::Path(_) => clean_qpath(ty, cx), TyKind::TraitObject(bounds, ref lifetime, _) => { let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect(); diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 0a7ee2005915b..f21e60a64e005 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -135,6 +135,7 @@ impl From for ItemType { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index c27f0ce18c141..cfd6ce402c28a 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1805,8 +1805,8 @@ fn resolution_failure( } return; } - Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam - | Static(_) => "associated item", + Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder + | TraitAlias | TyParam | Static(_) => "associated item", Impl | GlobalAsm => unreachable!("not a path"), } } else { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ca7a20bf3688a..7fe391f420f6a 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -362,6 +362,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Union(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)), From 15b8de86d869e285541f33475d9c85d13a5a6cd6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 05:12:40 +0000 Subject: [PATCH 07/27] Check that impl types actually satisfy RPITIT bounds --- .../rustc_typeck/src/check/compare_method.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index b6bc244d2b144..e55f43994b9f3 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -391,6 +391,30 @@ fn compare_predicate_entailment<'tcx>( return Err(diag.emit()); } + // Check that an impl's fn return satisfies the bounds of the + // FIXME(RPITIT): Generalize this to nested impl traits + if let ty::Projection(proj) = tcx.fn_sig(trait_m.def_id).skip_binder().output().kind() + && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder + { + let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); + + for (predicate, span) in tcx + .bound_explicit_item_bounds(proj.item_def_id) + .transpose_iter() + .map(|pred| pred.map_bound(|pred| *pred).subst(tcx, trait_to_placeholder_substs)) + { + ocx.register_obligation(traits::Obligation::new( + traits::ObligationCause::new( + return_span, + impl_m_hir_id, + ObligationCauseCode::BindingObligation(proj.item_def_id, span), + ), + param_env, + predicate, + )); + } + } + // Check that all obligations are satisfied by the implementation's // version. let errors = ocx.select_all_or_error(); From dffcca04ec8db44d5e9c45523d4bb9d0fbda143b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:46:54 +0000 Subject: [PATCH 08/27] Add tests --- ...ate-return_position_impl_trait_in_trait.rs | 5 +++ ...return_position_impl_trait_in_trait.stderr | 9 +++++ .../ui/impl-trait/in-trait/doesnt-satisfy.rs | 13 ++++++ .../impl-trait/in-trait/doesnt-satisfy.stderr | 17 ++++++++ .../in-trait/opaque-in-impl-is-opaque.rs | 19 +++++++++ .../in-trait/opaque-in-impl-is-opaque.stderr | 17 ++++++++ .../ui/impl-trait/in-trait/opaque-in-impl.rs | 20 ++++++++++ src/test/ui/impl-trait/in-trait/success.rs | 40 +++++++++++++++++++ 8 files changed, 140 insertions(+) create mode 100644 src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs create mode 100644 src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr create mode 100644 src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs create mode 100644 src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr create mode 100644 src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs create mode 100644 src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr create mode 100644 src/test/ui/impl-trait/in-trait/opaque-in-impl.rs create mode 100644 src/test/ui/impl-trait/in-trait/success.rs diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs new file mode 100644 index 0000000000000..de7966c66b057 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs @@ -0,0 +1,5 @@ +trait Foo { + fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr new file mode 100644 index 0000000000000..a41f5789fdbfa --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:2:17 + | +LL | fn bar() -> impl Sized; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs new file mode 100644 index 0000000000000..bb4e0d44f3eff --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs @@ -0,0 +1,13 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar() -> impl std::fmt::Display; +} + +impl Foo for () { + fn bar() -> () {} + //~^ ERROR `()` doesn't implement `std::fmt::Display` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr new file mode 100644 index 0000000000000..aa5492d285ed6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -0,0 +1,17 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/doesnt-satisfy.rs:9:17 + | +LL | fn bar() -> () {} + | ^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Foo::bar::{opaque#0}` + --> $DIR/doesnt-satisfy.rs:5:22 + | +LL | fn bar() -> impl std::fmt::Display; + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs new file mode 100644 index 0000000000000..3ac264e8ebac5 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs @@ -0,0 +1,19 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for () { + fn bar(&self) -> impl Display { + "Hello, world" + } +} + +fn main() { + let x: &str = ().bar(); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr new file mode 100644 index 0000000000000..15edda4834015 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/opaque-in-impl-is-opaque.rs:17:19 + | +LL | fn bar(&self) -> impl Display { + | ------------ the found opaque type +... +LL | let x: &str = ().bar(); + | ---- ^^^^^^^^ expected `&str`, found opaque type + | | + | expected due to this + | + = note: expected reference `&str` + found opaque type `impl std::fmt::Display` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs new file mode 100644 index 0000000000000..a777cbcd529a6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for () { + fn bar(&self) -> impl Display { + "Hello, world" + } +} + +fn main() { + println!("{}", ().bar()); +} diff --git a/src/test/ui/impl-trait/in-trait/success.rs b/src/test/ui/impl-trait/in-trait/success.rs new file mode 100644 index 0000000000000..4cbe682b46f73 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/success.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for i32 { + fn bar(&self) -> i32 { + *self + } +} + +impl Foo for &'static str { + fn bar(&self) -> &'static str { + *self + } +} + +struct Yay; + +impl Foo for Yay { + fn bar(&self) -> String { + String::from(":^)") + } +} + +fn foo_generically(t: T) { + println!("{}", t.bar()); +} + +fn main() { + println!("{}", "Hello, world.".bar()); + println!("The answer is {}!", 42.bar()); + foo_generically(Yay); +} From 57a56bd5e41b3e42c32032cd1cbd877d4b897ce4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 05:29:36 +0000 Subject: [PATCH 09/27] Make clippy happy --- src/tools/clippy/clippy_lints/src/dereference.rs | 2 +- src/tools/clippy/clippy_lints/src/missing_doc.rs | 3 ++- src/tools/clippy/clippy_lints/src/missing_inline.rs | 1 + src/tools/clippy/clippy_utils/src/hir_utils.rs | 3 +++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index d1ab7fb67962e..09a073f4234d0 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -959,7 +959,7 @@ fn binding_ty_auto_deref_stability<'tcx>( )) .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), ), - TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { + TyKind::OpaqueDef(..) | TyKind::ImplTraitInTrait(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { Position::ReborrowStable(precedence) }, }; diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 3701fdb4adbff..9f518c7aaa39f 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -147,7 +147,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::TraitAlias(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) - | hir::ItemKind::OpaqueTy(..) => {}, + | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) => {}, hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 07bc2ca5d3cd2..9fd1a475d7496 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -128,6 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Impl { .. } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 57448f716d494..6e4451e96120e 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -990,6 +990,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { TyKind::OpaqueDef(_, arg_list) => { self.hash_generic_args(arg_list); }, + TyKind::ImplTraitInTrait(_) => { + // Do nothing + } TyKind::TraitObject(_, lifetime, _) => { self.hash_lifetime(*lifetime); }, From d5a83c48ca4b8ae1a151fea3252e86d5eb03c1f3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 15:57:31 +0000 Subject: [PATCH 10/27] Make async fn in traits work --- compiler/rustc_ast/src/ast.rs | 4 ++-- compiler/rustc_ast_lowering/src/errors.rs | 11 ++++++++++ compiler/rustc_ast_lowering/src/expr.rs | 5 +++-- compiler/rustc_ast_lowering/src/item.rs | 14 +++++++++---- compiler/rustc_ast_lowering/src/lib.rs | 21 ++++++++++++------- .../rustc_ast_passes/src/ast_validation.rs | 7 ------- compiler/rustc_ast_passes/src/errors.rs | 11 ---------- .../locales/en-US/ast_lowering.ftl | 6 ++++++ .../locales/en-US/ast_passes.ftl | 6 ------ compiler/rustc_resolve/src/late.rs | 2 +- 10 files changed, 46 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f25fdc942b085..29ecab29cd597 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2367,9 +2367,9 @@ impl Async { } /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item. - pub fn opt_return_id(self) -> Option { + pub fn opt_return_id(self) -> Option<(NodeId, Span)> { match self { - Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id), + Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)), Async::No => None, } } diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 4adeaef9bbfa8..c87d0ca96570e 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -334,3 +334,14 @@ pub struct InclusiveRangeWithNoEnd { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::trait_fn_async, code = "E0706")] +#[note] +#[note(ast_lowering::note2)] +pub struct TraitFnAsync { + #[primary_span] + pub fn_span: Span, + #[label] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6fa8d7f0fcdd9..79babbfd6d63c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -851,7 +851,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -955,7 +955,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); + let fn_decl = + self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f0717b51d4b18..088ac42783106 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -267,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id) + this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id) }); let sig = hir::FnSig { decl, @@ -659,7 +659,13 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics(generics, i.id, &mut itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None), + this.lower_fn_decl( + fdec, + None, + sig.span, + FnDeclKind::ExternFn, + None, + ), this.lower_fn_params_to_names(fdec), ) }); @@ -1238,12 +1244,12 @@ impl<'hir> LoweringContext<'_, 'hir> { sig: &FnSig, id: NodeId, kind: FnDeclKind, - is_async: Option, + is_async: Option<(NodeId, Span)>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); let mut itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| { - this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) + this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 55a239aea114a..07043d9f0efa7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -42,7 +42,7 @@ #[macro_use] extern crate tracing; -use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait}; +use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync}; use rustc_ast::ptr::P; use rustc_ast::visit; @@ -1251,7 +1251,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_params, unsafety: self.lower_unsafety(f.unsafety), abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None), param_names: self.lower_fn_params_to_names(&f.decl), })) } @@ -1653,19 +1653,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the // given DefId, otherwise impl Trait is disallowed. Must be `Some` if // `make_ret_async` is also `Some`. - // `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position. - // This guards against trait declarations and implementations where `impl Trait` is - // disallowed. // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future` in the // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the - // return type `impl Trait` item. + // return type `impl Trait` item, and the `Span` points to the `async` keyword. #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, decl: &FnDecl, fn_node_id: Option, + fn_span: Span, kind: FnDeclKind, - make_ret_async: Option, + make_ret_async: Option<(NodeId, Span)>, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1696,7 +1694,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } })); - let output = if let Some(ret_id) = make_ret_async { + let output = if let Some((ret_id, span)) = make_ret_async { + if !self.tcx.features().return_position_impl_trait_in_trait { + self.tcx.sess.emit_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ); + } + self.lower_async_fn_ret_ty( &decl.output, fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d6d8881a53a14..6c754f38d144b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -290,12 +290,6 @@ impl<'a> AstValidator<'a> { } } - fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) { - if let Async::Yes { span, .. } = asyncness { - self.session.emit_err(TraitFnAsync { fn_span, span }); - } - } - fn check_trait_fn_not_const(&self, constness: Const) { if let Const::Yes(span) = constness { self.session.emit_err(TraitFnConst { span }); @@ -1596,7 +1590,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&item.vis, None); if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.check_trait_fn_not_const(sig.header.constness); - self.check_trait_fn_not_async(item.span, sig.header.asyncness); } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 21467e5765198..4f3b09c587113 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -79,17 +79,6 @@ pub enum InvalidVisibilityNote { IndividualForeignItems, } -#[derive(SessionDiagnostic)] -#[diag(ast_passes::trait_fn_async, code = "E0706")] -#[note] -#[note(ast_passes::note2)] -pub struct TraitFnAsync { - #[primary_span] - pub fn_span: Span, - #[label] - pub span: Span, -} - #[derive(SessionDiagnostic)] #[diag(ast_passes::trait_fn_const, code = "E0379")] pub struct TraitFnConst { diff --git a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl index f2790531aba44..c45e045b4dba0 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl @@ -131,3 +131,9 @@ ast_lowering_arbitrary_expression_in_pattern = arbitrary expressions aren't allowed in patterns ast_lowering_inclusive_range_with_no_end = inclusive range with no end + +ast_lowering_trait_fn_async = + functions in traits cannot be declared `async` + .label = `async` because of this + .note = `async` trait functions are not currently supported + .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl index d7108e1e2de35..e5cd1142b20c8 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl @@ -26,12 +26,6 @@ ast_passes_invalid_visibility = .individual_impl_items = place qualifiers on individual impl items instead .individual_foreign_items = place qualifiers on individual foreign items instead -ast_passes_trait_fn_async = - functions in traits cannot be declared `async` - .label = `async` because of this - .note = `async` trait functions are not currently supported - .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait - ast_passes_trait_fn_const = functions in traits cannot be declared const .label = functions in traits cannot be const diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b37feb15890ba..2d6e76c451bfa 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -851,7 +851,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // We include all lifetime parameters, either named or "Fresh". // The order of those parameters does not matter, as long as it is // deterministic. - if let Some(async_node_id) = async_node_id { + if let Some((async_node_id, _)) = async_node_id { let mut extra_lifetime_params = this .r .extra_lifetime_params_map From 63360b0033ac798f5d9259ef0d03326d404dff6a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 16:45:30 +0000 Subject: [PATCH 11/27] Address rebase issues, make async fn in trait work --- compiler/rustc_ast_lowering/src/item.rs | 10 ++- compiler/rustc_ast_lowering/src/lib.rs | 92 ++++++++++++++++---- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +- 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 088ac42783106..21143fda5582f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -775,9 +775,15 @@ impl<'hir> LoweringContext<'_, 'hir> { (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { + let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); - let (generics, sig) = - self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None); + let (generics, sig) = self.lower_method_sig( + generics, + sig, + i.id, + FnDeclKind::Trait, + asyncness.opt_return_id(), + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 07043d9f0efa7..b3777df323055 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1334,7 +1334,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::InTrait => { // FIXME(RPITIT): Should we use def_node_id here? - self.lower_impl_trait_in_trait(span, def_node_id, bounds) + self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { + lctx.lower_param_bounds( + bounds, + ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + ) + }) } ImplTraitContext::Universal => { let span = t.span; @@ -1522,19 +1527,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, lower_bounds))] fn lower_impl_trait_in_trait( &mut self, span: Span, opaque_ty_node_id: NodeId, - bounds: &GenericBounds, + lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, ) -> hir::TyKind<'hir> { let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT // FIXME(RPITIT): We _also_ should support this eventually - let hir_bounds = lctx - .lower_param_bounds(bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Trait)); + let hir_bounds = lower_bounds(lctx); let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; let rpitit_item = hir::Item { def_id: opaque_ty_def_id, @@ -1695,18 +1699,44 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })); let output = if let Some((ret_id, span)) = make_ret_async { - if !self.tcx.features().return_position_impl_trait_in_trait { - self.tcx.sess.emit_feature_err( - TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, - ); + match kind { + FnDeclKind::Trait => { + if !kind.impl_trait_in_trait_allowed(self.tcx) { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } + self.lower_async_fn_ret_ty_in_trait( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + ) + } + _ => { + if !kind.impl_trait_return_allowed(self.tcx) { + if kind == FnDeclKind::Impl { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } else { + self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); + } + } + self.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + ) + } } - - self.lower_async_fn_ret_ty( - &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), - ret_id, - ) } else { match decl.output { FnRetTy::Ty(ref ty) => { @@ -1997,6 +2027,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } + // Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }` + // combined with the following definition of `OpaqueTy`: + // + // type OpaqueTy = impl Future; + // + // `output`: unlowered output type (`T` in `-> T`) + // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) + // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created + #[instrument(level = "debug", skip(self))] + fn lower_async_fn_ret_ty_in_trait( + &mut self, + output: &FnRetTy, + fn_node_id: NodeId, + opaque_ty_node_id: NodeId, + ) -> hir::FnRetTy<'hir> { + let span = output.span(); + + let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + + let fn_def_id = self.local_def_id(fn_node_id); + + let kind = self.lower_impl_trait_in_trait(output.span(), opaque_ty_node_id, |lctx| { + let bound = + lctx.lower_async_fn_output_type_to_future_bound(output, fn_def_id, output.span()); + arena_vec![lctx; bound] + }); + let opaque_ty = self.ty(opaque_ty_span, kind); + hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) + } + /// Transforms `-> T` into `Future`. fn lower_async_fn_output_type_to_future_bound( &mut self, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 791b053dc98d4..ff321ec5ef02d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1036,6 +1036,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn @@ -1085,6 +1086,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn @@ -1495,7 +1497,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); - EntryKind::OpaqueTy + } + hir::ItemKind::ImplTraitPlaceholder(..) => { + self.encode_explicit_item_bounds(def_id); } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id); From e41b43069c4e62f3fb6d7e4d603e3a6c109072f8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 16:55:24 +0000 Subject: [PATCH 12/27] Address nits --- compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_hir/src/def.rs | 4 ++-- compiler/rustc_hir/src/hir.rs | 5 ++++- compiler/rustc_trait_selection/src/traits/project.rs | 6 +++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b3777df323055..0ba2539f343cf 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1333,7 +1333,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } ImplTraitContext::InTrait => { - // FIXME(RPITIT): Should we use def_node_id here? self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { lctx.lower_param_bounds( bounds, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 93bc99b566b04..631e92aa28277 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -193,7 +193,6 @@ impl DefKind { | DefKind::Variant | DefKind::Trait | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias @@ -221,7 +220,8 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::GlobalAsm - | DefKind::Impl => None, + | DefKind::Impl + | DefKind::ImplTraitPlaceholder => None, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 3aff259c20436..ed31de61f7605 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2522,7 +2522,10 @@ pub enum TyKind<'hir> { /// The generic argument list contains the lifetimes (and in the future /// possibly parameters) that are actually bound on the `impl Trait`. OpaqueDef(ItemId, &'hir [GenericArg<'hir>]), - /// The placeholder + /// A type that represents an `impl Trait` in a trait function. This is + /// not an opaque type, since it acts more like an associated type than + /// an opaque, and since it needs no generics since it inherits those + /// from the item's parent. ImplTraitInTrait(ItemId), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index de18ad393ba7e..0212d8ace941a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1268,9 +1268,9 @@ fn project<'cx, 'tcx>( } } -/// The first thing we have to do is scan through the parameter -/// environment to see whether there are any projection predicates -/// there that can answer this question. +/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the +/// corresponding trait ref. If this yields an `impl`, then we're able to project +/// to a concrete type, since we have an `impl`'s method to provide the RPITIT. fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, From e0322163a70201a082c5a55c324b108a75ca92df Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 17:54:58 +0000 Subject: [PATCH 13/27] Bless tests, fix ICE with ImplTraitPlaceholder --- compiler/rustc_ast_lowering/src/lib.rs | 31 +-- compiler/rustc_typeck/src/check/closure.rs | 12 +- src/test/ui/async-await/async-trait-fn.rs | 3 + src/test/ui/async-await/async-trait-fn.stderr | 75 +++++-- .../edition-deny-async-fns-2015.rs | 3 +- .../edition-deny-async-fns-2015.stderr | 30 ++- .../ui/async-await/issues/issue-95307.stderr | 2 + src/test/ui/parser/fn-header-semantic-fail.rs | 2 - .../ui/parser/fn-header-semantic-fail.stderr | 184 ++++++++---------- ...ue-70736-async-fn-no-body-def-collector.rs | 1 - ...0736-async-fn-no-body-def-collector.stderr | 43 ++-- ...021-incompatible-closure-captures-93117.rs | 5 +- ...incompatible-closure-captures-93117.stderr | 46 +++-- 13 files changed, 245 insertions(+), 192 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0ba2539f343cf..1c9ef12996e6c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1936,8 +1936,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); + let future_bound = this.lower_async_fn_output_type_to_future_bound( + output, + span, + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + }, + ); let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { @@ -2041,17 +2046,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn_node_id: NodeId, opaque_ty_node_id: NodeId, ) -> hir::FnRetTy<'hir> { - let span = output.span(); - - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); - - let fn_def_id = self.local_def_id(fn_node_id); - let kind = self.lower_impl_trait_in_trait(output.span(), opaque_ty_node_id, |lctx| { - let bound = - lctx.lower_async_fn_output_type_to_future_bound(output, fn_def_id, output.span()); + let bound = lctx.lower_async_fn_output_type_to_future_bound( + output, + output.span(), + ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn), + ); arena_vec![lctx; bound] }); + + let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, output.span(), None); let opaque_ty = self.ty(opaque_ty_span, kind); hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } @@ -2060,8 +2064,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: LocalDefId, span: Span, + mut nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { @@ -2069,10 +2073,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - let mut context = ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - }; - self.lower_ty(ty, &mut context) + self.lower_ty(ty, &mut nested_impl_trait_context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index bc3fec6e7d66a..55cbaf71e7cfd 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -4,6 +4,7 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use crate::astconv::AstConv; use crate::rustc_middle::ty::subst::Subst; +use hir::def::DefKind; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -680,9 +681,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|e| e.map_bound(|e| *e).transpose_tuple2()) .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?, ty::Error(_) => return None, + ty::Projection(proj) + if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder => + { + self.tcx + .bound_explicit_item_bounds(proj.item_def_id) + .transpose_iter() + .map(|e| e.map_bound(|e| *e).transpose_tuple2()) + .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))? + } _ => span_bug!( self.tcx.def_span(expr_def_id), - "async fn generator return type not an inference variable" + "async fn generator return type not an inference variable: {ret_ty}" ), }; diff --git a/src/test/ui/async-await/async-trait-fn.rs b/src/test/ui/async-await/async-trait-fn.rs index e2062e82725c0..0ea685986db40 100644 --- a/src/test/ui/async-await/async-trait-fn.rs +++ b/src/test/ui/async-await/async-trait-fn.rs @@ -1,8 +1,11 @@ // edition:2018 trait T { async fn foo() {} //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types async fn baz() { //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types // Nested item must not ICE. fn a() {} } diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index 1eb8969a80d20..e30dfb1e1a705 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -2,40 +2,89 @@ error[E0706]: functions in traits cannot be declared `async` --> $DIR/async-trait-fn.rs:3:5 | LL | async fn foo() {} - | -----^^^^^^^^^^^^ + | -----^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:4:5 + --> $DIR/async-trait-fn.rs:5:5 | LL | async fn bar(&self) {} - | -----^^^^^^^^^^^^^^^^^ + | -----^^^^^^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:5:5 + --> $DIR/async-trait-fn.rs:7:5 + | +LL | async fn baz() { + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:3:20 + | +LL | async fn foo() {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::foo::{opaque#0}` + found opaque type `impl Future` + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:5:25 + | +LL | async fn bar(&self) {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::bar::{opaque#0}` + found opaque type `impl Future` + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:7:20 | LL | async fn baz() { - | ^---- - | | - | _____`async` because of this - | | + | ____________________^ +LL | | LL | | // Nested item must not ICE. LL | | fn a() {} LL | | } - | |_____^ + | |_____^ expected associated type, found opaque type | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::baz::{opaque#0}` + found opaque type `impl Future` -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0706`. +Some errors have detailed explanations: E0308, E0706. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs index e5dc9c8a5fee8..22a61dcd25f98 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs @@ -16,7 +16,8 @@ impl Foo { trait Bar { async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 - //~^ ERROR functions in traits cannot be declared `async` + //~^ ERROR functions in traits cannot be declared `async` + //~| ERROR mismatched types } fn main() { diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index 35f9c581c7b21..2f40ef1ccbb14 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -53,7 +53,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:36:9 + --> $DIR/edition-deny-async-fns-2015.rs:37:9 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -62,7 +62,7 @@ LL | async fn bar() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:26:9 + --> $DIR/edition-deny-async-fns-2015.rs:27:9 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -71,7 +71,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:31:13 + --> $DIR/edition-deny-async-fns-2015.rs:32:13 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -83,14 +83,30 @@ error[E0706]: functions in traits cannot be declared `async` --> $DIR/edition-deny-async-fns-2015.rs:18:5 | LL | async fn foo() {} - | -----^^^^^^^^^^^^ + | -----^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error: aborting due to 10 previous errors +error[E0308]: mismatched types + --> $DIR/edition-deny-async-fns-2015.rs:18:20 + | +LL | async fn foo() {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::foo::{opaque#0}` + found opaque type `impl Future` + +error: aborting due to 11 previous errors -Some errors have detailed explanations: E0670, E0706. -For more information about an error, try `rustc --explain E0670`. +Some errors have detailed explanations: E0308, E0670, E0706. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/issues/issue-95307.stderr b/src/test/ui/async-await/issues/issue-95307.stderr index 29aebb719d66f..1c12f1e4862e8 100644 --- a/src/test/ui/async-await/issues/issue-95307.stderr +++ b/src/test/ui/async-await/issues/issue-95307.stderr @@ -8,6 +8,8 @@ LL | async fn new() -> [u8; _]; | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/issue-95307.rs:7:28 diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs index 8ff14fb1f304a..cf5d3dab4aada 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.rs +++ b/src/test/ui/parser/fn-header-semantic-fail.rs @@ -27,7 +27,6 @@ fn main() { struct Y; impl X for Y { async fn ft1() {} //~ ERROR functions in traits cannot be declared `async` - //~^ ERROR has an incompatible type for trait unsafe fn ft2() {} // OK. const fn ft3() {} //~ ERROR functions in traits cannot be declared const extern "C" fn ft4() {} @@ -36,7 +35,6 @@ fn main() { //~| ERROR functions in traits cannot be declared const //~| ERROR functions cannot be both `const` and `async` //~| ERROR cycle detected - //~| ERROR has an incompatible type for trait } impl Y { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index bc51ba8b8c5c5..36304779df36f 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -7,17 +7,6 @@ LL | const async unsafe extern "C" fn ff5() {} | | `async` because of this | `const` because of this -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:17:9 - | -LL | async fn ft1(); - | -----^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0379]: functions in traits cannot be declared const --> $DIR/fn-header-semantic-fail.rs:19:9 | @@ -30,17 +19,6 @@ error[E0379]: functions in traits cannot be declared const LL | const async unsafe extern "C" fn ft5(); | ^^^^^ functions in traits cannot be const -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:21:9 - | -LL | const async unsafe extern "C" fn ft5(); - | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:21:9 | @@ -50,42 +28,20 @@ LL | const async unsafe extern "C" fn ft5(); | | `async` because of this | `const` because of this -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:29:9 - | -LL | async fn ft1() {} - | -----^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:32:9 + --> $DIR/fn-header-semantic-fail.rs:31:9 | LL | const fn ft3() {} | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^ functions in traits cannot be const -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:34:9 - | -LL | const async unsafe extern "C" fn ft5() {} - | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^-^^^^^------------------------------ @@ -94,7 +50,7 @@ LL | const async unsafe extern "C" fn ft5() {} | `const` because of this error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:47:9 + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^-^^^^^------------------------------ @@ -103,7 +59,7 @@ LL | const async unsafe extern "C" fn fi5() {} | `const` because of this error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:53:18 + --> $DIR/fn-header-semantic-fail.rs:51:18 | LL | extern "C" { | ---------- in this `extern` block @@ -116,7 +72,7 @@ LL | fn fe1(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:54:19 + --> $DIR/fn-header-semantic-fail.rs:52:19 | LL | extern "C" { | ---------- in this `extern` block @@ -130,7 +86,7 @@ LL | fn fe2(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:55:18 + --> $DIR/fn-header-semantic-fail.rs:53:18 | LL | extern "C" { | ---------- in this `extern` block @@ -144,7 +100,7 @@ LL | fn fe3(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:56:23 + --> $DIR/fn-header-semantic-fail.rs:54:23 | LL | extern "C" { | ---------- in this `extern` block @@ -158,7 +114,7 @@ LL | fn fe4(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:57:42 + --> $DIR/fn-header-semantic-fail.rs:55:42 | LL | extern "C" { | ---------- in this `extern` block @@ -172,7 +128,7 @@ LL | fn fe5(); | ~~ error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:57:9 + --> $DIR/fn-header-semantic-fail.rs:55:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^-^^^^^---------------------------- @@ -180,6 +136,58 @@ LL | const async unsafe extern "C" fn fe5(); | | `async` because of this | `const` because of this +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:17:9 + | +LL | async fn ft1(); + | -----^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:21:9 + | +LL | const async unsafe extern "C" fn ft5(); + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:29:9 + | +LL | async fn ft1() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}` --> $DIR/fn-header-semantic-fail.rs:12:44 | @@ -216,60 +224,24 @@ LL | | } LL | | } | |_^ -error[E0053]: method `ft1` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:29:24 - | -LL | async fn ft1() {} - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:17:23 - | -LL | async fn ft1(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` - -error[E0053]: method `ft5` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:34:48 - | -LL | const async unsafe extern "C" fn ft5() {} - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:21:47 - | -LL | const async unsafe extern "C" fn ft5(); - | ^ - = note: expected fn pointer `unsafe extern "C" fn()` - found fn pointer `unsafe extern "C" fn() -> impl Future` - error[E0391]: cycle detected when computing type of `main::::ft5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:34:48 + --> $DIR/fn-header-semantic-fail.rs:33:48 | LL | const async unsafe extern "C" fn ft5() {} | ^ | note: ...which requires borrow-checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -288,30 +260,30 @@ LL | | } LL | | } | |_^ -error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:47:48 +error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:45:48 | LL | const async unsafe extern "C" fn fi5() {} | ^ | -note: ...which requires borrow-checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires borrow-checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires processing `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires const checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `impl core::future::future::Future` is freeze... = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... - = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle + = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 | @@ -324,7 +296,7 @@ LL | | } LL | | } | |_^ -error: aborting due to 23 previous errors +error: aborting due to 21 previous errors -Some errors have detailed explanations: E0053, E0379, E0391, E0706. -For more information about an error, try `rustc --explain E0053`. +Some errors have detailed explanations: E0379, E0391, E0706. +For more information about an error, try `rustc --explain E0379`. diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs index aaf0f7eaef0dc..49462f52fb4c2 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs @@ -14,7 +14,6 @@ trait B { impl B for A { async fn associated(); //~ ERROR without body //~^ ERROR cannot be declared `async` - //~| ERROR has an incompatible type for trait } fn main() {} diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index d3214458eac13..55c3b66f1363d 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -14,17 +14,6 @@ LL | async fn inherent(); | | | help: provide a definition for the function: `{ }` -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5 - | -LL | async fn associated(); - | -----^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: associated function in `impl` without body --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 | @@ -34,7 +23,7 @@ LL | async fn associated(); | help: provide a definition for the function: `{ }` error[E0706]: functions in traits cannot be declared `async` - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5 | LL | async fn associated(); | -----^^^^^^^^^^^^^^^^^ @@ -43,26 +32,22 @@ LL | async fn associated(); | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0053]: method `associated` has an incompatible type for trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26 +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 | LL | async fn associated(); - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26 + | -----^^^^^^^^^^^^^^^^^ + | | + | `async` because of this | -LL | async fn associated(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0053, E0706. -For more information about an error, try `rustc --explain E0053`. +For more information about this error, try `rustc --explain E0706`. diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs index b280c8ab6e2b2..94f578af209a8 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -12,7 +12,8 @@ impl A { trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 //~^ ERROR functions in traits cannot be declared `async` -//~^^ ERROR cannot find type `T` in this scope -//~^^^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] +//~| ERROR mismatched types +//~| ERROR cannot find type `T` in this scope +//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 50de2322907ed..9819f65013786 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:19:53 | LL | trait C{async fn new(val: T) {} | - unclosed delimiter @@ -25,17 +25,6 @@ LL | trait C{async fn new(val: T) {} = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 - | -LL | trait C{async fn new(val: T) {} - | -----^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0423]: expected function, found module `crate` --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5 | @@ -51,6 +40,19 @@ LL | pub struct A {} LL | trait C{async fn new(val: T) {} | ^ help: a struct with a similar name exists: `A` +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | -----^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57 | @@ -72,6 +74,20 @@ help: add a dummy let to cause `path` to be fully captured LL | async fn create(path: impl AsRef) { let _ = &path; | ++++++++++++++ +error[E0308]: mismatched types + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 + | +LL | trait C{async fn new(val: T) {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::new::{opaque#0}` + found opaque type `impl Future` + warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 | @@ -87,7 +103,7 @@ help: add a dummy let to cause `val` to be fully captured LL | trait C{async fn new(val: T) { let _ = &val;} | +++++++++++++ -error: aborting due to 6 previous errors; 2 warnings emitted +error: aborting due to 7 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0412, E0423, E0670, E0706. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0308, E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0308`. From 0e53c868f4e881b33b972b984be5a9ead63d9055 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 21:02:59 +0000 Subject: [PATCH 14/27] Deeply check that method signatures match, and allow for nested RPITITs --- compiler/rustc_ast_lowering/src/lib.rs | 9 +- compiler/rustc_middle/src/arena.rs | 2 + compiler/rustc_middle/src/query/mod.rs | 7 + compiler/rustc_middle/src/ty/mod.rs | 8 + compiler/rustc_middle/src/ty/util.rs | 7 + .../src/traits/project.rs | 13 +- .../rustc_typeck/src/check/compare_method.rs | 147 +++++++++++++----- compiler/rustc_typeck/src/check/mod.rs | 2 + compiler/rustc_typeck/src/collect.rs | 5 +- .../impl-trait/in-trait/deep-match-works.rs | 16 ++ src/test/ui/impl-trait/in-trait/deep-match.rs | 15 ++ .../ui/impl-trait/in-trait/deep-match.stderr | 20 +++ .../ui/impl-trait/in-trait/nested-rpitit.rs | 32 ++++ 13 files changed, 231 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/deep-match-works.rs create mode 100644 src/test/ui/impl-trait/in-trait/deep-match.rs create mode 100644 src/test/ui/impl-trait/in-trait/deep-match.stderr create mode 100644 src/test/ui/impl-trait/in-trait/nested-rpitit.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1c9ef12996e6c..15441c80fd4ae 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1334,10 +1334,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::InTrait => { self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { - lctx.lower_param_bounds( - bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Trait), - ) + lctx.lower_param_bounds(bounds, ImplTraitContext::InTrait) }) } ImplTraitContext::Universal => { @@ -1535,8 +1532,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::TyKind<'hir> { let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { - // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT - // FIXME(RPITIT): We _also_ should support this eventually let hir_bounds = lower_bounds(lctx); let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; let rpitit_item = hir::Item { @@ -2050,7 +2045,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound = lctx.lower_async_fn_output_type_to_future_bound( output, output.span(), - ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn), + ImplTraitContext::InTrait, ); arena_vec![lctx; bound] }); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 65d5f755f7248..9b1fedd0b533c 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -101,6 +101,8 @@ macro_rules! arena_types { [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>, + + [] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap>, ]); ) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8e7bacca262e1..0722040228618 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -161,6 +161,13 @@ rustc_queries! { separate_provide_extern } + query compare_predicates_and_trait_impl_trait_tys(key: DefId) + -> Result<&'tcx FxHashMap>, ErrorGuaranteed> + { + desc { "better description please" } + separate_provide_extern + } + query analysis(key: ()) -> Result<(), ErrorGuaranteed> { eval_always desc { "running analysis passes on this crate" } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ee4e8ff50f824..63107e648fba8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2458,6 +2458,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_const_default_method(self, def_id: DefId) -> bool { matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) } + + pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId { + while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn { + debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder); + def_id = self.parent(def_id); + } + def_id + } } /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a3837512bce26..0c73ae54bc31a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -651,6 +651,13 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } + pub fn bound_trait_impl_trait_tys( + self, + def_id: DefId, + ) -> ty::EarlyBinder>, ErrorGuaranteed>> { + ty::EarlyBinder(self.compare_predicates_and_trait_impl_trait_tys(def_id)) + } + pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder> { ty::EarlyBinder(self.fn_sig(def_id)) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0212d8ace941a..164fd0edd2f31 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1278,7 +1278,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( ) { let tcx = selcx.tcx(); if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { - let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id); + let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id); let trait_def_id = tcx.parent(trait_fn_def_id); let trait_substs = obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); @@ -2136,11 +2136,6 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( let impl_fn_def_id = leaf_def.item.def_id; let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); - let sig = tcx - .bound_fn_sig(impl_fn_def_id) - .map_bound(|fn_sig| tcx.liberate_late_bound_regions(impl_fn_def_id, fn_sig)) - .subst(tcx, impl_fn_substs); - let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, @@ -2177,7 +2172,11 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( selcx, obligation.param_env, cause.clone(), - sig.output(), + tcx.bound_trait_impl_trait_tys(impl_fn_def_id) + .map_bound(|tys| { + tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id]) + }) + .subst(tcx, impl_fn_substs), &mut obligations, ); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index e55f43994b9f3..da45469863e48 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1,18 +1,22 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; -use rustc_data_structures::fx::FxHashSet; +use hir::def_id::DefId; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::{self, DefIdTree}; +use rustc_middle::ty::{ + self, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, +}; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -64,10 +68,7 @@ pub(crate) fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) - { - return; - } + tcx.ensure().compare_predicates_and_trait_impl_trait_tys(impl_m.def_id); } /// This function is best explained by example. Consider a trait: @@ -136,13 +137,15 @@ pub(crate) fn compare_impl_method<'tcx>( /// /// Finally we register each of these predicates as an obligation and check that /// they hold. -fn compare_predicate_entailment<'tcx>( +pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, - impl_m: &ty::AssocItem, - impl_m_span: Span, - trait_m: &ty::AssocItem, - impl_trait_ref: ty::TraitRef<'tcx>, -) -> Result<(), ErrorGuaranteed> { + def_id: DefId, +) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { + let impl_m = tcx.opt_associated_item(def_id).unwrap(); + let impl_m_span = tcx.def_span(def_id); + let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); + let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap(); + let trait_to_impl_substs = impl_trait_ref.substs; // This node-id should be used for the `body_id` field on each @@ -161,6 +164,7 @@ fn compare_predicate_entailment<'tcx>( kind: impl_m.kind, }, ); + let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); // Create mapping from impl to placeholder. let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id); @@ -266,6 +270,13 @@ fn compare_predicate_entailment<'tcx>( let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig); + let mut collector = + ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id); + // FIXME(RPITIT): This should only be needed on the output type, but + // RPITIT placeholders shouldn't show up anywhere except for there, + // so I think this is fine. + let trait_sig = trait_sig.fold_with(&mut collector); + // Next, add all inputs and output as well-formed tys. Importantly, // we have to do this before normalization, since the normalized ty may // not contain the input parameters. See issue #87748. @@ -391,30 +402,6 @@ fn compare_predicate_entailment<'tcx>( return Err(diag.emit()); } - // Check that an impl's fn return satisfies the bounds of the - // FIXME(RPITIT): Generalize this to nested impl traits - if let ty::Projection(proj) = tcx.fn_sig(trait_m.def_id).skip_binder().output().kind() - && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder - { - let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); - - for (predicate, span) in tcx - .bound_explicit_item_bounds(proj.item_def_id) - .transpose_iter() - .map(|pred| pred.map_bound(|pred| *pred).subst(tcx, trait_to_placeholder_substs)) - { - ocx.register_obligation(traits::Obligation::new( - traits::ObligationCause::new( - return_span, - impl_m_hir_id, - ObligationCauseCode::BindingObligation(proj.item_def_id, span), - ), - param_env, - predicate, - )); - } - } - // Check that all obligations are satisfied by the implementation's // version. let errors = ocx.select_all_or_error(); @@ -435,10 +422,96 @@ fn compare_predicate_entailment<'tcx>( &outlives_environment, ); - Ok(()) + let mut collected_tys = FxHashMap::default(); + for (def_id, ty) in collector.types { + match infcx.fully_resolve(ty) { + Ok(ty) => { + collected_tys.insert(def_id, ty); + } + Err(err) => { + tcx.sess.delay_span_bug( + return_span, + format!("could not fully resolve: {ty} => {err:?}"), + ); + collected_tys.insert(def_id, tcx.ty_error()); + } + } + } + + Ok(&*tcx.arena.alloc(collected_tys)) }) } +struct ImplTraitInTraitCollector<'a, 'tcx> { + ocx: &'a ObligationCtxt<'a, 'tcx>, + types: FxHashMap>, + span: Span, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, +} + +impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> { + fn new( + ocx: &'a ObligationCtxt<'a, 'tcx>, + span: Span, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, + ) -> Self { + ImplTraitInTraitCollector { ocx, types: FxHashMap::default(), span, param_env, body_id } + } +} + +impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.ocx.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if let ty::Projection(proj) = ty.kind() + && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder + { + if let Some(ty) = self.types.get(&proj.item_def_id) { + return *ty; + } + //FIXME(RPITIT): Deny nested RPITIT in substs too + if proj.substs.has_escaping_bound_vars() { + bug!("FIXME(RPITIT): error here"); + } + // Replace with infer var + let infer_ty = self.ocx.infcx.next_ty_var(TypeVariableOrigin { + span: self.span, + kind: TypeVariableOriginKind::MiscVariable, + }); + self.types.insert(proj.item_def_id, infer_ty); + // Recurse into bounds + for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() { + let pred_span = pred.0.1; + + let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs); + let pred = pred.fold_with(self); + let pred = self.ocx.normalize( + ObligationCause::misc(self.span, self.body_id), + self.param_env, + pred, + ); + + self.ocx.register_obligation(traits::Obligation::new( + ObligationCause::new( + self.span, + self.body_id, + ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span), + ), + self.param_env, + pred, + )); + } + infer_ty + } else { + ty.super_fold_with(self) + } + } +} + fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 69eb34b5f802d..8811b38fc555a 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -132,6 +132,7 @@ use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; use self::coercion::DynamicCoerceMany; +use self::compare_method::compare_predicates_and_trait_impl_trait_tys; use self::region::region_scope_tree; pub use self::Expectation::*; @@ -249,6 +250,7 @@ pub fn provide(providers: &mut Providers) { used_trait_imports, check_mod_item_types, region_scope_tree, + compare_predicates_and_trait_impl_trait_tys, ..*providers }; } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 5429598871d99..e5e82a4ff6b01 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1602,7 +1602,10 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } ItemKind::ImplTraitPlaceholder(_) => { let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id(); - assert_eq!(tcx.def_kind(parent_id), DefKind::AssocFn); + assert!(matches!( + tcx.def_kind(parent_id), + DefKind::AssocFn | DefKind::ImplTraitPlaceholder + )); Some(parent_id) } _ => None, diff --git a/src/test/ui/impl-trait/in-trait/deep-match-works.rs b/src/test/ui/impl-trait/in-trait/deep-match-works.rs new file mode 100644 index 0000000000000..772da845ee1f7 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match-works.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> Wrapper { Wrapper(0) } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/deep-match.rs b/src/test/ui/impl-trait/in-trait/deep-match.rs new file mode 100644 index 0000000000000..5a220bc3f198a --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match.rs @@ -0,0 +1,15 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> i32 { 0 } + //~^ ERROR method `bar` has an incompatible type for trait +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/deep-match.stderr b/src/test/ui/impl-trait/in-trait/deep-match.stderr new file mode 100644 index 0000000000000..af449869cb356 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match.stderr @@ -0,0 +1,20 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/deep-match.rs:11:17 + | +LL | fn bar() -> i32 { 0 } + | ^^^ + | | + | expected struct `Wrapper`, found `i32` + | help: change the output type to match the trait: `Wrapper<_>` + | +note: type in trait + --> $DIR/deep-match.rs:7:17 + | +LL | fn bar() -> Wrapper; + | ^^^^^^^^^^^^^^^^^^^ + = note: expected fn pointer `fn() -> Wrapper<_>` + found fn pointer `fn() -> i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/impl-trait/in-trait/nested-rpitit.rs b/src/test/ui/impl-trait/in-trait/nested-rpitit.rs new file mode 100644 index 0000000000000..65285e3a3ccaf --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/nested-rpitit.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; +use std::ops::Deref; + +trait Foo { + fn bar(self) -> impl Deref; +} + +struct A; + +impl Foo for A { + fn bar(self) -> &'static str { + "Hello, world" + } +} + +struct B; + +impl Foo for B { + fn bar(self) -> Box { + Box::new(42) + } +} + +fn main() { + println!("Message for you: {:?}", &*A.bar()); + println!("Another for you: {:?}", &*B.bar()); +} From 2a4a0ecc672950f947ccfe2bd31ec14357cfe4c7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 6 Sep 2022 17:37:00 +0200 Subject: [PATCH 15/27] Handle generic parameters. --- compiler/rustc_ast_lowering/src/lib.rs | 120 ++++++------------ .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_hir/src/hir.rs | 19 +-- compiler/rustc_hir/src/intravisit.rs | 9 +- compiler/rustc_hir/src/target.rs | 9 +- compiler/rustc_hir_pretty/src/lib.rs | 4 - .../nice_region_error/static_impl_trait.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 - compiler/rustc_middle/src/hir/map/mod.rs | 18 ++- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_passes/src/dead.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 1 - compiler/rustc_privacy/src/lib.rs | 11 +- compiler/rustc_resolve/src/late/lifetimes.rs | 6 +- .../rustc_save_analysis/src/dump_visitor.rs | 2 +- compiler/rustc_save_analysis/src/sig.rs | 15 ++- .../src/traits/project.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 13 +- .../rustc_typeck/src/check/compare_method.rs | 27 +++- compiler/rustc_typeck/src/collect.rs | 25 ++-- .../rustc_typeck/src/collect/item_bounds.rs | 41 ++---- compiler/rustc_typeck/src/collect/type_of.rs | 11 +- src/librustdoc/clean/mod.rs | 12 +- src/librustdoc/visit_ast.rs | 1 - .../ui/impl-trait/in-trait/opaque-in-impl.rs | 36 +++++- 25 files changed, 170 insertions(+), 223 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 15441c80fd4ae..b133a3b94061e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -235,11 +235,10 @@ enum ImplTraitContext { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + in_trait: bool, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, - /// Return-position `impl Trait` in trait definition - InTrait, /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -1319,9 +1318,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => { - self.lower_opaque_impl_trait(span, *origin, def_node_id, bounds, itctx) - } + ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self + .lower_opaque_impl_trait( + span, + *origin, + def_node_id, + bounds, + *in_trait, + itctx, + ), ImplTraitContext::TypeAliasesOpaqueTy => { let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; self.lower_opaque_impl_trait( @@ -1329,14 +1334,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OpaqueTyOrigin::TyAlias, def_node_id, bounds, - &mut nested_itctx, + false, + nested_itctx, ) } - ImplTraitContext::InTrait => { - self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { - lctx.lower_param_bounds(bounds, ImplTraitContext::InTrait) - }) - } ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1406,6 +1407,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, bounds: &GenericBounds, + in_trait: bool, itctx: &mut ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. @@ -1494,6 +1496,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: hir_bounds, origin, + in_trait, }; debug!(?opaque_ty_item); @@ -1520,30 +1523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) - } - - #[instrument(level = "debug", skip(self, lower_bounds))] - fn lower_impl_trait_in_trait( - &mut self, - span: Span, - opaque_ty_node_id: NodeId, - lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, - ) -> hir::TyKind<'hir> { - let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); - self.with_hir_id_owner(opaque_ty_node_id, |lctx| { - let hir_bounds = lower_bounds(lctx); - let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; - let rpitit_item = hir::Item { - def_id: opaque_ty_def_id, - ident: Ident::empty(), - kind: hir::ItemKind::ImplTraitPlaceholder(rpitit_placeholder), - span: lctx.lower_span(span), - vis_span: lctx.lower_span(span.shrink_to_lo()), - }; - hir::OwnerNode::Item(lctx.arena.alloc(rpitit_item)) - }); - hir::TyKind::ImplTraitInTrait(hir::ItemId { def_id: opaque_ty_def_id }) + hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait) } /// Registers a new opaque type with the proper `NodeId`s and @@ -1704,30 +1684,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) .emit(); } - self.lower_async_fn_ret_ty_in_trait( + self.lower_async_fn_ret_ty( &decl.output, fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), ret_id, + true, ) } _ => { if !kind.impl_trait_return_allowed(self.tcx) { - if kind == FnDeclKind::Impl { - self.tcx - .sess - .create_feature_err( - TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, - ) - .emit(); - } else { - self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); - } + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); } self.lower_async_fn_ret_ty( &decl.output, fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), ret_id, + false, ) } } @@ -1739,10 +1717,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: false, } } - Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => { - ImplTraitContext::InTrait + Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => { + let fn_def_id = self.local_def_id(fn_node_id); + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: true, + } } _ => ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { @@ -1805,6 +1788,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output: &FnRetTy, fn_node_id: NodeId, opaque_ty_node_id: NodeId, + in_trait: bool, ) -> hir::FnRetTy<'hir> { let span = output.span(); @@ -1936,6 +1920,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait, }, ); @@ -1975,6 +1960,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: arena_vec![this; future_bound], origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + in_trait, }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -2020,41 +2006,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Foo = impl Trait` is, internally, created as a child of the // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. - let opaque_ty_ref = - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args); + let opaque_ty_ref = hir::TyKind::OpaqueDef( + hir::ItemId { def_id: opaque_ty_def_id }, + generic_args, + in_trait, + ); let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref); hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } - // Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }` - // combined with the following definition of `OpaqueTy`: - // - // type OpaqueTy = impl Future; - // - // `output`: unlowered output type (`T` in `-> T`) - // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) - // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created - #[instrument(level = "debug", skip(self))] - fn lower_async_fn_ret_ty_in_trait( - &mut self, - output: &FnRetTy, - fn_node_id: NodeId, - opaque_ty_node_id: NodeId, - ) -> hir::FnRetTy<'hir> { - let kind = self.lower_impl_trait_in_trait(output.span(), opaque_ty_node_id, |lctx| { - let bound = lctx.lower_async_fn_output_type_to_future_bound( - output, - output.span(), - ImplTraitContext::InTrait, - ); - arena_vec![lctx; bound] - }); - - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, output.span(), None); - let opaque_ty = self.ty(opaque_ty_span, kind); - hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) - } - /// Transforms `-> T` into `Future`. fn lower_async_fn_output_type_to_future_bound( &mut self, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 75fde53b6cdec..0707ff5ed02a0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -772,7 +772,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { let hir = self.infcx.tcx.hir(); - let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind else { + let hir::TyKind::OpaqueDef(id, _, _) = hir_ty.kind else { span_bug!( hir_ty.span, "lowered return type of async fn is not OpaqueDef: {:?}", diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ed31de61f7605..6fae1441f04a0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2476,6 +2476,7 @@ pub struct OpaqueTy<'hir> { pub generics: &'hir Generics<'hir>, pub bounds: GenericBounds<'hir>, pub origin: OpaqueTyOrigin, + pub in_trait: bool, } /// From whence the opaque type came. @@ -2489,12 +2490,6 @@ pub enum OpaqueTyOrigin { TyAlias, } -/// Placeholder representation of an `impl Trait` in a trait. Since this never gets lowered into a `ty::Opaque` of its own, we just keep this as -#[derive(Debug, HashStable_Generic)] -pub struct ImplTraitPlaceholder<'hir> { - pub bounds: GenericBounds<'hir>, -} - /// The various kinds of types recognized by the compiler. #[derive(Debug, HashStable_Generic)] pub enum TyKind<'hir> { @@ -2521,12 +2516,9 @@ pub enum TyKind<'hir> { /// /// The generic argument list contains the lifetimes (and in the future /// possibly parameters) that are actually bound on the `impl Trait`. - OpaqueDef(ItemId, &'hir [GenericArg<'hir>]), - /// A type that represents an `impl Trait` in a trait function. This is - /// not an opaque type, since it acts more like an associated type than - /// an opaque, and since it needs no generics since it inherits those - /// from the item's parent. - ImplTraitInTrait(ItemId), + /// + /// The last parameter specifies whether this opaque appears in a trait definition. + OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime, TraitObjectSyntax), @@ -2982,8 +2974,6 @@ pub enum ItemKind<'hir> { TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`. OpaqueTy(OpaqueTy<'hir>), - /// An `impl Trait` in a trait - ImplTraitPlaceholder(ImplTraitPlaceholder<'hir>), /// An enum definition, e.g., `enum Foo {C, D}`. Enum(EnumDef<'hir>, &'hir Generics<'hir>), /// A struct definition, e.g., `struct Foo {x: A}`. @@ -3052,7 +3042,6 @@ impl ItemKind<'_> { ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", ItemKind::Impl(..) => "implementation", - ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait", } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3e9ab10b1f7e3..bf4ab06638bb1 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -562,10 +562,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { walk_generics(visitor, generics); walk_list!(visitor, visit_param_bound, bounds); } - ItemKind::ImplTraitPlaceholder(ImplTraitPlaceholder { bounds }) => { - visitor.visit_id(item.hir_id()); - walk_list!(visitor, visit_param_bound, bounds); - } ItemKind::Enum(ref enum_definition, ref generics) => { visitor.visit_generics(generics); // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`. @@ -674,13 +670,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { TyKind::Path(ref qpath) => { visitor.visit_qpath(qpath, typ.hir_id, typ.span); } - TyKind::OpaqueDef(item_id, lifetimes) => { + TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { visitor.visit_nested_item(item_id); walk_list!(visitor, visit_generic_arg, lifetimes); } - TyKind::ImplTraitInTrait(item_id) => { - visitor.visit_nested_item(item_id); - } TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); visitor.visit_array_length(length) diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 0e9b05729d29e..5917d5e346e37 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -80,8 +80,13 @@ impl Target { ItemKind::ForeignMod { .. } => Target::ForeignMod, ItemKind::GlobalAsm(..) => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, - ItemKind::OpaqueTy(..) => Target::OpaqueTy, - ItemKind::ImplTraitPlaceholder(..) => Target::ImplTraitPlaceholder, + ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + Target::ImplTraitPlaceholder + } else { + Target::OpaqueTy + } + } ItemKind::Enum(..) => Target::Enum, ItemKind::Struct(..) => Target::Struct, ItemKind::Union(..) => Target::Union, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a86aec4df58d1..1220755f44b30 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -327,7 +327,6 @@ impl<'a> State<'a> { self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names); } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), - hir::TyKind::ImplTraitInTrait(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { @@ -609,9 +608,6 @@ impl<'a> State<'a> { state.print_bounds("= impl", real_bounds); }); } - hir::ItemKind::ImplTraitPlaceholder(..) => { - unreachable!("FIXME(RPITIT): I don't think this ever gets called here..."); - } hir::ItemKind::Enum(ref enum_definition, params) => { self.print_enum_def(enum_definition, params, item.ident.name, item.span); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index f804569b0747e..b115ac8b3df95 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -300,7 +300,7 @@ pub fn suggest_new_region_bound( continue; } match fn_return.kind { - TyKind::OpaqueDef(item_id, _) => { + TyKind::OpaqueDef(item_id, _, _) => { let item = tcx.hir().item(item_id); let ItemKind::OpaqueTy(opaque) = &item.kind else { return; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ff321ec5ef02d..5a1a3488cc252 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1498,9 +1498,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); } - hir::ItemKind::ImplTraitPlaceholder(..) => { - self.encode_explicit_item_bounds(def_id); - } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1a0bea68293e7..5a65ec9a4765a 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -212,8 +212,13 @@ impl<'hir> Map<'hir> { ItemKind::Fn(..) => DefKind::Fn, ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, - ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, - ItemKind::ImplTraitPlaceholder(..) => DefKind::ImplTraitPlaceholder, + ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + DefKind::ImplTraitPlaceholder + } else { + DefKind::OpaqueTy + } + } ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, @@ -1188,8 +1193,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::ForeignMod { .. } => "foreign mod", ItemKind::GlobalAsm(..) => "global asm", ItemKind::TyAlias(..) => "ty", - ItemKind::OpaqueTy(..) => "opaque type", - ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait", + ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + "opaque type in trait" + } else { + "opaque type" + } + } ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index dd2f43210603a..d8ce96bad663e 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -396,7 +396,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { ) => { self.0.push(ty); } - hir::TyKind::OpaqueDef(item_id, _) => { + hir::TyKind::OpaqueDef(item_id, _, _) => { self.0.push(ty); let item = self.1.item(item_id); hir::intravisit::walk_item(self, item); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 625c854ea77a5..2191e3befb8cf 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -450,7 +450,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { } fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - if let TyKind::OpaqueDef(item_id, _) = ty.kind { + if let TyKind::OpaqueDef(item_id, _, _) = ty.kind { let item = self.tcx.hir().item(item_id); intravisit::walk_item(self, item); } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 74c5ccf9cd205..f7e3fac6b2e20 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -235,7 +235,6 @@ impl<'tcx> ReachableContext<'tcx> { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4c7837aa5e8fc..3cdb596c01605 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -690,7 +690,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) @@ -712,12 +711,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::OpaqueTy(..) => { + hir::ItemKind::OpaqueTy(ref opaque) => { // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general) // Since rustdoc never needs to do codegen and doesn't care about link-time reachability, // mark this as unreachable. // See https://github.com/rust-lang/rust/issues/75100 - if !self.tcx.sess.opts.actually_rustdoc { + if !opaque.in_trait && !self.tcx.sess.opts.actually_rustdoc { // FIXME: This is some serious pessimization intended to workaround deficiencies // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time // reachable if they are returned via `impl Trait`, even from private functions. @@ -726,9 +725,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { self.reach(item.def_id, exist_level).generics().predicates().ty(); } } - hir::ItemKind::ImplTraitPlaceholder(..) => { - // FIXME(RPITIT): Do we need to do anything here? - } // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) @@ -2041,8 +2037,7 @@ fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility { // query failing on some items, we provide it for opaque types as well. | Node::Item(hir::Item { kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..), + | hir::ItemKind::OpaqueTy(..), .. }) => ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id()), // Visibilities of trait impl items are inherited from their traits diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index e9e4f8fc483c5..6ff56f9a89114 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -596,10 +596,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } } - hir::ItemKind::ImplTraitPlaceholder(..) => { - // FIXME(RPITIT): We don't need to do anything special here, right? - intravisit::walk_item(self, item); - } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) | hir::ItemKind::Struct(_, ref generics) @@ -719,7 +715,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.with(scope, |this| this.visit_ty(&mt.ty)); } - hir::TyKind::OpaqueDef(item_id, lifetimes) => { + hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { // Resolve the lifetimes in the bounds to the lifetime defs in the generics. // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to // `type MyAnonTy<'b> = impl MyTrait<'b>;` diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 6658892881d4b..94f222251d3dc 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1321,7 +1321,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { }), } } - hir::TyKind::OpaqueDef(item_id, _) => { + hir::TyKind::OpaqueDef(item_id, _, _) => { let item = self.tcx.hir().item(item_id); self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item)); } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index ea9c82b3597d0..bae1828cd182d 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -316,11 +316,7 @@ impl<'hir> Sig for hir::Ty<'hir> { let text = format!("[{}; {}]", nested_ty.text, expr); Ok(replace_text(nested_ty, text)) } - hir::TyKind::OpaqueDef(item_id, _) => { - let item = scx.tcx.hir().item(item_id); - item.make(offset, Some(item_id.hir_id()), scx) - } - hir::TyKind::ImplTraitInTrait(item_id) => { + hir::TyKind::OpaqueDef(item_id, _, _) => { let item = scx.tcx.hir().item(item_id); item.make(offset, Some(item_id.hir_id()), scx) } @@ -565,8 +561,13 @@ impl<'hir> Sig for hir::Item<'hir> { hir::ItemKind::ForeignMod { .. } => Err("extern mod"), hir::ItemKind::GlobalAsm(_) => Err("global asm"), hir::ItemKind::ExternCrate(_) => Err("extern crate"), - hir::ItemKind::OpaqueTy(..) => Err("opaque type"), - hir::ItemKind::ImplTraitPlaceholder(..) => Err("opaque type in trait"), + hir::ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + Err("opaque type in trait") + } else { + Err("opaque type") + } + } // FIXME should implement this (e.g., pub use). hir::ItemKind::Use(..) => Err("import"), } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 164fd0edd2f31..e962b3a9df2b3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2125,7 +2125,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( let tcx = selcx.tcx(); let mut obligations = data.nested; - let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id); + let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id); let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else { return Progress { term: tcx.ty_error().into(), obligations }; }; diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index d0a74c6c147cb..2f02bcd99f7da 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2360,7 +2360,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let span = path.span; match path.res { - Res::Def(DefKind::OpaqueTy, did) => { + Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => { // Check for desugared `impl Trait`. assert!(ty::is_impl_trait_defn(tcx, did).is_none()); let item_segment = path.segments.split_last().unwrap(); @@ -2627,21 +2627,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself)); self.res_to_ty(opt_self_ty, path, false) } - hir::TyKind::OpaqueDef(item_id, lifetimes) => { + hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => { let opaque_ty = tcx.hir().item(item_id); let def_id = item_id.def_id.to_def_id(); match opaque_ty.kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - self.impl_trait_ty_to_ty(def_id, lifetimes, origin) + self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait) } ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } - hir::TyKind::ImplTraitInTrait(item_id) => { - let def_id = item_id.def_id.to_def_id(); - tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id)) - } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); let ty = self.ast_ty_to_ty_inner(qself, false, true); @@ -2707,6 +2703,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id: DefId, lifetimes: &[hir::GenericArg<'_>], origin: OpaqueTyOrigin, + in_trait: bool, ) -> Ty<'tcx> { debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes); let tcx = self.tcx(); @@ -2750,7 +2747,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); debug!("impl_trait_ty_to_ty: substs={:?}", substs); - tcx.mk_opaque(def_id, substs) + if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) } } pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index da45469863e48..a6c8dbb2555dd 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -423,9 +423,28 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>( ); let mut collected_tys = FxHashMap::default(); - for (def_id, ty) in collector.types { + for (def_id, (ty, substs)) in collector.types { match infcx.fully_resolve(ty) { Ok(ty) => { + // `ty` contains free regions that we created earlier while liberating the + // trait fn signature. However, projection normalization expects `ty` to + // contains `def_id`'s early-bound regions. + let id_substs = InternalSubsts::identity_for_item(tcx, def_id); + debug!(?id_substs, ?substs); + let map: FxHashMap, ty::GenericArg<'tcx>> = substs + .iter() + .enumerate() + .map(|(index, arg)| (arg, id_substs[index])) + .collect(); + debug!(?map); + + let ty = tcx.fold_regions(ty, |region, _| { + if let ty::ReFree(_) = region.kind() { + map[®ion.into()].expect_region() + } else { + region + } + }); collected_tys.insert(def_id, ty); } Err(err) => { @@ -444,7 +463,7 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>( struct ImplTraitInTraitCollector<'a, 'tcx> { ocx: &'a ObligationCtxt<'a, 'tcx>, - types: FxHashMap>, + types: FxHashMap, ty::SubstsRef<'tcx>)>, span: Span, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, @@ -470,7 +489,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { if let ty::Projection(proj) = ty.kind() && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder { - if let Some(ty) = self.types.get(&proj.item_def_id) { + if let Some((ty, _)) = self.types.get(&proj.item_def_id) { return *ty; } //FIXME(RPITIT): Deny nested RPITIT in substs too @@ -482,7 +501,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { span: self.span, kind: TypeVariableOriginKind::MiscVariable, }); - self.types.insert(proj.item_def_id, infer_ty); + self.types.insert(proj.item_def_id, (infer_ty, proj.substs)); // Recurse into bounds for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() { let pred_span = pred.0.1; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e5e82a4ff6b01..ceb5684fdf0a8 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -815,11 +815,6 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().predicates_of(def_id); tcx.ensure().explicit_item_bounds(def_id); } - hir::ItemKind::ImplTraitPlaceholder(..) => { - tcx.ensure().generics_of(def_id); - tcx.ensure().predicates_of(def_id); - tcx.ensure().explicit_item_bounds(def_id); - } hir::ItemKind::TyAlias(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) @@ -1590,8 +1585,16 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + in_trait, .. - }) => Some(fn_def_id.to_def_id()), + }) => { + if in_trait { + assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn)) + } else { + assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn)) + } + Some(fn_def_id.to_def_id()) + } ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { let parent_id = tcx.hir().get_parent_item(hir_id); assert_ne!(parent_id, CRATE_DEF_ID); @@ -1600,14 +1603,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // inherit the generics of the item. Some(parent_id.to_def_id()) } - ItemKind::ImplTraitPlaceholder(_) => { - let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id(); - assert!(matches!( - tcx.def_kind(parent_id), - DefKind::AssocFn | DefKind::ImplTraitPlaceholder - )); - Some(parent_id) - } _ => None, }, _ => None, @@ -1800,7 +1795,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { } Tup(tys) => tys.iter().any(is_suggestable_infer_ty), Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), - OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args), + OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args), Path(hir::QPath::TypeRelative(ty, segment)) => { is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args) } diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index fe8d8f54f0477..0d34a8bfee333 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -59,10 +59,15 @@ fn opaque_type_bounds<'tcx>( opaque_def_id: DefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, + in_trait: bool, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries!({ - let item_ty = - tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); + let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id); + let item_ty = if in_trait { + tcx.mk_projection(opaque_def_id, substs) + } else { + tcx.mk_opaque(opaque_def_id, substs) + }; let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); @@ -74,29 +79,6 @@ fn opaque_type_bounds<'tcx>( }) } -/// Opaque types don't inherit bounds from their parent: for return position -/// impl trait it isn't possible to write a suitable predicate on the -/// containing function and for type-alias impl trait we don't have a backwards -/// compatibility issue. -fn impl_trait_in_trait_item_bounds<'tcx>( - tcx: TyCtxt<'tcx>, - opaque_def_id: DefId, - ast_bounds: &'tcx [hir::GenericBound<'tcx>], - span: Span, -) -> &'tcx [(ty::Predicate<'tcx>, Span)] { - ty::print::with_no_queries!({ - // FIXME(RPITIT): DRY-er code please - let item_ty = - tcx.mk_projection(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); - - let icx = ItemCtxt::new(tcx, opaque_def_id); - let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); - // RPITITs are implicitly sized unless a `?Sized` bound is found - >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); - tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) - }) -} - pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: DefId, @@ -109,15 +91,10 @@ pub(super) fn explicit_item_bounds( .. }) => associated_type_bounds(tcx, def_id, bounds, *span), hir::Node::Item(hir::Item { - kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }), - span, - .. - }) => opaque_type_bounds(tcx, def_id, bounds, *span), - hir::Node::Item(hir::Item { - kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }), + kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }), span, .. - }) => impl_trait_in_trait_item_bounds(tcx, def_id, bounds, *span), + }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait), _ => bug!("item_bounds called on {:?}", def_id), } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index ded2ac1308e54..a26e26cb38996 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -333,11 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { find_opaque_ty_constraints_for_tait(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { - find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) - } - ItemKind::ImplTraitPlaceholder(..) => { - span_bug!(item.span, "not yet implemented") + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => { + if in_trait { + span_bug!(item.span, "impl-trait in trait has no default") + } else { + find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) + } } ItemKind::Trait(..) | ItemKind::TraitAlias(..) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2be89a0fb370f..86571ccd2e102 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1492,7 +1492,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T Array(Box::new(clean_ty(ty, cx)), length) } TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), - TyKind::OpaqueDef(item_id, _) => { + TyKind::OpaqueDef(item_id, _, _) => { let item = cx.tcx.hir().item(item_id); if let hir::ItemKind::OpaqueTy(ref ty) = item.kind { ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) @@ -1500,16 +1500,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T unreachable!() } } - TyKind::ImplTraitInTrait(item_id) => { - let item = cx.tcx.hir().item(item_id); - if let hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }) = - item.kind - { - ImplTrait(bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) - } else { - unreachable!() - } - } TyKind::Path(_) => clean_qpath(ty, cx), TyKind::TraitObject(bounds, ref lifetime, _) => { let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect(); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 7fe391f420f6a..ca7a20bf3688a 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -362,7 +362,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Union(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)), diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs index a777cbcd529a6..2e06629699aad 100644 --- a/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -3,18 +3,46 @@ #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] -use std::fmt::Display; +use std::fmt::Debug; trait Foo { - fn bar(&self) -> impl Display; + fn foo(&self) -> impl Debug; } impl Foo for () { - fn bar(&self) -> impl Display { + fn foo(&self) -> impl Debug { "Hello, world" } } +impl Foo for std::marker::PhantomData { + fn foo(&self) -> impl Debug { + T::default() + } +} + +trait Bar { + fn bar(&self) -> impl Debug; +} + +impl Bar for () { + fn bar(&self) -> impl Debug { + format!("Hello with generic {}", std::any::type_name::()) + } +} + +trait Baz { + fn baz(&self) -> impl Debug + '_; +} + +impl Baz for String { + fn baz(&self) -> impl Debug + '_ { + (self,) + } +} + fn main() { - println!("{}", ().bar()); + println!("{:?}", ().foo()); + println!("{:?}", ().bar::()); + println!("{:?}", "hi".to_string().baz()); } From 8bf0bab43230c49f71a28641bd63c672814e4a81 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Sep 2022 17:16:08 +0000 Subject: [PATCH 16/27] Tweak feature error, add test --- compiler/rustc_ast_lowering/src/lib.rs | 32 ++++++++++++++----- src/test/ui/async-await/async-trait-fn.stderr | 2 +- ...return_position_impl_trait_in_trait.stderr | 3 ++ src/test/ui/impl-trait/in-trait/reveal.rs | 18 +++++++++++ src/test/ui/impl-trait/where-allowed.stderr | 6 ++++ 5 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/reveal.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b133a3b94061e..b41d04a55f2e3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -295,7 +295,7 @@ impl std::fmt::Display for ImplTraitPosition { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] enum FnDeclKind { Fn, Inherent, @@ -1349,6 +1349,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } + ImplTraitContext::Disallowed( + position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), + ) => { + self.tcx.sess.create_feature_err( + MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }, + sym::return_position_impl_trait_in_trait, + ).emit(); + hir::TyKind::Err + } ImplTraitContext::Disallowed(position) => { self.tcx.sess.emit_err(MisplacedImplTrait { span: t.span, @@ -1693,13 +1705,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => { if !kind.impl_trait_return_allowed(self.tcx) { - self.tcx - .sess - .create_feature_err( - TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, - ) - .emit(); + if kind == FnDeclKind::Impl { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } else { + self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); + } } self.lower_async_fn_ret_ty( &decl.output, diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index e30dfb1e1a705..6c17077d90b95 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -62,7 +62,7 @@ LL | async fn bar(&self) {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::bar::{opaque#0}` + = note: expected associated type `::bar::{opaque#0}<'_>` found opaque type `impl Future` error[E0308]: mismatched types diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr index a41f5789fdbfa..36177bbe15830 100644 --- a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -3,6 +3,9 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t | LL | fn bar() -> impl Sized; | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/impl-trait/in-trait/reveal.rs b/src/test/ui/impl-trait/in-trait/reveal.rs new file mode 100644 index 0000000000000..d6ede1cc495c6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/reveal.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn f() -> Box; +} + +impl Foo for () { + fn f() -> Box { + Box::new(String::new()) + } +} + +fn main() { + let x: Box = <() as Foo>::f(); +} diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 58a2f79efb4c6..9b346387d6106 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -162,12 +162,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return --> $DIR/where-allowed.rs:125:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param --> $DIR/where-allowed.rs:138:33 From 815f5b213cfa670af5ac7c5da01f9244be212633 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Sep 2022 17:27:47 +0000 Subject: [PATCH 17/27] Appease clippy again --- compiler/rustc_ast_lowering/src/lib.rs | 17 ++++++++++------- .../clippy/clippy_lints/src/dereference.rs | 2 +- src/tools/clippy/clippy_lints/src/lifetimes.rs | 2 +- .../clippy/clippy_lints/src/manual_async_fn.rs | 2 +- .../clippy/clippy_lints/src/missing_doc.rs | 3 +-- .../clippy/clippy_lints/src/missing_inline.rs | 1 - src/tools/clippy/clippy_utils/src/hir_utils.rs | 6 ++---- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b41d04a55f2e3..fc9033e73dbe7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1352,13 +1352,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed( position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), ) => { - self.tcx.sess.create_feature_err( - MisplacedImplTrait { - span: t.span, - position: DiagnosticArgFromDisplay(&position), - }, - sym::return_position_impl_trait_in_trait, - ).emit(); + self.tcx + .sess + .create_feature_err( + MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); hir::TyKind::Err } ImplTraitContext::Disallowed(position) => { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 09a073f4234d0..d1ab7fb67962e 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -959,7 +959,7 @@ fn binding_ty_auto_deref_stability<'tcx>( )) .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), ), - TyKind::OpaqueDef(..) | TyKind::ImplTraitInTrait(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { + TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { Position::ReborrowStable(precedence) }, }; diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 573a7c016b8e8..5995675bd969c 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -441,7 +441,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty<'_>) { match ty.kind { - TyKind::OpaqueDef(item, bounds) => { + TyKind::OpaqueDef(item, bounds, _) => { let map = self.cx.tcx.hir(); let item = map.item(item); let len = self.lts.len(); diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 2502c8f880ddc..754b0e78a148c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -103,7 +103,7 @@ fn future_trait_ref<'tcx>( ty: &'tcx Ty<'tcx>, ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { if_chain! { - if let TyKind::OpaqueDef(item_id, bounds) = ty.kind; + if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind; let item = cx.tcx.hir().item(item_id); if let ItemKind::OpaqueTy(opaque) = &item.kind; if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 9f518c7aaa39f..3701fdb4adbff 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -147,8 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::TraitAlias(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) => {}, + | hir::ItemKind::OpaqueTy(..) => {}, hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 9fd1a475d7496..07bc2ca5d3cd2 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -128,7 +128,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Impl { .. } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 6e4451e96120e..f972106168ade 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -987,12 +987,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, TyKind::Path(ref qpath) => self.hash_qpath(qpath), - TyKind::OpaqueDef(_, arg_list) => { + TyKind::OpaqueDef(_, arg_list, in_trait) => { self.hash_generic_args(arg_list); + in_trait.hash(&mut self.s); }, - TyKind::ImplTraitInTrait(_) => { - // Do nothing - } TyKind::TraitObject(_, lifetime, _) => { self.hash_lifetime(*lifetime); }, From 1c052058522c0b9e8c92fac322ca5ca3ea246c51 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 8 Sep 2022 00:26:01 +0000 Subject: [PATCH 18/27] Rebase fallout --- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index fc9033e73dbe7..0028199f97a61 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1327,17 +1327,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { *in_trait, itctx, ), - ImplTraitContext::TypeAliasesOpaqueTy => { - let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; - self.lower_opaque_impl_trait( - span, - hir::OpaqueTyOrigin::TyAlias, - def_node_id, - bounds, - false, - nested_itctx, - ) - } + ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait( + span, + hir::OpaqueTyOrigin::TyAlias, + def_node_id, + bounds, + false, + &mut ImplTraitContext::TypeAliasesOpaqueTy, + ), ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); From 09430b78e9fb53ae16ce3d0b5cb5045a40166166 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 8 Sep 2022 00:45:09 +0000 Subject: [PATCH 19/27] Adjust pretty printing of RPITITs --- .../rustc_infer/src/infer/error_reporting/mod.rs | 14 ++++++++++++++ compiler/rustc_middle/src/ty/print/pretty.rs | 8 +++++++- src/test/ui/async-await/async-trait-fn.stderr | 12 ++++++------ .../async-await/edition-deny-async-fns-2015.stderr | 4 ++-- ...2021-incompatible-closure-captures-93117.stderr | 4 ++-- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 0196bd262179e..95a36dd8a56a5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -61,6 +61,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::Node; @@ -1682,6 +1683,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pos.col.to_usize() + 1, ) } + (true, ty::Projection(proj)) + if self.tcx.def_kind(proj.item_def_id) + == DefKind::ImplTraitPlaceholder => + { + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo()); + format!( + " (trait associated opaque type at <{}:{}:{}>)", + sm.filename_for_diagnostics(&pos.file.name), + pos.line, + pos.col.to_usize() + 1, + ) + } (true, _) => format!(" ({})", ty.sort_string(self.tcx)), (false, _) => "".to_string(), }; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1ae3063dae4e7..f134e2cd1bc65 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -632,7 +632,13 @@ pub trait PrettyPrinter<'tcx>: ty::Foreign(def_id) => { p!(print_def_path(def_id, &[])); } - ty::Projection(ref data) => p!(print(data)), + ty::Projection(ref data) => { + if self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder { + return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs); + } else { + p!(print(data)) + } + } ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), ty::Opaque(def_id, substs) => { // FIXME(eddyb) print this with `print_def_path`. diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index 6c17077d90b95..e5c584e31e815 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -48,8 +48,8 @@ LL | async fn foo() {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::foo::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:3:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error[E0308]: mismatched types --> $DIR/async-trait-fn.rs:5:25 @@ -62,8 +62,8 @@ LL | async fn bar(&self) {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::bar::{opaque#0}<'_>` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:5:25>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error[E0308]: mismatched types --> $DIR/async-trait-fn.rs:7:20 @@ -81,8 +81,8 @@ LL | | } LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::baz::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:7:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error: aborting due to 6 previous errors diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index 2f40ef1ccbb14..8c2902d9b00d1 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -103,8 +103,8 @@ LL | async fn foo() {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::foo::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/edition-deny-async-fns-2015.rs:18:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error: aborting due to 11 previous errors diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 9819f65013786..3814c568e72c1 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -85,8 +85,8 @@ LL | trait C{async fn new(val: T) {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::new::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 From 60b49581c4bbbb94967f5ac170bf6152e4eba5cf Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Fri, 26 Aug 2022 16:06:27 +0200 Subject: [PATCH 20/27] translations(rustc_session): migrates session.rs and config.rs --- .../locales/en-US/session.ftl | 26 ++++ compiler/rustc_session/src/config.rs | 3 +- compiler/rustc_session/src/errors.rs | 69 ++++++++++- compiler/rustc_session/src/session.rs | 114 ++++++++++++------ 4 files changed, 174 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 983e5cee8237d..998196403e744 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -14,3 +14,29 @@ session_feature_diagnostic_for_issue = session_feature_diagnostic_help = add `#![feature({$feature})]` to the crate attributes to enable + +session_target_data_layout_parse_error = {$err} + +session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine + +session_profile_use_file_does_not_exist = File `{$path}` passed to `-C profile-use` does not exist. + +session_linker_plugin_lto_windows_not_supported = Linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets" + +session_profile_sample_use_file_does_not_exist = File `{$path}` passed to `-C profile-sample-use` does not exist. + +session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`." + +session_sanitizer_not_supported = {$us} sanitizer is not supported for this target + +session_sanitizers_not_supported = {$us} sanitizers are not supported for this target + +session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}` + +session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` + +session_sanitizer_cfi_enabled = `-Zsanitizer=cfi` requires `-Clto` + +session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` + +session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5 diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 04bd685f19001..0018346c72c49 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1,6 +1,7 @@ //! Contains infrastructure for configuring the compiler, including parsing //! command-line options. +use crate::errors::TargetDataLayoutParseError; pub use crate::options::*; use crate::search_paths::SearchPath; @@ -898,7 +899,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { let max_atomic_width = sess.target.max_atomic_width(); let atomic_cas = sess.target.atomic_cas; let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| { - sess.fatal(&err); + sess.emit_fatal(TargetDataLayoutParseError { err }); }); let mut ret = CrateConfig::default(); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 7252f1799dac1..7aa8d66824103 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,7 +1,7 @@ use std::num::NonZeroU32; -use crate as rustc_session; use crate::cgu_reuse_tracker::CguReuse; +use crate::{self as rustc_session}; use rustc_errors::MultiSpan; use rustc_macros::SessionDiagnostic; use rustc_span::{Span, Symbol}; @@ -43,3 +43,70 @@ pub struct FeatureDiagnosticForIssue { pub struct FeatureDiagnosticHelp { pub feature: Symbol, } + +#[derive(SessionDiagnostic)] +#[diag(session::target_data_layout_parse_error)] +pub struct TargetDataLayoutParseError { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(session::not_circumvent_feature)] +pub struct NotCircumventFeature; + +#[derive(SessionDiagnostic)] +#[diag(session::linker_plugin_lto_windows_not_supported)] +pub struct LinkerPluginToWindowsNotSupported; + +#[derive(SessionDiagnostic)] +#[diag(session::profile_use_file_does_not_exist)] +pub struct ProfileUseFileDoesNotExist<'a> { + pub path: &'a std::path::Path, +} + +#[derive(SessionDiagnostic)] +#[diag(session::profile_sample_use_file_does_not_exist)] +pub struct ProfileSampleUseFileDoesNotExist<'a> { + pub path: &'a std::path::Path, +} + +#[derive(SessionDiagnostic)] +#[diag(session::target_requires_unwind_tables)] +pub struct TargetRequiresUnwindTables; + +#[derive(SessionDiagnostic)] +#[diag(session::sanitizer_not_supported)] +pub struct SanitizerNotSupported { + pub us: String, +} + +#[derive(SessionDiagnostic)] +#[diag(session::sanitizers_not_supported)] +pub struct SanitizersNotSupported { + pub us: String, +} + +#[derive(SessionDiagnostic)] +#[diag(session::cannot_mix_and_match_sanitizers)] +pub struct CannotMixAndMatchSanitizers { + pub first: String, + pub second: String, +} + +#[derive(SessionDiagnostic)] +#[diag(session::cannot_enable_crt_static_linux)] +pub struct CannotEnableCrtStaticLinux; + +#[derive(SessionDiagnostic)] +#[diag(session::sanitizer_cfi_enabled)] +pub struct SanitizerCfiEnabled; + +#[derive(SessionDiagnostic)] +#[diag(session::unstable_virtual_function_elimination)] +pub struct UnstableVirtualFunctionElimination; + +#[derive(SessionDiagnostic)] +#[diag(session::unsupported_dwarf_version)] +pub struct UnsupportedDwarfVersion { + pub dwarf_version: u32, +} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 557edad548c64..4fe0e1de5b333 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -2,6 +2,12 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath}; +use crate::errors::{ + CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported, + NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, + SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, TargetRequiresUnwindTables, + UnstableVirtualFunctionElimination, UnsupportedDwarfVersion, +}; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; use crate::{filesearch, lint}; @@ -235,6 +241,9 @@ impl Session { if !unleashed_features.is_empty() { let mut must_err = false; // Create a diagnostic pointing at where things got unleashed. + // FIXME: We need to correctly migrate this. I couldn't find a way to migrate this. + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] let mut diag = self.struct_warn("skipping const checks"); for &(span, feature_gate) in unleashed_features.iter() { // FIXME: `span_label` doesn't do anything, so we use "help" as a hack. @@ -250,10 +259,7 @@ impl Session { // If we should err, make sure we did. if must_err && self.has_errors().is_none() { // We have skipped a feature gate, and not run into other errors... reject. - self.err( - "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \ - gates, except when testing error paths in the CTFE engine", - ); + self.emit_err(NotCircumventFeature); } } } @@ -290,6 +296,8 @@ impl Session { } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_warn>( &self, sp: S, @@ -298,6 +306,8 @@ impl Session { self.diagnostic().struct_span_warn(sp, msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_warn_with_expectation>( &self, sp: S, @@ -307,6 +317,8 @@ impl Session { self.diagnostic().struct_span_warn_with_expectation(sp, msg, id) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_warn_with_code>( &self, sp: S, @@ -316,6 +328,8 @@ impl Session { self.diagnostic().struct_span_warn_with_code(sp, msg, code) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn(msg) } @@ -328,6 +342,8 @@ impl Session { self.diagnostic().struct_warn_with_expectation(msg, id) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_allow>( &self, sp: S, @@ -336,10 +352,14 @@ impl Session { self.diagnostic().struct_span_allow(sp, msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_allow(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_allow(msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_expect( &self, msg: impl Into, @@ -348,6 +368,8 @@ impl Session { self.diagnostic().struct_expect(msg, id) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_err>( &self, sp: S, @@ -356,6 +378,8 @@ impl Session { self.diagnostic().struct_span_err(sp, msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_err_with_code>( &self, sp: S, @@ -366,6 +390,8 @@ impl Session { } // FIXME: This method should be removed (every error should have an associated error code). #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_err( &self, msg: impl Into, @@ -373,6 +399,8 @@ impl Session { self.parse_sess.struct_err(msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_err_with_code( &self, msg: impl Into, @@ -381,6 +409,8 @@ impl Session { self.diagnostic().struct_err_with_code(msg, code) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_warn_with_code( &self, msg: impl Into, @@ -389,6 +419,8 @@ impl Session { self.diagnostic().struct_warn_with_code(msg, code) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_fatal>( &self, sp: S, @@ -397,6 +429,8 @@ impl Session { self.diagnostic().struct_span_fatal(sp, msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_fatal_with_code>( &self, sp: S, @@ -406,15 +440,21 @@ impl Session { self.diagnostic().struct_span_fatal_with_code(sp, msg, code) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_fatal(msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_fatal>(&self, sp: S, msg: impl Into) -> ! { self.diagnostic().span_fatal(sp, msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_fatal_with_code>( &self, sp: S, @@ -424,10 +464,14 @@ impl Session { self.diagnostic().span_fatal_with_code(sp, msg, code) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn fatal(&self, msg: impl Into) -> ! { self.diagnostic().fatal(msg).raise() } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_err_or_warn>( &self, is_warning: bool, @@ -441,6 +485,8 @@ impl Session { } } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_err>( &self, sp: S, @@ -449,6 +495,8 @@ impl Session { self.diagnostic().span_err(sp, msg) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_err_with_code>( &self, sp: S, @@ -534,9 +582,13 @@ impl Session { Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) } } + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_warn>(&self, sp: S, msg: impl Into) { self.diagnostic().span_warn(sp, msg) } + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_warn_with_code>( &self, sp: S, @@ -585,6 +637,8 @@ impl Session { ) { self.diagnostic().span_note_without_error(sp, msg) } + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_note_without_error( &self, msg: impl Into, @@ -1469,40 +1523,28 @@ fn validate_commandline_args_with_session_available(sess: &Session) { && sess.opts.cg.prefer_dynamic && sess.target.is_like_windows { - sess.err( - "Linker plugin based LTO is not supported together with \ - `-C prefer-dynamic` when targeting Windows-like targets", - ); + sess.emit_err(LinkerPluginToWindowsNotSupported); } // Make sure that any given profiling data actually exists so LLVM can't // decide to silently skip PGO. if let Some(ref path) = sess.opts.cg.profile_use { if !path.exists() { - sess.err(&format!( - "File `{}` passed to `-C profile-use` does not exist.", - path.display() - )); + sess.emit_err(ProfileUseFileDoesNotExist { path }); } } // Do the same for sample profile data. if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use { if !path.exists() { - sess.err(&format!( - "File `{}` passed to `-C profile-sample-use` does not exist.", - path.display() - )); + sess.emit_err(ProfileSampleUseFileDoesNotExist { path }); } } // Unwind tables cannot be disabled if the target requires them. if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables { if sess.target.requires_uwtable && !include_uwtables { - sess.err( - "target requires unwind tables, they cannot be disabled with \ - `-C force-unwind-tables=no`.", - ); + sess.emit_err(TargetRequiresUnwindTables); } } @@ -1512,39 +1554,33 @@ fn validate_commandline_args_with_session_available(sess: &Session) { match unsupported_sanitizers.into_iter().count() { 0 => {} 1 => { - sess.err(&format!( - "{} sanitizer is not supported for this target", - unsupported_sanitizers - )); + sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() }); } _ => { - sess.err(&format!( - "{} sanitizers are not supported for this target", - unsupported_sanitizers - )); + sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() }); } } // Cannot mix and match sanitizers. let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter(); if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) { - sess.err(&format!("`-Zsanitizer={first}` is incompatible with `-Zsanitizer={second}`")); + sess.emit_err(CannotMixAndMatchSanitizers { + first: first.to_string(), + second: second.to_string(), + }); } // Cannot enable crt-static with sanitizers on Linux if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() { - sess.err( - "sanitizer is incompatible with statically linked libc, \ - disable it using `-C target-feature=-crt-static`", - ); + sess.emit_err(CannotEnableCrtStaticLinux); } // LLVM CFI and VFE both require LTO. if sess.lto() != config::Lto::Fat { if sess.is_sanitizer_cfi_enabled() { - sess.err("`-Zsanitizer=cfi` requires `-Clto`"); + sess.emit_err(SanitizerCfiEnabled); } if sess.opts.unstable_opts.virtual_function_elimination { - sess.err("`-Zvirtual-function-elimination` requires `-Clto`"); + sess.emit_err(UnstableVirtualFunctionElimination); } } @@ -1559,7 +1595,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version { if dwarf_version > 5 { - sess.err(&format!("requested DWARF version {} is greater than 5", dwarf_version)); + sess.emit_err(UnsupportedDwarfVersion { dwarf_version }); } } @@ -1614,14 +1650,20 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler rustc_errors::Handler::with_emitter(true, None, emitter) } +#[allow(rustc::untranslatable_diagnostic)] +#[allow(rustc::diagnostic_outside_of_impl)] pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed { early_error_handler(output).struct_err(msg).emit() } +#[allow(rustc::untranslatable_diagnostic)] +#[allow(rustc::diagnostic_outside_of_impl)] pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { early_error_handler(output).struct_fatal(msg).emit() } +#[allow(rustc::untranslatable_diagnostic)] +#[allow(rustc::diagnostic_outside_of_impl)] pub fn early_warn(output: config::ErrorOutputType, msg: &str) { early_error_handler(output).struct_warn(msg).emit() } From 0f06320c2491acc8cf9e61c976041785acb06aca Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Fri, 2 Sep 2022 19:29:52 +0200 Subject: [PATCH 21/27] translations(rustc_session): migrate TargetDataLayout::parse --- .../locales/en-US/session.ftl | 14 +++++ compiler/rustc_errors/src/diagnostic.rs | 2 + compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_session/src/errors.rs | 61 ++++++++++++++++-- compiler/rustc_target/src/abi/mod.rs | 63 +++++++++++-------- 5 files changed, 111 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 998196403e744..c5d23f2925011 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -40,3 +40,17 @@ session_sanitizer_cfi_enabled = `-Zsanitizer=cfi` requires `-Clto` session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5 + +session_target_invalid_address_space = invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err} + +session_target_invalid_bits = invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err} + +session_target_missing_alignment = missing alignment for `{$cause}` in "data-layout" + +session_target_invalid_alignment = invalid alignment for `{$cause}` in "data-layout": {$err} + +session_target_inconsistent_architecture = inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}` + +session_target_inconsistent_pointer_width = inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}` + +session_target_invalid_bits_size = {$err} diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a052aaee04756..b88292b893cea 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -14,6 +14,7 @@ use rustc_target::spec::PanicStrategy; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; +use std::num::ParseIntError; use std::path::{Path, PathBuf}; /// Error type for `Diagnostic`'s `suggestions` field, indicating that @@ -91,6 +92,7 @@ into_diagnostic_arg_using_display!( Edition, Ident, MacroRulesNormalizedIdent, + ParseIntError, ); impl IntoDiagnosticArg for bool { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 262d59f8ff8a7..583f682f568c3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -52,6 +52,7 @@ use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{CrateType, OutputFilenames}; use rustc_session::cstore::CrateStoreDyn; +use rustc_session::errors::TargetDataLayoutParseError; use rustc_session::lint::{Level, Lint}; use rustc_session::Limit; use rustc_session::Session; @@ -1251,7 +1252,7 @@ impl<'tcx> TyCtxt<'tcx> { output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { - s.fatal(&err); + s.emit_fatal(TargetDataLayoutParseError { err }); }); let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new( diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 7aa8d66824103..226e09589276f 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,10 +1,12 @@ use std::num::NonZeroU32; use crate::cgu_reuse_tracker::CguReuse; +use crate::parse::ParseSess; use crate::{self as rustc_session}; -use rustc_errors::MultiSpan; +use rustc_errors::{fluent, MultiSpan}; use rustc_macros::SessionDiagnostic; use rustc_span::{Span, Symbol}; +use rustc_target::abi::TargetDataLayoutErrors; #[derive(SessionDiagnostic)] #[diag(session::incorrect_cgu_reuse_type)] @@ -44,10 +46,59 @@ pub struct FeatureDiagnosticHelp { pub feature: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(session::target_data_layout_parse_error)] -pub struct TargetDataLayoutParseError { - pub err: String, +pub struct TargetDataLayoutParseError<'a> { + pub err: TargetDataLayoutErrors<'a>, +} + +impl crate::SessionDiagnostic<'_, !> for TargetDataLayoutParseError<'_> { + fn into_diagnostic(self, sess: &ParseSess) -> rustc_errors::DiagnosticBuilder<'_, !> { + let mut diag; + match self.err { + TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { + diag = sess.struct_fatal(fluent::session::target_invalid_address_space); + diag.set_arg("addr_space", addr_space); + diag.set_arg("cause", cause); + diag.set_arg("err", err); + diag + } + TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { + diag = sess.struct_fatal(fluent::session::target_invalid_bits); + diag.set_arg("kind", kind); + diag.set_arg("bit", bit); + diag.set_arg("cause", cause); + diag.set_arg("err", err); + diag + } + TargetDataLayoutErrors::MissingAlignment { cause } => { + diag = sess.struct_fatal(fluent::session::target_missing_alignment); + diag.set_arg("cause", cause); + diag + } + TargetDataLayoutErrors::InvalidAlignment { cause, err } => { + diag = sess.struct_fatal(fluent::session::target_invalid_alignment); + diag.set_arg("cause", cause); + diag.set_arg("err", err); + diag + } + TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { + diag = sess.struct_fatal(fluent::session::target_inconsistent_architecture); + diag.set_arg("dl", dl); + diag.set_arg("target", target); + diag + } + TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { + diag = sess.struct_fatal(fluent::session::target_inconsistent_pointer_width); + diag.set_arg("pointer_size", pointer_size); + diag.set_arg("target", target); + diag + } + TargetDataLayoutErrors::InvalidBitsSize { err } => { + diag = sess.struct_fatal(fluent::session::target_invalid_bits_size); + diag.set_arg("err", err); + diag + } + } + } } #[derive(SessionDiagnostic)] diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index bcaf209f84b65..ec334e5887ab7 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -7,7 +7,7 @@ use crate::spec::Target; use std::convert::{TryFrom, TryInto}; use std::fmt; use std::iter::Step; -use std::num::NonZeroUsize; +use std::num::{NonZeroUsize, ParseIntError}; use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub}; use std::str::FromStr; @@ -69,34 +69,46 @@ impl Default for TargetDataLayout { } } +pub enum TargetDataLayoutErrors<'a> { + InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError }, + InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError }, + MissingAlignment { cause: &'a str }, + InvalidAlignment { cause: &'a str, err: String }, + InconsistentTargetArchitecture { dl: &'a str, target: &'a str }, + InconsistentTargetPointerWidth { pointer_size: u64, target: u32 }, + InvalidBitsSize { err: String }, +} + impl TargetDataLayout { - pub fn parse(target: &Target) -> Result { + pub fn parse<'a>(target: &'a Target) -> Result> { // Parse an address space index from a string. - let parse_address_space = |s: &str, cause: &str| { + let parse_address_space = |s: &'a str, cause: &'a str| { s.parse::().map(AddressSpace).map_err(|err| { - format!("invalid address space `{}` for `{}` in \"data-layout\": {}", s, cause, err) + TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err } }) }; // Parse a bit count from a string. - let parse_bits = |s: &str, kind: &str, cause: &str| { - s.parse::().map_err(|err| { - format!("invalid {} `{}` for `{}` in \"data-layout\": {}", kind, s, cause, err) + let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| { + s.parse::().map_err(|err| TargetDataLayoutErrors::InvalidBits { + kind, + bit: s, + cause, + err, }) }; // Parse a size string. - let size = |s: &str, cause: &str| parse_bits(s, "size", cause).map(Size::from_bits); + let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); // Parse an alignment string. - let align = |s: &[&str], cause: &str| { + let align = |s: &[&'a str], cause: &'a str| { if s.is_empty() { - return Err(format!("missing alignment for `{}` in \"data-layout\"", cause)); + return Err(TargetDataLayoutErrors::MissingAlignment { cause }); } let align_from_bits = |bits| { - Align::from_bits(bits).map_err(|err| { - format!("invalid alignment for `{}` in \"data-layout\": {}", cause, err) - }) + Align::from_bits(bits) + .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err }) }; let abi = parse_bits(s[0], "alignment", cause)?; let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; @@ -158,25 +170,24 @@ impl TargetDataLayout { // Perform consistency checks against the Target information. if dl.endian != target.endian { - return Err(format!( - "inconsistent target specification: \"data-layout\" claims \ - architecture is {}-endian, while \"target-endian\" is `{}`", - dl.endian.as_str(), - target.endian.as_str(), - )); + return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture { + dl: dl.endian.as_str(), + target: target.endian.as_str(), + }); } let target_pointer_width: u64 = target.pointer_width.into(); if dl.pointer_size.bits() != target_pointer_width { - return Err(format!( - "inconsistent target specification: \"data-layout\" claims \ - pointers are {}-bit, while \"target-pointer-width\" is `{}`", - dl.pointer_size.bits(), - target.pointer_width - )); + return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth { + pointer_size: dl.pointer_size.bits(), + target: target.pointer_width, + }); } - dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?; + dl.c_enum_min_size = match Integer::from_size(Size::from_bits(target.c_enum_min_bits)) { + Ok(bits) => bits, + Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }), + }; Ok(dl) } From 24de9435e2d4efe2bde043f389579a72fb532c6f Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Mon, 5 Sep 2022 07:58:05 +0200 Subject: [PATCH 22/27] translations(rustc_session): remove lint allow rule to the methods marked with rustc_lint_diagnostic This commit removes the allows rules for the SessionDiagnostic lint that were being used in the session.rs file. Thanks to the PR #101230 we do not need to annotate the methods with the allow rule as they are part of the diagnostic machinery. --- .../locales/en-US/session.ftl | 8 ++-- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_session/src/config.rs | 3 +- compiler/rustc_session/src/errors.rs | 15 +++---- compiler/rustc_session/src/session.rs | 44 +------------------ 5 files changed, 12 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index c5d23f2925011..a9ed8b4835b77 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -19,13 +19,13 @@ session_target_data_layout_parse_error = {$err} session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine -session_profile_use_file_does_not_exist = File `{$path}` passed to `-C profile-use` does not exist. +session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist. -session_linker_plugin_lto_windows_not_supported = Linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets" +session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets -session_profile_sample_use_file_does_not_exist = File `{$path}` passed to `-C profile-sample-use` does not exist. +session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist. -session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`." +session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` session_sanitizer_not_supported = {$us} sanitizer is not supported for this target diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 583f682f568c3..ccdcf47b46885 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -52,7 +52,6 @@ use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{CrateType, OutputFilenames}; use rustc_session::cstore::CrateStoreDyn; -use rustc_session::errors::TargetDataLayoutParseError; use rustc_session::lint::{Level, Lint}; use rustc_session::Limit; use rustc_session::Session; @@ -1252,7 +1251,7 @@ impl<'tcx> TyCtxt<'tcx> { output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { - s.emit_fatal(TargetDataLayoutParseError { err }); + s.emit_fatal(err); }); let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new( diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0018346c72c49..8bb3878fbbb47 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1,7 +1,6 @@ //! Contains infrastructure for configuring the compiler, including parsing //! command-line options. -use crate::errors::TargetDataLayoutParseError; pub use crate::options::*; use crate::search_paths::SearchPath; @@ -899,7 +898,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { let max_atomic_width = sess.target.max_atomic_width(); let atomic_cas = sess.target.atomic_cas; let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| { - sess.emit_fatal(TargetDataLayoutParseError { err }); + sess.emit_fatal(err); }); let mut ret = CrateConfig::default(); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 226e09589276f..a4e13e22ae221 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,9 +1,8 @@ use std::num::NonZeroU32; use crate::cgu_reuse_tracker::CguReuse; -use crate::parse::ParseSess; -use crate::{self as rustc_session}; -use rustc_errors::{fluent, MultiSpan}; +use crate::{self as rustc_session, SessionDiagnostic}; +use rustc_errors::{fluent, DiagnosticBuilder, Handler, MultiSpan}; use rustc_macros::SessionDiagnostic; use rustc_span::{Span, Symbol}; use rustc_target::abi::TargetDataLayoutErrors; @@ -46,14 +45,10 @@ pub struct FeatureDiagnosticHelp { pub feature: Symbol, } -pub struct TargetDataLayoutParseError<'a> { - pub err: TargetDataLayoutErrors<'a>, -} - -impl crate::SessionDiagnostic<'_, !> for TargetDataLayoutParseError<'_> { - fn into_diagnostic(self, sess: &ParseSess) -> rustc_errors::DiagnosticBuilder<'_, !> { +impl SessionDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { + fn into_diagnostic(self, sess: &Handler) -> DiagnosticBuilder<'_, !> { let mut diag; - match self.err { + match self { TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { diag = sess.struct_fatal(fluent::session::target_invalid_address_space); diag.set_arg("addr_space", addr_space); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 4fe0e1de5b333..6add576cdff35 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -241,7 +241,7 @@ impl Session { if !unleashed_features.is_empty() { let mut must_err = false; // Create a diagnostic pointing at where things got unleashed. - // FIXME: We need to correctly migrate this. I couldn't find a way to migrate this. + // FIXME(#100717): needs eager translation/lists #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] let mut diag = self.struct_warn("skipping const checks"); @@ -296,8 +296,6 @@ impl Session { } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_warn>( &self, sp: S, @@ -306,8 +304,6 @@ impl Session { self.diagnostic().struct_span_warn(sp, msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_warn_with_expectation>( &self, sp: S, @@ -317,8 +313,6 @@ impl Session { self.diagnostic().struct_span_warn_with_expectation(sp, msg, id) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_warn_with_code>( &self, sp: S, @@ -328,8 +322,6 @@ impl Session { self.diagnostic().struct_span_warn_with_code(sp, msg, code) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn(msg) } @@ -342,8 +334,6 @@ impl Session { self.diagnostic().struct_warn_with_expectation(msg, id) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_allow>( &self, sp: S, @@ -352,14 +342,10 @@ impl Session { self.diagnostic().struct_span_allow(sp, msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_allow(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_allow(msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_expect( &self, msg: impl Into, @@ -368,8 +354,6 @@ impl Session { self.diagnostic().struct_expect(msg, id) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_err>( &self, sp: S, @@ -378,8 +362,6 @@ impl Session { self.diagnostic().struct_span_err(sp, msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_err_with_code>( &self, sp: S, @@ -390,8 +372,6 @@ impl Session { } // FIXME: This method should be removed (every error should have an associated error code). #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_err( &self, msg: impl Into, @@ -399,8 +379,6 @@ impl Session { self.parse_sess.struct_err(msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_err_with_code( &self, msg: impl Into, @@ -409,8 +387,6 @@ impl Session { self.diagnostic().struct_err_with_code(msg, code) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_warn_with_code( &self, msg: impl Into, @@ -419,8 +395,6 @@ impl Session { self.diagnostic().struct_warn_with_code(msg, code) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_fatal>( &self, sp: S, @@ -429,8 +403,6 @@ impl Session { self.diagnostic().struct_span_fatal(sp, msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_span_fatal_with_code>( &self, sp: S, @@ -440,21 +412,15 @@ impl Session { self.diagnostic().struct_span_fatal_with_code(sp, msg, code) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_fatal(msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_fatal>(&self, sp: S, msg: impl Into) -> ! { self.diagnostic().span_fatal(sp, msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_fatal_with_code>( &self, sp: S, @@ -464,14 +430,10 @@ impl Session { self.diagnostic().span_fatal_with_code(sp, msg, code) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn fatal(&self, msg: impl Into) -> ! { self.diagnostic().fatal(msg).raise() } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_err_or_warn>( &self, is_warning: bool, @@ -485,8 +447,6 @@ impl Session { } } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_err>( &self, sp: S, @@ -495,8 +455,6 @@ impl Session { self.diagnostic().span_err(sp, msg) } #[rustc_lint_diagnostics] - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_err_with_code>( &self, sp: S, From ddb225f1f57882c4f87d99d585fab982461d1fd9 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 7 Sep 2022 12:26:50 +0800 Subject: [PATCH 23/27] fixes #101477: Recover from typo where == is used in place of = --- .../locales/en-US/parser.ftl | 3 +++ compiler/rustc_parse/src/parser/diagnostics.rs | 16 ++++++++++++++++ src/test/ui/parser/issue-101477-enum.fixed | 10 ++++++++++ src/test/ui/parser/issue-101477-enum.rs | 10 ++++++++++ src/test/ui/parser/issue-101477-enum.stderr | 14 ++++++++++++++ src/test/ui/parser/issue-101477-let.fixed | 6 ++++++ src/test/ui/parser/issue-101477-let.rs | 6 ++++++ src/test/ui/parser/issue-101477-let.stderr | 8 ++++++++ 8 files changed, 73 insertions(+) create mode 100644 src/test/ui/parser/issue-101477-enum.fixed create mode 100644 src/test/ui/parser/issue-101477-enum.rs create mode 100644 src/test/ui/parser/issue-101477-enum.stderr create mode 100644 src/test/ui/parser/issue-101477-let.fixed create mode 100644 src/test/ui/parser/issue-101477-let.rs create mode 100644 src/test/ui/parser/issue-101477-let.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index bc17754c56ae3..f74df3d9746ae 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -153,3 +153,6 @@ parser_left_arrow_operator = unexpected token: `<-` parser_remove_let = expected pattern, found `let` .suggestion = remove the unnecessary `let` keyword + +parser_use_eq_instead = unexpected `==` + .suggestion = try using `=` instead diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ad49227222b2c..be524db785bc0 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -713,6 +713,14 @@ pub(crate) struct RemoveLet { pub span: Span, } +#[derive(SessionDiagnostic)] +#[diag(parser::use_eq_instead)] +pub(crate) struct UseEqInstead { + #[primary_span] + #[suggestion_short(applicability = "machine-applicable", code = "=")] + pub span: Span, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. @@ -957,6 +965,14 @@ impl<'a> Parser<'a> { } } + if self.token.kind == TokenKind::EqEq + && self.prev_token.is_ident() + && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq))) + { + // Likely typo: `=` → `==` in let expr or enum item + return Err(self.sess.create_err(UseEqInstead { span: self.token.span })); + } + let expect = tokens_to_string(&expected); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { diff --git a/src/test/ui/parser/issue-101477-enum.fixed b/src/test/ui/parser/issue-101477-enum.fixed new file mode 100644 index 0000000000000..1dfeae22aea2f --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B = 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-101477-enum.rs b/src/test/ui/parser/issue-101477-enum.rs new file mode 100644 index 0000000000000..ea7051d69a4c7 --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.rs @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B == 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-101477-enum.stderr b/src/test/ui/parser/issue-101477-enum.stderr new file mode 100644 index 0000000000000..bffc881bdc84b --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.stderr @@ -0,0 +1,14 @@ +error: unexpected `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ help: try using `=` instead + +error: expected item, found `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ expected item + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/issue-101477-let.fixed b/src/test/ui/parser/issue-101477-let.fixed new file mode 100644 index 0000000000000..9989ad81524e1 --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x = 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/src/test/ui/parser/issue-101477-let.rs b/src/test/ui/parser/issue-101477-let.rs new file mode 100644 index 0000000000000..8b0e8bee1799d --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.rs @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x == 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/src/test/ui/parser/issue-101477-let.stderr b/src/test/ui/parser/issue-101477-let.stderr new file mode 100644 index 0000000000000..1b30d4b17861a --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.stderr @@ -0,0 +1,8 @@ +error: unexpected `==` + --> $DIR/issue-101477-let.rs:4:11 + | +LL | let x == 2; + | ^^ help: try using `=` instead + +error: aborting due to previous error + From 5c9d28d303f316c6cc6895ec742839b79392720a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 5 Jul 2022 13:56:51 +0000 Subject: [PATCH 24/27] Opaque types' generic params do not imply anything about their hidden type's lifetimes --- compiler/rustc_middle/src/ty/visit.rs | 2 +- .../type-alias-impl-trait/constrain_inputs.rs | 24 +++++++-- .../constrain_inputs.stderr | 52 +++++++++++++++++++ .../constrain_inputs_unsound.rs | 31 +++++++++++ .../constrain_inputs_unsound.stderr | 9 ++++ 5 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/constrain_inputs.stderr create mode 100644 src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs create mode 100644 src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 5e042c3acfce2..5f8cb57820210 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -666,7 +666,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // ignore the inputs to a projection, as they may not appear // in the normalized form if self.just_constrained { - if let ty::Projection(..) = t.kind() { + if let ty::Projection(..) | ty::Opaque(..) = t.kind() { return ControlFlow::CONTINUE; } } diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs index c32174288ee68..1300a2e45d57d 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs @@ -1,17 +1,33 @@ -// check-pass - #![feature(type_alias_impl_trait)] -mod foo { +mod lifetime_params { type Ty<'a> = impl Sized; fn defining(s: &str) -> Ty<'_> { s } fn execute(ty: Ty<'_>) -> &str { todo!() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + + type BadFnSig = fn(Ty<'_>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime } -mod bar { +mod type_params { type Ty<'a> = impl FnOnce() -> &'a str; fn defining(s: &str) -> Ty<'_> { move || s } fn execute(ty: Ty<'_>) -> &str { ty() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types +} + +// regression test for https://github.com/rust-lang/rust/issues/97104 +mod type_params2 { + type Ty = impl Sized; + fn define(s: T) -> Ty { s } + + type BadFnSig = fn(Ty<&str>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr new file mode 100644 index 0000000000000..c35b55df64380 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -0,0 +1,52 @@ +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:6:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { todo!() } + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:9:35 + | +LL | type BadFnSig = fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:11:42 + | +LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:18:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { ty() } + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:27:37 + | +LL | type BadFnSig = fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:29:44 + | +LL | type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0581, E0582. +For more information about an error, try `rustc --explain E0581`. diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs new file mode 100644 index 0000000000000..937ca48a52dbd --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +trait Static: 'static {} +impl Static for () {} + +type Gal = impl Static; +fn _defining() -> Gal {} + +trait Callable { type Output; } + +/// We can infer `>::Output: 'static`, +/// because we know `C: 'static` and `Arg: 'static`, +fn box_str(s: C::Output) -> Box + 'static> +where + Arg: Static, + C: ?Sized + Callable + 'static, + C::Output: AsRef, +{ + Box::new(s) +} + +fn extend_lifetime(s: &str) -> Box + 'static> { + type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + //~^ ERROR binding for associated type `Output` references lifetime `'a` + box_str::(s) +} + +fn main() { + //let extended = extend_lifetime(&String::from("hello")); + //println!("{}", extended.as_ref().as_ref()); +} diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr new file mode 100644 index 0000000000000..d5fc46cb1f596 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr @@ -0,0 +1,9 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/constrain_inputs_unsound.rs:23:58 + | +LL | type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. From 5cd3cc134a41c92616ff74f652556135404ead8a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Aug 2022 10:23:22 +0000 Subject: [PATCH 25/27] Uncomment unsound code example --- src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs index 937ca48a52dbd..3bae0f1730994 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs @@ -26,6 +26,6 @@ fn extend_lifetime(s: &str) -> Box + 'static> { } fn main() { - //let extended = extend_lifetime(&String::from("hello")); - //println!("{}", extended.as_ref().as_ref()); + let extended = extend_lifetime(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); } From 64d11fc8e336344a8b8a55a55131ded4be26cebd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Aug 2022 10:30:46 +0000 Subject: [PATCH 26/27] Clarify some diagnostic messages --- compiler/rustc_typeck/src/astconv/mod.rs | 3 ++- src/test/ui/associated-types/issue-62200.rs | 3 ++- .../ui/associated-types/issue-62200.stderr | 3 ++- src/test/ui/issues/issue-47511.stderr | 3 ++- .../type-alias-impl-trait/constrain_inputs.rs | 4 ++-- .../constrain_inputs.stderr | 18 ++++++++++++------ 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 801063583e633..d66cf6d099ad5 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2940,8 +2940,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // though we can easily give a hint that ought to be // relevant. err.note( - "lifetimes appearing in an associated type are not considered constrained", + "lifetimes appearing in an associated or opaque type are not considered constrained", ); + err.note("consider introducing a named lifetime parameter"); } err.emit(); diff --git a/src/test/ui/associated-types/issue-62200.rs b/src/test/ui/associated-types/issue-62200.rs index 9d18690e96049..499bbd6b6fad2 100644 --- a/src/test/ui/associated-types/issue-62200.rs +++ b/src/test/ui/associated-types/issue-62200.rs @@ -10,6 +10,7 @@ impl T<'_> for S { fn foo(x: impl Fn(>::A) -> >::A) {} //~^ ERROR binding for associated type `Output` references an anonymous lifetime -//~^^ NOTE lifetimes appearing in an associated type are not considered constrained +//~| NOTE lifetimes appearing in an associated or opaque type are not considered constrained +//~| NOTE consider introducing a named lifetime parameter fn main() {} diff --git a/src/test/ui/associated-types/issue-62200.stderr b/src/test/ui/associated-types/issue-62200.stderr index f14cd81fdfe1f..04f0728f58ea8 100644 --- a/src/test/ui/associated-types/issue-62200.stderr +++ b/src/test/ui/associated-types/issue-62200.stderr @@ -4,7 +4,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet LL | fn foo(x: impl Fn(>::A) -> >::A) {} | ^^^^^^^^^^^^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr index 5b84f7ed62c3a..9998ee0e8d0c6 100644 --- a/src/test/ui/issues/issue-47511.stderr +++ b/src/test/ui/issues/issue-47511.stderr @@ -4,7 +4,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | fn f(_: X) -> X { | ^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types --> $DIR/issue-47511.rs:12:23 diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs index 1300a2e45d57d..03fb64b7b94d7 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs @@ -12,7 +12,7 @@ mod lifetime_params { //~^ ERROR binding for associated type `Output` references an anonymous lifetime } -mod type_params { +mod lifetime_params_2 { type Ty<'a> = impl FnOnce() -> &'a str; fn defining(s: &str) -> Ty<'_> { move || s } fn execute(ty: Ty<'_>) -> &str { ty() } @@ -20,7 +20,7 @@ mod type_params { } // regression test for https://github.com/rust-lang/rust/issues/97104 -mod type_params2 { +mod type_params { type Ty = impl Sized; fn define(s: T) -> Ty { s } diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr index c35b55df64380..93953fd06d1fd 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -4,7 +4,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | fn execute(ty: Ty<'_>) -> &str { todo!() } | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:9:35 @@ -12,7 +13,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | type BadFnSig = fn(Ty<'_>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types --> $DIR/constrain_inputs.rs:11:42 @@ -20,7 +22,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:18:31 @@ -28,7 +31,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | fn execute(ty: Ty<'_>) -> &str { ty() } | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:27:37 @@ -36,7 +40,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | type BadFnSig = fn(Ty<&str>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types --> $DIR/constrain_inputs.rs:29:44 @@ -44,7 +49,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet LL | type BadTraitRef = dyn Fn(Ty<&str>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error: aborting due to 6 previous errors From 0e497a714ebfefbee094b8475ea9aa4eeaa7b692 Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Thu, 8 Sep 2022 08:15:37 +0200 Subject: [PATCH 27/27] translations(rustc_session): migrates two diagnostics in session.rs --- .../locales/en-US/session.ftl | 6 ++++-- compiler/rustc_errors/src/diagnostic.rs | 5 ++++- compiler/rustc_session/src/errors.rs | 14 ++++++++++++++ compiler/rustc_session/src/session.rs | 18 ++++++++---------- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index a9ed8b4835b77..d2a2958f62436 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -15,8 +15,6 @@ session_feature_diagnostic_for_issue = session_feature_diagnostic_help = add `#![feature({$feature})]` to the crate attributes to enable -session_target_data_layout_parse_error = {$err} - session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist. @@ -54,3 +52,7 @@ session_target_inconsistent_architecture = inconsistent target specification: "d session_target_inconsistent_pointer_width = inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}` session_target_invalid_bits_size = {$err} + +session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored + +session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b88292b893cea..a774b52c8a592 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -10,7 +10,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::{edition::Edition, Span, DUMMY_SP}; -use rustc_target::spec::PanicStrategy; +use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; @@ -93,6 +93,9 @@ into_diagnostic_arg_using_display!( Ident, MacroRulesNormalizedIdent, ParseIntError, + StackProtector, + &TargetTriple, + SplitDebuginfo ); impl IntoDiagnosticArg for bool { diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index a4e13e22ae221..3c93cfab183d2 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -6,6 +6,7 @@ use rustc_errors::{fluent, DiagnosticBuilder, Handler, MultiSpan}; use rustc_macros::SessionDiagnostic; use rustc_span::{Span, Symbol}; use rustc_target::abi::TargetDataLayoutErrors; +use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; #[derive(SessionDiagnostic)] #[diag(session::incorrect_cgu_reuse_type)] @@ -156,3 +157,16 @@ pub struct UnstableVirtualFunctionElimination; pub struct UnsupportedDwarfVersion { pub dwarf_version: u32, } + +#[derive(SessionDiagnostic)] +#[diag(session::target_stack_protector_not_supported)] +pub struct StackProtectorNotSupportedForTarget<'a> { + pub stack_protector: StackProtector, + pub target_triple: &'a TargetTriple, +} + +#[derive(SessionDiagnostic)] +#[diag(session::split_debuginfo_unstable_platform)] +pub struct SplitDebugInfoUnstablePlatform { + pub debuginfo: SplitDebuginfo, +} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 6add576cdff35..caf9d582ab099 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -5,8 +5,9 @@ use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, S use crate::errors::{ CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, - SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, TargetRequiresUnwindTables, - UnstableVirtualFunctionElimination, UnsupportedDwarfVersion, + SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, + SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget, + TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion, }; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; @@ -1544,10 +1545,10 @@ fn validate_commandline_args_with_session_available(sess: &Session) { if sess.opts.unstable_opts.stack_protector != StackProtector::None { if !sess.target.options.supports_stack_protector { - sess.warn(&format!( - "`-Z stack-protector={}` is not supported for target {} and will be ignored", - sess.opts.unstable_opts.stack_protector, sess.opts.target_triple - )) + sess.emit_warning(StackProtectorNotSupportedForTarget { + stack_protector: sess.opts.unstable_opts.stack_protector, + target_triple: &sess.opts.target_triple, + }); } } @@ -1560,10 +1561,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo()) && !sess.opts.unstable_opts.unstable_options { - sess.err(&format!( - "`-Csplit-debuginfo={}` is unstable on this platform", - sess.split_debuginfo() - )); + sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() }); } }