From b232bb84a46e3083dbacbed9afd8cd15030dfa4a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 19 Jan 2023 14:43:41 +0000 Subject: [PATCH 1/7] Require TAITs to appear in the signature of items that register a hidden type --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- compiler/rustc_hir_typeck/src/inherited.rs | 8 +- compiler/rustc_hir_typeck/src/lib.rs | 16 +- .../rustc_infer/src/infer/opaque_types.rs | 137 ++++++- .../src/ty/normalize_erasing_regions.rs | 2 +- .../src/methods/unnecessary_to_owned.rs | 3 +- .../clippy_lints/src/transmute/utils.rs | 3 +- ...i-emit-type-metadata-id-itanium-cxx-abi.rs | 333 +++++++++--------- .../feature-gate-type_alias_impl_trait.rs | 15 +- .../deduce-signature-from-supertrait.rs | 7 +- tests/ui/impl-trait/issues/issue-70877.rs | 4 +- tests/ui/impl-trait/issues/issue-70877.stderr | 19 - tests/ui/impl-trait/issues/issue-74282.rs | 15 +- tests/ui/impl-trait/issues/issue-74282.stderr | 26 +- .../issues/issue-78722.global.stderr | 20 ++ ...722.stderr => issue-78722.in_const.stderr} | 8 +- tests/ui/impl-trait/issues/issue-78722.rs | 12 +- .../associated-type-impl-trait-lifetime.rs | 7 +- .../ui/type-alias-impl-trait/closure_args.rs | 14 +- .../ui/type-alias-impl-trait/closure_args2.rs | 23 +- .../generic_type_does_not_live_long_enough.rs | 9 +- ...eric_type_does_not_live_long_enough.stderr | 6 +- .../type-alias-impl-trait/inference-cycle.rs | 3 +- tests/ui/type-alias-impl-trait/issue-57961.rs | 4 +- .../issue-63263-closure-return.rs | 9 +- ...sue-65679-inst-opaque-ty-from-val-twice.rs | 7 +- .../nested_type_alias_impl_trait.rs | 4 +- .../nested_type_alias_impl_trait.stderr | 19 - .../ui/type-alias-impl-trait/reveal_local.rs | 8 +- .../type-alias-impl-trait/reveal_local.stderr | 29 +- .../ui/type-alias-impl-trait/type_of_a_let.rs | 10 +- .../type_of_a_let.stderr | 4 +- 32 files changed, 520 insertions(+), 266 deletions(-) delete mode 100644 tests/ui/impl-trait/issues/issue-70877.stderr create mode 100644 tests/ui/impl-trait/issues/issue-78722.global.stderr rename tests/ui/impl-trait/issues/{issue-78722.stderr => issue-78722.in_const.stderr} (79%) delete mode 100644 tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 6ed8adb47425a..c69c73d1e5101 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -680,7 +680,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind() && let Some(def_id) = def_id.as_local() - && self.opaque_type_origin(def_id, DUMMY_SP).is_some() { + && self.opaque_type_origin(def_id, DUMMY_SP, self.param_env).is_some() { return None; } } diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index b33e7b8d68cf9..5c8ceaebba426 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -82,14 +82,18 @@ pub struct InheritedBuilder<'tcx> { } impl<'tcx> Inherited<'tcx> { - pub fn build(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> InheritedBuilder<'tcx> { + pub fn build( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + mk_defining_use_anchor: impl FnOnce(LocalDefId) -> DefiningAnchor, + ) -> InheritedBuilder<'tcx> { let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner; InheritedBuilder { infcx: tcx .infer_ctxt() .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)), + .with_opaque_type_inference(mk_defining_use_anchor(hir_owner.def_id)), def_id, typeck_results: RefCell::new(ty::TypeckResults::new(hir_owner)), } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 7ddf9eaa4d899..e642b31d28b83 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -48,6 +48,7 @@ pub use diverges::Diverges; pub use expectation::Expectation; pub use fn_ctxt::*; pub use inherited::{Inherited, InheritedBuilder}; +use rustc_infer::infer::DefiningAnchor; use crate::check::check_fn; use crate::coercion::DynamicCoerceMany; @@ -199,12 +200,23 @@ fn typeck_with_fallback<'tcx>( }); let body = tcx.hir().body(body_id); - let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { + let fn_sig_infer = fn_sig.map_or(false, |fn_sig| { + rustc_hir_analysis::collect::get_infer_ret_ty(&fn_sig.decl.output).is_some() + }); + + let mk_defining_use_anchor = |def_id| { + // In case we are inferring the return signature (via `_` types), ignore defining use + // rules, as we'll error out anyway. This helps improve diagnostics, which otherwise + // may just see `ty::Error` instead of `ty::Alias(Opaque, _)` and not produce better errors. + if fn_sig_infer { DefiningAnchor::Bubble } else { DefiningAnchor::Bind(def_id) } + }; + + let typeck_results = Inherited::build(tcx, def_id, mk_defining_use_anchor).enter(|inh| { let param_env = tcx.param_env(def_id); let mut fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); if let Some(hir::FnSig { header, decl, .. }) = fn_sig { - let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() { + let fn_sig = if fn_sig_infer { fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None) } else { tcx.fn_sig(def_id) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e22ba9785e1fd..447f1e6116463 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -10,12 +10,13 @@ use rustc_hir as hir; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; -use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{ self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; +use rustc_middle::ty::{DefIdTree, GenericArgKind}; use rustc_span::Span; +use smallvec::SmallVec; use std::ops::ControlFlow; @@ -59,7 +60,7 @@ impl<'tcx> InferCtxt<'tcx> { let replace_opaque_type = |def_id: DefId| { def_id .as_local() - .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some()) + .map_or(false, |def_id| self.opaque_type_origin(def_id, span, param_env).is_some()) }; let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, @@ -144,7 +145,7 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - self.opaque_type_origin(def_id, cause.span)? + self.opaque_type_origin(def_id, cause.span, param_env)? } DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span), DefiningAnchor::Error => return None, @@ -155,9 +156,10 @@ impl<'tcx> InferCtxt<'tcx> { // no one encounters it in practice. // It does occur however in `fn fut() -> impl Future { async { 42 } }`, // where it is of no concern, so we only check for TAITs. - if let Some(OpaqueTyOrigin::TyAlias) = b_def_id - .as_local() - .and_then(|b_def_id| self.opaque_type_origin(b_def_id, cause.span)) + if let Some(OpaqueTyOrigin::TyAlias) = + b_def_id.as_local().and_then(|b_def_id| { + self.opaque_type_origin(b_def_id, cause.span, param_env) + }) { self.tcx.sess.emit_err(OpaqueHiddenTypeDiag { span: cause.span, @@ -372,7 +374,12 @@ impl<'tcx> InferCtxt<'tcx> { } #[instrument(skip(self), level = "trace", ret)] - pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option { + pub fn opaque_type_origin( + &self, + def_id: LocalDefId, + span: Span, + param_env: ty::ParamEnv<'tcx>, + ) -> Option { let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = match self.defining_use_anchor { DefiningAnchor::Bubble | DefiningAnchor::Error => return None, @@ -395,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> { hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` hir::OpaqueTyOrigin::TyAlias => { - may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id) + may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id, def_id, param_env) } }; trace!(?origin); @@ -639,11 +646,123 @@ impl<'tcx> InferCtxt<'tcx> { /// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`), /// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. /// For the above example, this function returns `true` for `f1` and `false` for `f2`. -fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool { +#[instrument(skip(tcx), level = "trace", ret)] +fn may_define_opaque_type<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + opaque_hir_id: hir::HirId, + opaque_def_id: LocalDefId, + param_env: ty::ParamEnv<'tcx>, +) -> bool { let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); // Named opaque types can be defined by any siblings or children of siblings. let scope = tcx.hir().get_defining_scope(opaque_hir_id); + + // When doing checks within the opaque type itself + if def_id != opaque_def_id + // When the opaque type is defined in the body of a function, the function may access it. + && hir_id != scope + { + trace!(parent = ?tcx.parent(opaque_def_id.to_def_id())); + fn has_tait<'tcx>( + val: impl TypeVisitable<'tcx>, + opaque_def_id: LocalDefId, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + struct Visitor<'tcx> { + opaque_def_id: DefId, + tcx: TyCtxt<'tcx>, + ignore_nested: SmallVec<[DefId; 1]>, + param_env: ty::ParamEnv<'tcx>, + } + impl<'tcx> TypeVisitor<'tcx> for Visitor<'tcx> { + type BreakTy = (); + #[instrument(skip(self), level = "trace", ret)] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + match t.kind() { + ty::Alias(ty::Opaque, alias) => { + if alias.def_id == self.opaque_def_id { + return ControlFlow::Break(()); + } + if !self.ignore_nested.contains(&alias.def_id) { + // avoid infinite recursion since the opaque type shows + // up in its own bounds. + self.ignore_nested.push(alias.def_id); + for (pred, _span) in self + .tcx + .bound_explicit_item_bounds(alias.def_id) + .subst_iter_copied(self.tcx, alias.substs) + { + pred.visit_with(self)?; + } + } + } + ty::Alias(ty::Projection, _) => { + if let Ok(proj) = + self.tcx.try_normalize_erasing_regions(self.param_env, t) + { + proj.visit_with(self)?; + } + } + // Types that have opaque type fields must get walked manually, they + // would not be seen by the type visitor otherwise. + ty::Adt(adt_def, substs) => { + if !self.ignore_nested.contains(&adt_def.did()) { + // avoid infinite recursion since adts can recursively refer + // to themselves + self.ignore_nested.push(adt_def.did()); + for variant in adt_def.variants() { + for field in &variant.fields { + field.ty(self.tcx, substs).visit_with(self)?; + } + } + } + } + _ => (), + } + t.super_visit_with(self) + } + } + val.visit_with(&mut Visitor { + opaque_def_id: opaque_def_id.to_def_id(), + tcx, + ignore_nested: SmallVec::new(), + param_env, + }) + .is_break() + } + let tait_in_fn_sig = match tcx.def_kind(def_id) { + DefKind::AssocFn | DefKind::Fn => { + has_tait(tcx.fn_sig(def_id.to_def_id()), opaque_def_id, tcx, param_env) + } + // Opaque types in types of contsts + DefKind::Static(_) | DefKind::Const | DefKind::AssocConst => { + has_tait(tcx.type_of(def_id.to_def_id()), opaque_def_id, tcx, param_env) + } + // Nested opaque types + DefKind::OpaqueTy => has_tait( + tcx.bound_explicit_item_bounds(def_id.to_def_id()).skip_binder(), + opaque_def_id, + tcx, + param_env, + ), + _ => false, + }; + trace!(?tait_in_fn_sig); + if !tait_in_fn_sig + && !has_tait( + tcx.predicates_of(def_id.to_def_id()).predicates, + opaque_def_id, + tcx, + param_env, + ) + { + return false; + } + } + // We walk up the node tree until we hit the root or the scope of the opaque type. while hir_id != scope && hir_id != hir::CRATE_HIR_ID { hir_id = tcx.hir().get_parent_item(hir_id).into(); diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index ee13920d52edd..34a056065c839 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -226,7 +226,7 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { TryNormalizeAfterErasingRegionsFolder { tcx, param_env } } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "debug", ret)] fn try_normalize_generic_arg_after_erasing_regions( &self, arg: ty::GenericArg<'tcx>, diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 9263f0519724b..e4310c5afac6a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -17,6 +17,7 @@ use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, Clause, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; +use rustc_infer::infer::DefiningAnchor; use super::UNNECESSARY_TO_OWNED; @@ -370,7 +371,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< if let ItemKind::Fn(_, _, body_id) = &item.kind && let output_ty = return_ty(cx, item.hir_id()) && let local_def_id = cx.tcx.hir().local_def_id(item.hir_id()) - && Inherited::build(cx.tcx, local_def_id).enter(|inherited| { + && Inherited::build(cx.tcx, local_def_id, DefiningAnchor::Bind).enter(|inherited| { let fn_ctxt = FnCtxt::new(inherited, cx.param_env, item.hir_id()); fn_ctxt.can_coerce(ty, output_ty) }) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 49d863ec03f1d..5aa43cb850106 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -4,6 +4,7 @@ use rustc_hir_typeck::{cast, FnCtxt, Inherited}; use rustc_lint::LateContext; use rustc_middle::ty::{cast::CastKind, Ty}; use rustc_span::DUMMY_SP; +use rustc_infer::infer::DefiningAnchor; // check if the component types of the transmuted collection and the result have different ABI, // size or alignment @@ -45,7 +46,7 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx> let hir_id = e.hir_id; let local_def_id = hir_id.owner.def_id; - Inherited::build(cx.tcx, local_def_id).enter(|inherited| { + Inherited::build(cx.tcx, local_def_id, DefiningAnchor::Bind).enter(|inherited| { let fn_ctxt = FnCtxt::new(inherited, cx.param_env, hir_id); // If we already have errors, we can't be sure we can pointer cast. diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs index b9c33914360ba..56e5cd433a70f 100644 --- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -3,7 +3,7 @@ // needs-sanitizer-cfi // compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -#![crate_type="lib"] +#![crate_type = "lib"] #![allow(dead_code)] #![allow(incomplete_features)] #![allow(unused_must_use)] @@ -29,23 +29,23 @@ pub union Union1 { } // Extern type -extern { +extern "C" { pub type type1; } // Trait pub trait Trait1 { - fn foo(&self) { } + fn foo(&self) {} } // Trait implementation impl Trait1 for i32 { - fn foo(&self) { } + fn foo(&self) {} } // Trait implementation impl Trait1 for Struct1 { - fn foo(&self) { } + fn foo(&self) {} } // impl Trait type aliases for helping with defining other types (see below) @@ -61,9 +61,22 @@ pub type Type9 = impl Send; pub type Type10 = impl Send; pub type Type11 = impl Send; -pub fn fn1<'a>() { +pub fn fn1<'a>() +where + Type1:, + Type2:, + Type3:, + Type4:, + Type5:, + Type6:, + Type7:, + Type8:, + Type9:, + Type10:, + Type11:, +{ // Closure - let closure1 = || { }; + let closure1 = || {}; let _: Type1 = closure1; // Constructor @@ -71,7 +84,7 @@ pub fn fn1<'a>() { let _: Type2 = Foo; // Type in extern path - extern { + extern "C" { fn foo(); } let _: Type3 = foo; @@ -85,12 +98,14 @@ pub fn fn1<'a>() { // Type in const path const { pub struct Foo; - fn foo() -> Type5 { Foo } + fn foo() -> Type5 { + Foo + } }; // Type in impl path impl Struct1 { - fn foo(&self) { } + fn foo(&self) {} } let _: Type6 = >::foo; @@ -138,305 +153,305 @@ pub struct Bar; #[repr(transparent)] pub struct Type14(T); -pub fn foo0(_: ()) { } +pub fn foo0(_: ()) {} // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] -pub fn foo1(_: c_void, _: ()) { } +pub fn foo1(_: c_void, _: ()) {} // CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] -pub fn foo2(_: (), _: c_void, _: c_void) { } +pub fn foo2(_: (), _: c_void, _: c_void) {} // CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] -pub fn foo3(_: *mut c_void) { } +pub fn foo3(_: *mut c_void) {} // CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] -pub fn foo4(_: *mut c_void, _: *mut ()) { } +pub fn foo4(_: *mut c_void, _: *mut ()) {} // CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] -pub fn foo5(_: *mut (), _: *mut c_void, _: *mut c_void) { } +pub fn foo5(_: *mut (), _: *mut c_void, _: *mut c_void) {} // CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] -pub fn foo6(_: *const c_void) { } +pub fn foo6(_: *const c_void) {} // CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] -pub fn foo7(_: *const c_void, _: *const ()) { } +pub fn foo7(_: *const c_void, _: *const ()) {} // CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] -pub fn foo8(_: *const (), _: *const c_void, _: *const c_void) { } +pub fn foo8(_: *const (), _: *const c_void, _: *const c_void) {} // CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] -pub fn foo9(_: bool) { } +pub fn foo9(_: bool) {} // CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] -pub fn foo10(_: bool, _: bool) { } +pub fn foo10(_: bool, _: bool) {} // CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] -pub fn foo11(_: bool, _: bool, _: bool) { } +pub fn foo11(_: bool, _: bool, _: bool) {} // CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] -pub fn foo12(_: i8) { } +pub fn foo12(_: i8) {} // CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] -pub fn foo13(_: i8, _: i8) { } +pub fn foo13(_: i8, _: i8) {} // CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] -pub fn foo14(_: i8, _: i8, _: i8) { } +pub fn foo14(_: i8, _: i8, _: i8) {} // CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] -pub fn foo15(_: i16) { } +pub fn foo15(_: i16) {} // CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]] -pub fn foo16(_: i16, _: i16) { } +pub fn foo16(_: i16, _: i16) {} // CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]] -pub fn foo17(_: i16, _: i16, _: i16) { } +pub fn foo17(_: i16, _: i16, _: i16) {} // CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]] -pub fn foo18(_: i32) { } +pub fn foo18(_: i32) {} // CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]] -pub fn foo19(_: i32, _: i32) { } +pub fn foo19(_: i32, _: i32) {} // CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]] -pub fn foo20(_: i32, _: i32, _: i32) { } +pub fn foo20(_: i32, _: i32, _: i32) {} // CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]] -pub fn foo21(_: i64) { } +pub fn foo21(_: i64) {} // CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]] -pub fn foo22(_: i64, _: i64) { } +pub fn foo22(_: i64, _: i64) {} // CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]] -pub fn foo23(_: i64, _: i64, _: i64) { } +pub fn foo23(_: i64, _: i64, _: i64) {} // CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]] -pub fn foo24(_: i128) { } +pub fn foo24(_: i128) {} // CHECK: define{{.*}}foo24{{.*}}!type ![[TYPE24:[0-9]+]] -pub fn foo25(_: i128, _: i128) { } +pub fn foo25(_: i128, _: i128) {} // CHECK: define{{.*}}foo25{{.*}}!type ![[TYPE25:[0-9]+]] -pub fn foo26(_: i128, _: i128, _: i128) { } +pub fn foo26(_: i128, _: i128, _: i128) {} // CHECK: define{{.*}}foo26{{.*}}!type ![[TYPE26:[0-9]+]] -pub fn foo27(_: isize) { } +pub fn foo27(_: isize) {} // CHECK: define{{.*}}foo27{{.*}}!type ![[TYPE27:[0-9]+]] -pub fn foo28(_: isize, _: isize) { } +pub fn foo28(_: isize, _: isize) {} // CHECK: define{{.*}}foo28{{.*}}!type ![[TYPE28:[0-9]+]] -pub fn foo29(_: isize, _: isize, _: isize) { } +pub fn foo29(_: isize, _: isize, _: isize) {} // CHECK: define{{.*}}foo29{{.*}}!type ![[TYPE29:[0-9]+]] -pub fn foo30(_: u8) { } +pub fn foo30(_: u8) {} // CHECK: define{{.*}}foo30{{.*}}!type ![[TYPE30:[0-9]+]] -pub fn foo31(_: u8, _: u8) { } +pub fn foo31(_: u8, _: u8) {} // CHECK: define{{.*}}foo31{{.*}}!type ![[TYPE31:[0-9]+]] -pub fn foo32(_: u8, _: u8, _: u8) { } +pub fn foo32(_: u8, _: u8, _: u8) {} // CHECK: define{{.*}}foo32{{.*}}!type ![[TYPE32:[0-9]+]] -pub fn foo33(_: u16) { } +pub fn foo33(_: u16) {} // CHECK: define{{.*}}foo33{{.*}}!type ![[TYPE33:[0-9]+]] -pub fn foo34(_: u16, _: u16) { } +pub fn foo34(_: u16, _: u16) {} // CHECK: define{{.*}}foo34{{.*}}!type ![[TYPE34:[0-9]+]] -pub fn foo35(_: u16, _: u16, _: u16) { } +pub fn foo35(_: u16, _: u16, _: u16) {} // CHECK: define{{.*}}foo35{{.*}}!type ![[TYPE35:[0-9]+]] -pub fn foo36(_: u32) { } +pub fn foo36(_: u32) {} // CHECK: define{{.*}}foo36{{.*}}!type ![[TYPE36:[0-9]+]] -pub fn foo37(_: u32, _: u32) { } +pub fn foo37(_: u32, _: u32) {} // CHECK: define{{.*}}foo37{{.*}}!type ![[TYPE37:[0-9]+]] -pub fn foo38(_: u32, _: u32, _: u32) { } +pub fn foo38(_: u32, _: u32, _: u32) {} // CHECK: define{{.*}}foo38{{.*}}!type ![[TYPE38:[0-9]+]] -pub fn foo39(_: u64) { } +pub fn foo39(_: u64) {} // CHECK: define{{.*}}foo39{{.*}}!type ![[TYPE39:[0-9]+]] -pub fn foo40(_: u64, _: u64) { } +pub fn foo40(_: u64, _: u64) {} // CHECK: define{{.*}}foo40{{.*}}!type ![[TYPE40:[0-9]+]] -pub fn foo41(_: u64, _: u64, _: u64) { } +pub fn foo41(_: u64, _: u64, _: u64) {} // CHECK: define{{.*}}foo41{{.*}}!type ![[TYPE41:[0-9]+]] -pub fn foo42(_: u128) { } +pub fn foo42(_: u128) {} // CHECK: define{{.*}}foo42{{.*}}!type ![[TYPE42:[0-9]+]] -pub fn foo43(_: u128, _: u128) { } +pub fn foo43(_: u128, _: u128) {} // CHECK: define{{.*}}foo43{{.*}}!type ![[TYPE43:[0-9]+]] -pub fn foo44(_: u128, _: u128, _: u128) { } +pub fn foo44(_: u128, _: u128, _: u128) {} // CHECK: define{{.*}}foo44{{.*}}!type ![[TYPE44:[0-9]+]] -pub fn foo45(_: usize) { } +pub fn foo45(_: usize) {} // CHECK: define{{.*}}foo45{{.*}}!type ![[TYPE45:[0-9]+]] -pub fn foo46(_: usize, _: usize) { } +pub fn foo46(_: usize, _: usize) {} // CHECK: define{{.*}}foo46{{.*}}!type ![[TYPE46:[0-9]+]] -pub fn foo47(_: usize, _: usize, _: usize) { } +pub fn foo47(_: usize, _: usize, _: usize) {} // CHECK: define{{.*}}foo47{{.*}}!type ![[TYPE47:[0-9]+]] -pub fn foo48(_: f32) { } +pub fn foo48(_: f32) {} // CHECK: define{{.*}}foo48{{.*}}!type ![[TYPE48:[0-9]+]] -pub fn foo49(_: f32, _: f32) { } +pub fn foo49(_: f32, _: f32) {} // CHECK: define{{.*}}foo49{{.*}}!type ![[TYPE49:[0-9]+]] -pub fn foo50(_: f32, _: f32, _: f32) { } +pub fn foo50(_: f32, _: f32, _: f32) {} // CHECK: define{{.*}}foo50{{.*}}!type ![[TYPE50:[0-9]+]] -pub fn foo51(_: f64) { } +pub fn foo51(_: f64) {} // CHECK: define{{.*}}foo51{{.*}}!type ![[TYPE51:[0-9]+]] -pub fn foo52(_: f64, _: f64) { } +pub fn foo52(_: f64, _: f64) {} // CHECK: define{{.*}}foo52{{.*}}!type ![[TYPE52:[0-9]+]] -pub fn foo53(_: f64, _: f64, _: f64) { } +pub fn foo53(_: f64, _: f64, _: f64) {} // CHECK: define{{.*}}foo53{{.*}}!type ![[TYPE53:[0-9]+]] -pub fn foo54(_: char) { } +pub fn foo54(_: char) {} // CHECK: define{{.*}}foo54{{.*}}!type ![[TYPE54:[0-9]+]] -pub fn foo55(_: char, _: char) { } +pub fn foo55(_: char, _: char) {} // CHECK: define{{.*}}foo55{{.*}}!type ![[TYPE55:[0-9]+]] -pub fn foo56(_: char, _: char, _: char) { } +pub fn foo56(_: char, _: char, _: char) {} // CHECK: define{{.*}}foo56{{.*}}!type ![[TYPE56:[0-9]+]] -pub fn foo57(_: &str) { } +pub fn foo57(_: &str) {} // CHECK: define{{.*}}foo57{{.*}}!type ![[TYPE57:[0-9]+]] -pub fn foo58(_: &str, _: &str) { } +pub fn foo58(_: &str, _: &str) {} // CHECK: define{{.*}}foo58{{.*}}!type ![[TYPE58:[0-9]+]] -pub fn foo59(_: &str, _: &str, _: &str) { } +pub fn foo59(_: &str, _: &str, _: &str) {} // CHECK: define{{.*}}foo59{{.*}}!type ![[TYPE59:[0-9]+]] -pub fn foo60(_: (i32, i32)) { } +pub fn foo60(_: (i32, i32)) {} // CHECK: define{{.*}}foo60{{.*}}!type ![[TYPE60:[0-9]+]] -pub fn foo61(_: (i32, i32), _: (i32, i32)) { } +pub fn foo61(_: (i32, i32), _: (i32, i32)) {} // CHECK: define{{.*}}foo61{{.*}}!type ![[TYPE61:[0-9]+]] -pub fn foo62(_: (i32, i32), _: (i32, i32), _: (i32, i32)) { } +pub fn foo62(_: (i32, i32), _: (i32, i32), _: (i32, i32)) {} // CHECK: define{{.*}}foo62{{.*}}!type ![[TYPE62:[0-9]+]] -pub fn foo63(_: [i32; 32]) { } +pub fn foo63(_: [i32; 32]) {} // CHECK: define{{.*}}foo63{{.*}}!type ![[TYPE63:[0-9]+]] -pub fn foo64(_: [i32; 32], _: [i32; 32]) { } +pub fn foo64(_: [i32; 32], _: [i32; 32]) {} // CHECK: define{{.*}}foo64{{.*}}!type ![[TYPE64:[0-9]+]] -pub fn foo65(_: [i32; 32], _: [i32; 32], _: [i32; 32]) { } +pub fn foo65(_: [i32; 32], _: [i32; 32], _: [i32; 32]) {} // CHECK: define{{.*}}foo65{{.*}}!type ![[TYPE65:[0-9]+]] -pub fn foo66(_: &[i32]) { } +pub fn foo66(_: &[i32]) {} // CHECK: define{{.*}}foo66{{.*}}!type ![[TYPE66:[0-9]+]] -pub fn foo67(_: &[i32], _: &[i32]) { } +pub fn foo67(_: &[i32], _: &[i32]) {} // CHECK: define{{.*}}foo67{{.*}}!type ![[TYPE67:[0-9]+]] -pub fn foo68(_: &[i32], _: &[i32], _: &[i32]) { } +pub fn foo68(_: &[i32], _: &[i32], _: &[i32]) {} // CHECK: define{{.*}}foo68{{.*}}!type ![[TYPE68:[0-9]+]] -pub fn foo69(_: &Struct1::) { } +pub fn foo69(_: &Struct1) {} // CHECK: define{{.*}}foo69{{.*}}!type ![[TYPE69:[0-9]+]] -pub fn foo70(_: &Struct1::, _: &Struct1::) { } +pub fn foo70(_: &Struct1, _: &Struct1) {} // CHECK: define{{.*}}foo70{{.*}}!type ![[TYPE70:[0-9]+]] -pub fn foo71(_: &Struct1::, _: &Struct1::, _: &Struct1::) { } +pub fn foo71(_: &Struct1, _: &Struct1, _: &Struct1) {} // CHECK: define{{.*}}foo71{{.*}}!type ![[TYPE71:[0-9]+]] -pub fn foo72(_: &Enum1::) { } +pub fn foo72(_: &Enum1) {} // CHECK: define{{.*}}foo72{{.*}}!type ![[TYPE72:[0-9]+]] -pub fn foo73(_: &Enum1::, _: &Enum1::) { } +pub fn foo73(_: &Enum1, _: &Enum1) {} // CHECK: define{{.*}}foo73{{.*}}!type ![[TYPE73:[0-9]+]] -pub fn foo74(_: &Enum1::, _: &Enum1::, _: &Enum1::) { } +pub fn foo74(_: &Enum1, _: &Enum1, _: &Enum1) {} // CHECK: define{{.*}}foo74{{.*}}!type ![[TYPE74:[0-9]+]] -pub fn foo75(_: &Union1::) { } +pub fn foo75(_: &Union1) {} // CHECK: define{{.*}}foo75{{.*}}!type ![[TYPE75:[0-9]+]] -pub fn foo76(_: &Union1::, _: &Union1::) { } +pub fn foo76(_: &Union1, _: &Union1) {} // CHECK: define{{.*}}foo76{{.*}}!type ![[TYPE76:[0-9]+]] -pub fn foo77(_: &Union1::, _: &Union1::, _: &Union1::) { } +pub fn foo77(_: &Union1, _: &Union1, _: &Union1) {} // CHECK: define{{.*}}foo77{{.*}}!type ![[TYPE77:[0-9]+]] -pub fn foo78(_: *mut type1) { } +pub fn foo78(_: *mut type1) {} // CHECK: define{{.*}}foo78{{.*}}!type ![[TYPE78:[0-9]+]] -pub fn foo79(_: *mut type1, _: *mut type1) { } +pub fn foo79(_: *mut type1, _: *mut type1) {} // CHECK: define{{.*}}foo79{{.*}}!type ![[TYPE79:[0-9]+]] -pub fn foo80(_: *mut type1, _: *mut type1, _: *mut type1) { } +pub fn foo80(_: *mut type1, _: *mut type1, _: *mut type1) {} // CHECK: define{{.*}}foo80{{.*}}!type ![[TYPE80:[0-9]+]] -pub fn foo81(_: &mut i32) { } +pub fn foo81(_: &mut i32) {} // CHECK: define{{.*}}foo81{{.*}}!type ![[TYPE81:[0-9]+]] -pub fn foo82(_: &mut i32, _: &i32) { } +pub fn foo82(_: &mut i32, _: &i32) {} // CHECK: define{{.*}}foo82{{.*}}!type ![[TYPE82:[0-9]+]] -pub fn foo83(_: &mut i32, _: &i32, _: &i32) { } +pub fn foo83(_: &mut i32, _: &i32, _: &i32) {} // CHECK: define{{.*}}foo83{{.*}}!type ![[TYPE83:[0-9]+]] -pub fn foo84(_: &i32) { } +pub fn foo84(_: &i32) {} // CHECK: define{{.*}}foo84{{.*}}!type ![[TYPE84:[0-9]+]] -pub fn foo85(_: &i32, _: &mut i32) { } +pub fn foo85(_: &i32, _: &mut i32) {} // CHECK: define{{.*}}foo85{{.*}}!type ![[TYPE85:[0-9]+]] -pub fn foo86(_: &i32, _: &mut i32, _: &mut i32) { } +pub fn foo86(_: &i32, _: &mut i32, _: &mut i32) {} // CHECK: define{{.*}}foo86{{.*}}!type ![[TYPE86:[0-9]+]] -pub fn foo87(_: *mut i32) { } +pub fn foo87(_: *mut i32) {} // CHECK: define{{.*}}foo87{{.*}}!type ![[TYPE87:[0-9]+]] -pub fn foo88(_: *mut i32, _: *const i32) { } +pub fn foo88(_: *mut i32, _: *const i32) {} // CHECK: define{{.*}}foo88{{.*}}!type ![[TYPE88:[0-9]+]] -pub fn foo89(_: *mut i32, _: *const i32, _: *const i32) { } +pub fn foo89(_: *mut i32, _: *const i32, _: *const i32) {} // CHECK: define{{.*}}foo89{{.*}}!type ![[TYPE89:[0-9]+]] -pub fn foo90(_: *const i32) { } +pub fn foo90(_: *const i32) {} // CHECK: define{{.*}}foo90{{.*}}!type ![[TYPE90:[0-9]+]] -pub fn foo91(_: *const i32, _: *mut i32) { } +pub fn foo91(_: *const i32, _: *mut i32) {} // CHECK: define{{.*}}foo91{{.*}}!type ![[TYPE91:[0-9]+]] -pub fn foo92(_: *const i32, _: *mut i32, _: *mut i32) { } +pub fn foo92(_: *const i32, _: *mut i32, _: *mut i32) {} // CHECK: define{{.*}}foo92{{.*}}!type ![[TYPE92:[0-9]+]] -pub fn foo93(_: fn(i32) -> i32) { } +pub fn foo93(_: fn(i32) -> i32) {} // CHECK: define{{.*}}foo93{{.*}}!type ![[TYPE93:[0-9]+]] -pub fn foo94(_: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo94(_: fn(i32) -> i32, _: fn(i32) -> i32) {} // CHECK: define{{.*}}foo94{{.*}}!type ![[TYPE94:[0-9]+]] -pub fn foo95(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo95(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) {} // CHECK: define{{.*}}foo95{{.*}}!type ![[TYPE95:[0-9]+]] -pub fn foo96(_: &dyn Fn(i32) -> i32) { } +pub fn foo96(_: &dyn Fn(i32) -> i32) {} // CHECK: define{{.*}}foo96{{.*}}!type ![[TYPE96:[0-9]+]] -pub fn foo97(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo97(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) {} // CHECK: define{{.*}}foo97{{.*}}!type ![[TYPE97:[0-9]+]] -pub fn foo98(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo98(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) {} // CHECK: define{{.*}}foo98{{.*}}!type ![[TYPE98:[0-9]+]] -pub fn foo99(_: &dyn FnMut(i32) -> i32) { } +pub fn foo99(_: &dyn FnMut(i32) -> i32) {} // CHECK: define{{.*}}foo99{{.*}}!type ![[TYPE99:[0-9]+]] -pub fn foo100(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo100(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) {} // CHECK: define{{.*}}foo100{{.*}}!type ![[TYPE100:[0-9]+]] -pub fn foo101(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo101(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) {} // CHECK: define{{.*}}foo101{{.*}}!type ![[TYPE101:[0-9]+]] -pub fn foo102(_: &dyn FnOnce(i32) -> i32) { } +pub fn foo102(_: &dyn FnOnce(i32) -> i32) {} // CHECK: define{{.*}}foo102{{.*}}!type ![[TYPE102:[0-9]+]] -pub fn foo103(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { } +pub fn foo103(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {} // CHECK: define{{.*}}foo103{{.*}}!type ![[TYPE103:[0-9]+]] pub fn foo104(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {} // CHECK: define{{.*}}foo104{{.*}}!type ![[TYPE104:[0-9]+]] -pub fn foo105(_: &dyn Send) { } +pub fn foo105(_: &dyn Send) {} // CHECK: define{{.*}}foo105{{.*}}!type ![[TYPE105:[0-9]+]] -pub fn foo106(_: &dyn Send, _: &dyn Send) { } +pub fn foo106(_: &dyn Send, _: &dyn Send) {} // CHECK: define{{.*}}foo106{{.*}}!type ![[TYPE106:[0-9]+]] -pub fn foo107(_: &dyn Send, _: &dyn Send, _: &dyn Send) { } +pub fn foo107(_: &dyn Send, _: &dyn Send, _: &dyn Send) {} // CHECK: define{{.*}}foo107{{.*}}!type ![[TYPE107:[0-9]+]] -pub fn foo108(_: Type1) { } +pub fn foo108(_: Type1) {} // CHECK: define{{.*}}foo108{{.*}}!type ![[TYPE108:[0-9]+]] -pub fn foo109(_: Type1, _: Type1) { } +pub fn foo109(_: Type1, _: Type1) {} // CHECK: define{{.*}}foo109{{.*}}!type ![[TYPE109:[0-9]+]] -pub fn foo110(_: Type1, _: Type1, _: Type1) { } +pub fn foo110(_: Type1, _: Type1, _: Type1) {} // CHECK: define{{.*}}foo110{{.*}}!type ![[TYPE110:[0-9]+]] -pub fn foo111(_: Type2) { } +pub fn foo111(_: Type2) {} // CHECK: define{{.*}}foo111{{.*}}!type ![[TYPE111:[0-9]+]] -pub fn foo112(_: Type2, _: Type2) { } +pub fn foo112(_: Type2, _: Type2) {} // CHECK: define{{.*}}foo112{{.*}}!type ![[TYPE112:[0-9]+]] -pub fn foo113(_: Type2, _: Type2, _: Type2) { } +pub fn foo113(_: Type2, _: Type2, _: Type2) {} // CHECK: define{{.*}}foo113{{.*}}!type ![[TYPE113:[0-9]+]] -pub fn foo114(_: Type3) { } +pub fn foo114(_: Type3) {} // CHECK: define{{.*}}foo114{{.*}}!type ![[TYPE114:[0-9]+]] -pub fn foo115(_: Type3, _: Type3) { } +pub fn foo115(_: Type3, _: Type3) {} // CHECK: define{{.*}}foo115{{.*}}!type ![[TYPE115:[0-9]+]] -pub fn foo116(_: Type3, _: Type3, _: Type3) { } +pub fn foo116(_: Type3, _: Type3, _: Type3) {} // CHECK: define{{.*}}foo116{{.*}}!type ![[TYPE116:[0-9]+]] -pub fn foo117(_: Type4) { } +pub fn foo117(_: Type4) {} // CHECK: define{{.*}}foo117{{.*}}!type ![[TYPE117:[0-9]+]] -pub fn foo118(_: Type4, _: Type4) { } +pub fn foo118(_: Type4, _: Type4) {} // CHECK: define{{.*}}foo118{{.*}}!type ![[TYPE118:[0-9]+]] -pub fn foo119(_: Type4, _: Type4, _: Type4) { } +pub fn foo119(_: Type4, _: Type4, _: Type4) {} // CHECK: define{{.*}}foo119{{.*}}!type ![[TYPE119:[0-9]+]] -pub fn foo120(_: Type5) { } +pub fn foo120(_: Type5) {} // CHECK: define{{.*}}foo120{{.*}}!type ![[TYPE120:[0-9]+]] -pub fn foo121(_: Type5, _: Type5) { } +pub fn foo121(_: Type5, _: Type5) {} // CHECK: define{{.*}}foo121{{.*}}!type ![[TYPE121:[0-9]+]] -pub fn foo122(_: Type5, _: Type5, _: Type5) { } +pub fn foo122(_: Type5, _: Type5, _: Type5) {} // CHECK: define{{.*}}foo122{{.*}}!type ![[TYPE122:[0-9]+]] -pub fn foo123(_: Type6) { } +pub fn foo123(_: Type6) {} // CHECK: define{{.*}}foo123{{.*}}!type ![[TYPE123:[0-9]+]] -pub fn foo124(_: Type6, _: Type6) { } +pub fn foo124(_: Type6, _: Type6) {} // CHECK: define{{.*}}foo124{{.*}}!type ![[TYPE124:[0-9]+]] -pub fn foo125(_: Type6, _: Type6, _: Type6) { } +pub fn foo125(_: Type6, _: Type6, _: Type6) {} // CHECK: define{{.*}}foo125{{.*}}!type ![[TYPE125:[0-9]+]] -pub fn foo126(_: Type7) { } +pub fn foo126(_: Type7) {} // CHECK: define{{.*}}foo126{{.*}}!type ![[TYPE126:[0-9]+]] -pub fn foo127(_: Type7, _: Type7) { } +pub fn foo127(_: Type7, _: Type7) {} // CHECK: define{{.*}}foo127{{.*}}!type ![[TYPE127:[0-9]+]] -pub fn foo128(_: Type7, _: Type7, _: Type7) { } +pub fn foo128(_: Type7, _: Type7, _: Type7) {} // CHECK: define{{.*}}foo128{{.*}}!type ![[TYPE128:[0-9]+]] -pub fn foo129(_: Type8) { } +pub fn foo129(_: Type8) {} // CHECK: define{{.*}}foo129{{.*}}!type ![[TYPE129:[0-9]+]] -pub fn foo130(_: Type8, _: Type8) { } +pub fn foo130(_: Type8, _: Type8) {} // CHECK: define{{.*}}foo130{{.*}}!type ![[TYPE130:[0-9]+]] -pub fn foo131(_: Type8, _: Type8, _: Type8) { } +pub fn foo131(_: Type8, _: Type8, _: Type8) {} // CHECK: define{{.*}}foo131{{.*}}!type ![[TYPE131:[0-9]+]] -pub fn foo132(_: Type9) { } +pub fn foo132(_: Type9) {} // CHECK: define{{.*}}foo132{{.*}}!type ![[TYPE132:[0-9]+]] -pub fn foo133(_: Type9, _: Type9) { } +pub fn foo133(_: Type9, _: Type9) {} // CHECK: define{{.*}}foo133{{.*}}!type ![[TYPE133:[0-9]+]] -pub fn foo134(_: Type9, _: Type9, _: Type9) { } +pub fn foo134(_: Type9, _: Type9, _: Type9) {} // CHECK: define{{.*}}foo134{{.*}}!type ![[TYPE134:[0-9]+]] -pub fn foo135(_: Type10) { } +pub fn foo135(_: Type10) {} // CHECK: define{{.*}}foo135{{.*}}!type ![[TYPE135:[0-9]+]] -pub fn foo136(_: Type10, _: Type10) { } +pub fn foo136(_: Type10, _: Type10) {} // CHECK: define{{.*}}foo136{{.*}}!type ![[TYPE136:[0-9]+]] -pub fn foo137(_: Type10, _: Type10, _: Type10) { } +pub fn foo137(_: Type10, _: Type10, _: Type10) {} // CHECK: define{{.*}}foo137{{.*}}!type ![[TYPE137:[0-9]+]] -pub fn foo138(_: Type11) { } +pub fn foo138(_: Type11) {} // CHECK: define{{.*}}foo138{{.*}}!type ![[TYPE138:[0-9]+]] -pub fn foo139(_: Type11, _: Type11) { } +pub fn foo139(_: Type11, _: Type11) {} // CHECK: define{{.*}}foo139{{.*}}!type ![[TYPE139:[0-9]+]] -pub fn foo140(_: Type11, _: Type11, _: Type11) { } +pub fn foo140(_: Type11, _: Type11, _: Type11) {} // CHECK: define{{.*}}foo140{{.*}}!type ![[TYPE140:[0-9]+]] -pub fn foo141(_: Type12) { } +pub fn foo141(_: Type12) {} // CHECK: define{{.*}}foo141{{.*}}!type ![[TYPE141:[0-9]+]] -pub fn foo142(_: Type12, _: Type12) { } +pub fn foo142(_: Type12, _: Type12) {} // CHECK: define{{.*}}foo142{{.*}}!type ![[TYPE142:[0-9]+]] -pub fn foo143(_: Type12, _: Type12, _: Type12) { } +pub fn foo143(_: Type12, _: Type12, _: Type12) {} // CHECK: define{{.*}}foo143{{.*}}!type ![[TYPE143:[0-9]+]] -pub fn foo144(_: Type13) { } +pub fn foo144(_: Type13) {} // CHECK: define{{.*}}foo144{{.*}}!type ![[TYPE144:[0-9]+]] -pub fn foo145(_: Type13, _: Type13) { } +pub fn foo145(_: Type13, _: Type13) {} // CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]] -pub fn foo146(_: Type13, _: Type13, _: Type13) { } +pub fn foo146(_: Type13, _: Type13, _: Type13) {} // CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]] -pub fn foo147(_: Type14) { } +pub fn foo147(_: Type14) {} // CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]] -pub fn foo148(_: Type14, _: Type14) { } +pub fn foo148(_: Type14, _: Type14) {} // CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]] -pub fn foo149(_: Type14, _: Type14, _: Type14) { } +pub fn foo149(_: Type14, _: Type14, _: Type14) {} // CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]] // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"} diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index 6dfd7f6840f1b..ff4c1b4ccad0d 100644 --- a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -12,7 +12,10 @@ fn define() -> Bar { type Foo2 = impl Debug; -fn define2() { +fn define2() +where + Foo2: Debug, +{ let x = || -> Foo2 { 42 }; } @@ -21,13 +24,19 @@ type Foo3 = impl Debug; fn define3(x: Foo3) { let y: i32 = x; } -fn define3_1() { +fn define3_1() +where + Foo3: Debug, +{ define3(42) } type Foo4 = impl Debug; -fn define4() { +fn define4() +where + Foo4: Debug, +{ let y: Foo4 = 42; } diff --git a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs index d2c3479203573..86648e81f752b 100644 --- a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs +++ b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs @@ -8,8 +8,13 @@ impl SuperExpectation for T {} type Foo = impl SuperExpectation; -fn main() { +fn foo() +where + Foo: SuperExpectation, +{ let _: Foo = |x| { let _ = x.to_string(); }; } + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-70877.rs b/tests/ui/impl-trait/issues/issue-70877.rs index 8169cfafac711..42e5436390cbc 100644 --- a/tests/ui/impl-trait/issues/issue-70877.rs +++ b/tests/ui/impl-trait/issues/issue-70877.rs @@ -1,5 +1,7 @@ #![feature(type_alias_impl_trait)] +// check-pass + type FooArg<'a> = &'a dyn ToString; type FooRet = impl std::fmt::Debug; @@ -28,7 +30,7 @@ fn ham() -> Foo { fn oof() -> impl std::fmt::Debug { let mut bar = ham(); let func = bar.next().unwrap(); - return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type + return func(&"oof"); } fn main() { diff --git a/tests/ui/impl-trait/issues/issue-70877.stderr b/tests/ui/impl-trait/issues/issue-70877.stderr deleted file mode 100644 index 8813bff3c353e..0000000000000 --- a/tests/ui/impl-trait/issues/issue-70877.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/issue-70877.rs:31:12 - | -LL | return func(&"oof"); - | ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope - | -note: opaque type whose hidden type is being assigned - --> $DIR/issue-70877.rs:28:13 - | -LL | fn oof() -> impl std::fmt::Debug { - | ^^^^^^^^^^^^^^^^^^^^ -note: opaque type being used as hidden type - --> $DIR/issue-70877.rs:4:15 - | -LL | type FooRet = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/impl-trait/issues/issue-74282.rs b/tests/ui/impl-trait/issues/issue-74282.rs index 654de0cd0253c..7e377644799bd 100644 --- a/tests/ui/impl-trait/issues/issue-74282.rs +++ b/tests/ui/impl-trait/issues/issue-74282.rs @@ -3,9 +3,18 @@ type Closure = impl Fn() -> u64; struct Anonymous(Closure); -fn main() { +fn fop() +where + Anonymous: 'static, +{ let y = || -> Closure { || 3 }; - Anonymous(|| { //~ ERROR mismatched types - 3 //~^ ERROR mismatched types + Anonymous(|| { + //~^ ERROR mismatched types + //~| ERROR mismatched types + 3 }) } + +fn main() { + fop(); +} diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr index 5b05fb2810dff..785d4919b1cea 100644 --- a/tests/ui/impl-trait/issues/issue-74282.stderr +++ b/tests/ui/impl-trait/issues/issue-74282.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-74282.rs:8:15 + --> $DIR/issue-74282.rs:11:15 | LL | type Closure = impl Fn() -> u64; | ---------------- the expected opaque type @@ -8,12 +8,14 @@ LL | Anonymous(|| { | _____---------_^ | | | | | arguments to this struct are incorrect +LL | | +LL | | LL | | 3 LL | | }) | |_____^ expected closure, found a different closure | = note: expected opaque type `Closure` - found closure `[closure@$DIR/issue-74282.rs:8:15: 8:17]` + found closure `[closure@$DIR/issue-74282.rs:11:15: 11:17]` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object note: tuple struct defined here @@ -23,17 +25,23 @@ LL | struct Anonymous(Closure); | ^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/issue-74282.rs:8:5 + --> $DIR/issue-74282.rs:11:5 | -LL | fn main() { - | - expected `()` because of default return type -LL | let y = || -> Closure { || 3 }; LL | / Anonymous(|| { +LL | | +LL | | LL | | 3 LL | | }) - | | ^- help: consider using a semicolon here: `;` - | |______| - | expected `()`, found struct `Anonymous` + | |______^ expected `()`, found struct `Anonymous` + | +help: consider using a semicolon here + | +LL | }); + | + +help: try adding a return type + | +LL | -> Anonymous where + | ++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-78722.global.stderr b/tests/ui/impl-trait/issues/issue-78722.global.stderr new file mode 100644 index 0000000000000..bf43b723ff854 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-78722.global.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-78722.rs:18:20 + | +LL | type F = impl core::future::Future; + | -------------------------------------- the expected opaque type +... +LL | let f: F = async { 1 }; + | ^^^^^^^^^^^ + | | + | expected opaque type, found `async` block + | arguments to this function are incorrect + | + = note: expected opaque type `F` + found `async` block `[async block@$DIR/issue-78722.rs:18:20: 18:31]` +note: function defined here + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.in_const.stderr similarity index 79% rename from tests/ui/impl-trait/issues/issue-78722.stderr rename to tests/ui/impl-trait/issues/issue-78722.in_const.stderr index c00df8087e895..790b4135b8923 100644 --- a/tests/ui/impl-trait/issues/issue-78722.stderr +++ b/tests/ui/impl-trait/issues/issue-78722.in_const.stderr @@ -1,5 +1,5 @@ error[E0658]: `async` blocks are not allowed in constants - --> $DIR/issue-78722.rs:13:20 + --> $DIR/issue-78722.rs:18:20 | LL | let f: F = async { 1 }; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let f: F = async { 1 }; = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable error[E0493]: destructor of `F` cannot be evaluated at compile-time - --> $DIR/issue-78722.rs:13:13 + --> $DIR/issue-78722.rs:18:13 | LL | let f: F = async { 1 }; | ^ the destructor for this type cannot be evaluated in constants @@ -16,8 +16,8 @@ LL | let f: F = async { 1 }; LL | }], | - value is dropped here -error[E0271]: expected `[async block@$DIR/issue-78722.rs:11:13: 11:21]` to be a future that resolves to `u8`, but it resolves to `()` - --> $DIR/issue-78722.rs:9:30 +error[E0271]: expected `[async block@$DIR/issue-78722.rs:16:13: 16:21]` to be a future that resolves to `u8`, but it resolves to `()` + --> $DIR/issue-78722.rs:14:30 | LL | fn concrete_use() -> F { | ^ expected `()`, found `u8` diff --git a/tests/ui/impl-trait/issues/issue-78722.rs b/tests/ui/impl-trait/issues/issue-78722.rs index 78233f300bdd0..848a5c7d7e93a 100644 --- a/tests/ui/impl-trait/issues/issue-78722.rs +++ b/tests/ui/impl-trait/issues/issue-78722.rs @@ -1,18 +1,24 @@ // edition:2018 +// revisions: global in_const + #![feature(type_alias_impl_trait)] +#[cfg(global)] type F = impl core::future::Future; struct Bug { V1: [(); { + #[cfg(in_const)] + type F = impl core::future::Future; fn concrete_use() -> F { - //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()` + //[in_const]~^ ERROR to be a future that resolves to `u8`, but it resolves to `()` async {} } let f: F = async { 1 }; - //~^ ERROR `async` blocks are not allowed in constants - //~| ERROR destructor of + //[in_const]~^ ERROR `async` blocks are not allowed in constants + //[in_const]~| ERROR destructor of + //[global]~^^^ ERROR mismatched types 1 }], } diff --git a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs index 962606508be7a..09b67b18449b7 100644 --- a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs +++ b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs @@ -5,15 +5,14 @@ trait Trait { type Opaque1; type Opaque2; - fn constrain(self); + fn constrain(self) -> (Self::Opaque1, Self::Opaque2); } impl<'a> Trait for &'a () { type Opaque1 = impl Sized; type Opaque2 = impl Sized + 'a; - fn constrain(self) { - let _: Self::Opaque1 = (); - let _: Self::Opaque2 = self; + fn constrain(self) -> (Self::Opaque1, Self::Opaque2) { + ((), self) } } diff --git a/tests/ui/type-alias-impl-trait/closure_args.rs b/tests/ui/type-alias-impl-trait/closure_args.rs index c5e7af81d3dd0..0bd855dcedd44 100644 --- a/tests/ui/type-alias-impl-trait/closure_args.rs +++ b/tests/ui/type-alias-impl-trait/closure_args.rs @@ -11,6 +11,18 @@ fn run ()>(f: F, i: Input) { f(i); } +fn foo() +where + Input: Anything, +{ + run( + |x: u32| { + println!("{x}"); + }, + 0, + ); +} + fn main() { - run(|x: u32| {println!("{x}");}, 0); + foo(); } diff --git a/tests/ui/type-alias-impl-trait/closure_args2.rs b/tests/ui/type-alias-impl-trait/closure_args2.rs index 82386c280a8e3..2ec10d5aefa02 100644 --- a/tests/ui/type-alias-impl-trait/closure_args2.rs +++ b/tests/ui/type-alias-impl-trait/closure_args2.rs @@ -4,7 +4,9 @@ trait Foo { // This was reachable in https://github.com/rust-lang/rust/issues/100800 - fn foo(&self) { unreachable!() } + fn foo(&self) { + unreachable!() + } } impl Foo for T {} @@ -14,10 +16,21 @@ impl B { } type Input = impl Foo; -fn run1(f: F, i: Input) {f(i)} -fn run2(f: F, i: B) {f(i)} +fn run1(f: F, i: Input) { + f(i) +} +fn run2(f: F, i: B) { + f(i) +} + +fn foo() +where + Input: Foo, +{ + run1(|x: B| x.foo(), B); + run2(|x: B| x.foo(), B); +} fn main() { - run1(|x: B| {x.foo()}, B); - run2(|x: B| {x.foo()}, B); + foo(); } diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index d3e169a70d3f7..e3b18893af696 100644 --- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -1,6 +1,9 @@ #![feature(type_alias_impl_trait)] -fn main() { +fn foo() +where + WrongGeneric: 'static, +{ let y = 42; let x = wrong_generic(&y); let z: i32 = x; @@ -14,3 +17,7 @@ fn wrong_generic(t: T) -> WrongGeneric { t //~^ ERROR the parameter type `T` may not live long enough } + +fn main() { + foo(); +} diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 19115fd28662b..b20d2377c6a62 100644 --- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -1,11 +1,11 @@ error: at least one trait must be specified - --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 + --> $DIR/generic_type_does_not_live_long_enough.rs:13:24 | LL | type WrongGeneric = impl 'static; | ^^^^^^^^^^^^ error[E0792]: expected generic type parameter, found `&'static i32` - --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 + --> $DIR/generic_type_does_not_live_long_enough.rs:9:18 | LL | let z: i32 = x; | ^ @@ -14,7 +14,7 @@ LL | type WrongGeneric = impl 'static; | - this generic parameter must be used with a generic type parameter error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 + --> $DIR/generic_type_does_not_live_long_enough.rs:17:5 | LL | t | ^ ...so that the type `T` will meet its required lifetime bounds diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs index 79caddf791320..34a68631d23b5 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.rs +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -15,8 +15,9 @@ mod m { is_send(foo()); // Today: error } - fn baz() { + fn baz() -> Foo { let f: Foo = 22_u32; + f } fn is_send(_: T) {} diff --git a/tests/ui/type-alias-impl-trait/issue-57961.rs b/tests/ui/type-alias-impl-trait/issue-57961.rs index 4aa5966ff25d4..4b22de66efe10 100644 --- a/tests/ui/type-alias-impl-trait/issue-57961.rs +++ b/tests/ui/type-alias-impl-trait/issue-57961.rs @@ -11,8 +11,8 @@ impl Foo for () { //~^ ERROR expected `IntoIter` to be an iterator that yields `X`, but it yields `u32` } -fn incoherent() { - let f: X = 22_i32; +fn incoherent() -> X { + 22_i32; } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs index 7414611a74893..2062f8b97c838 100644 --- a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs +++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs @@ -8,6 +8,13 @@ pub type Closure = impl FnOnce(); -fn main() { +fn foo() +where + Closure: FnOnce(), +{ || -> Closure { || () }; } + +fn main() { + foo(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs index 72c22827f624b..f8f6302345431 100644 --- a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs +++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -12,7 +12,12 @@ type T = impl Sized; fn take(_: fn() -> T) {} -fn main() { +fn foo() +where + T: Sized, +{ take(|| {}); take(|| {}); } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs index 60b6e1aac6281..0a1e0aa232939 100644 --- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs @@ -1,5 +1,7 @@ #![feature(type_alias_impl_trait)] +// check-pass + mod my_mod { use std::fmt::Debug; @@ -11,7 +13,7 @@ mod my_mod { } pub fn get_foot() -> Foot { - get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type + get_foo() } } diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr deleted file mode 100644 index fa6ecf68d28f3..0000000000000 --- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/nested_type_alias_impl_trait.rs:14:9 - | -LL | get_foo() - | ^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope - | -note: opaque type whose hidden type is being assigned - --> $DIR/nested_type_alias_impl_trait.rs:7:21 - | -LL | pub type Foot = impl Debug; - | ^^^^^^^^^^ -note: opaque type being used as hidden type - --> $DIR/nested_type_alias_impl_trait.rs:6:20 - | -LL | pub type Foo = impl Debug; - | ^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs index 7ecb553530106..475ca88747b7a 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.rs +++ b/tests/ui/type-alias-impl-trait/reveal_local.rs @@ -4,8 +4,9 @@ use std::fmt::Debug; type Foo = impl Debug; //~^ ERROR cycle detected +//~| ERROR cycle detected -fn is_send() { } +fn is_send() {} fn not_good() { // Error: this function does not constrain `Foo` to any particular @@ -13,7 +14,10 @@ fn not_good() { is_send::(); } -fn not_gooder() { +fn not_gooder() +where + Foo: Debug, +{ // Constrain `Foo = u32` let x: Foo = 22_u32; diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr index 27fded3332921..4047cf4be2045 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.stderr +++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr @@ -5,7 +5,7 @@ LL | type Foo = impl Debug; | ^^^^^^^^^^ | note: ...which requires type-checking `not_good`... - --> $DIR/reveal_local.rs:13:5 + --> $DIR/reveal_local.rs:14:5 | LL | is_send::(); | ^^^^^^^^^^^^^^ @@ -23,6 +23,31 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_gooder`... + --> $DIR/reveal_local.rs:26:5 + | +LL | is_send::(); + | ^^^^^^^^^^^^^^ + = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`... + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs index 4e9d1788b94d8..c8d6d993ac6e0 100644 --- a/tests/ui/type-alias-impl-trait/type_of_a_let.rs +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs @@ -5,12 +5,18 @@ use std::fmt::Debug; type Foo = impl Debug; -fn foo1() -> u32 { +fn foo1() -> u32 +where + Foo: Debug, +{ let x: Foo = 22_u32; x } -fn foo2() -> u32 { +fn foo2() -> u32 +where + Foo: Debug, +{ let x: Foo = 22_u32; let y: Foo = x; same_type((x, y)); //~ ERROR use of moved value diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr index 1dabe4586c5b9..396786a08ebe4 100644 --- a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x` - --> $DIR/type_of_a_let.rs:16:16 + --> $DIR/type_of_a_let.rs:22:16 | LL | let x: Foo = 22_u32; | - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait @@ -9,7 +9,7 @@ LL | same_type((x, y)); | ^ value used here after move error[E0382]: use of moved value: `y` - --> $DIR/type_of_a_let.rs:17:5 + --> $DIR/type_of_a_let.rs:23:5 | LL | let y: Foo = x; | - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait From 3f0b21f1df103f616b23c38cb234c42a82f09c5d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 23 Jan 2023 16:50:04 +0000 Subject: [PATCH 2/7] Add some more tests --- tests/ui/impl-trait/issues/issue-74282.rs | 14 ++-------- .../defining-scopes-cycle-prevention.rs | 19 +++++++++++++ .../defining-scopes-cycle-prevention.stderr | 28 +++++++++++++++++++ .../defining-scopes-in_type.rs | 16 +++++++++++ .../defining-scopes-in_type.stderr | 17 +++++++++++ .../defining-scopes-semantic.rs | 14 ++++++++++ .../defining-scopes-syntactic.rs | 18 ++++++++++++ .../defining-scopes-syntactic.stderr | 24 ++++++++++++++++ .../defining-scopes-syntacticish.rs | 18 ++++++++++++ .../defining-scopes.stderr | 17 +++++++++++ .../issue-63263-closure-return.rs | 12 ++------ 11 files changed, 176 insertions(+), 21 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-in_type.rs create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-in_type.stderr create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-semantic.rs create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-syntacticish.rs create mode 100644 tests/ui/type-alias-impl-trait/defining-scopes.stderr diff --git a/tests/ui/impl-trait/issues/issue-74282.rs b/tests/ui/impl-trait/issues/issue-74282.rs index 7e377644799bd..00c5cc723ac87 100644 --- a/tests/ui/impl-trait/issues/issue-74282.rs +++ b/tests/ui/impl-trait/issues/issue-74282.rs @@ -1,12 +1,8 @@ #![feature(type_alias_impl_trait)] -type Closure = impl Fn() -> u64; -struct Anonymous(Closure); - -fn fop() -where - Anonymous: 'static, -{ +fn main() { + type Closure = impl Fn() -> u64; + struct Anonymous(Closure); let y = || -> Closure { || 3 }; Anonymous(|| { //~^ ERROR mismatched types @@ -14,7 +10,3 @@ where 3 }) } - -fn main() { - fop(); -} diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs b/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs new file mode 100644 index 0000000000000..6728553d71cab --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +// Check that, even within the defining scope, we can get the +// `Send` or `Sync` bound of a TAIT, as long as the current function +// doesn't mention those TAITs in the signature +type Foo = impl std::fmt::Debug; +//~^ ERROR cycle detected + +fn is_send() {} + +fn foo() -> Foo { + 42 +} + +fn bar() { + is_send::(); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr b/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr new file mode 100644 index 0000000000000..00b5d3f6eb781 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr @@ -0,0 +1,28 @@ +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/defining-scopes-cycle-prevention.rs:6:12 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `bar`... + --> $DIR/defining-scopes-cycle-prevention.rs:16:5 + | +LL | is_send::(); + | ^^^^^^^^^^^^^^ + = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`... + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/defining-scopes-cycle-prevention.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | // Check that, even within the defining scope, we can get the +LL | | // `Send` or `Sync` bound of a TAIT, as long as the current function +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-in_type.rs b/tests/ui/type-alias-impl-trait/defining-scopes-in_type.rs new file mode 100644 index 0000000000000..18b3c1127da15 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-in_type.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +// check that we don't allow defining hidden types of TAITs in +// const generic defaults. +type Foo = impl Send; + +#[rustfmt::skip] +struct Struct< + const C: usize = { + let _: Foo = (); + //~^ ERROR: mismatched types + 0 + }, +>; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-in_type.stderr b/tests/ui/type-alias-impl-trait/defining-scopes-in_type.stderr new file mode 100644 index 0000000000000..4fd3465d75fb5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-in_type.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/defining-scopes-in_type.rs:10:22 + | +LL | type Foo = impl Send; + | --------- the expected opaque type +... +LL | let _: Foo = (); + | --- ^^ expected opaque type, found `()` + | | + | expected due to this + | + = note: expected opaque type `Foo` + found unit type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-semantic.rs b/tests/ui/type-alias-impl-trait/defining-scopes-semantic.rs new file mode 100644 index 0000000000000..4ec37cbcd648c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-semantic.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +type Foo = impl std::fmt::Debug; + +struct Wrap(Foo); + +// Check that fields count as defining uses, too +fn h() -> Wrap { + Wrap(42) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs new file mode 100644 index 0000000000000..9daa3c00afd82 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +// Check that we cannot syntactically mention a TAIT without +// it also being part of the type. + +type DropType = (); +//~^ ERROR type parameter `T` is unused + +type Foo = impl std::fmt::Debug; +// Check that, even though `Foo` is not part +// of the actual type, we do allow this to be a defining scope +fn g() -> DropType { + let _: Foo = 42; + //~^ ERROR: mismatched types + () +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr new file mode 100644 index 0000000000000..d345b9efbbe9b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr @@ -0,0 +1,24 @@ +error[E0091]: type parameter `T` is unused + --> $DIR/defining-scopes-syntactic.rs:6:15 + | +LL | type DropType = (); + | ^ unused type parameter + +error[E0308]: mismatched types + --> $DIR/defining-scopes-syntactic.rs:13:18 + | +LL | type Foo = impl std::fmt::Debug; + | -------------------- the expected opaque type +... +LL | let _: Foo = 42; + | --- ^^ expected opaque type, found integer + | | + | expected due to this + | + = note: expected opaque type `Foo` + found type `{integer}` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0091, E0308. +For more information about an error, try `rustc --explain E0091`. diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-syntacticish.rs b/tests/ui/type-alias-impl-trait/defining-scopes-syntacticish.rs new file mode 100644 index 0000000000000..07fd7fbacf4b0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-syntacticish.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +// Check that we cannot syntactically mention a TAIT without +// it also being part of the type. + +struct DropType(std::marker::PhantomData); + +type Foo = impl std::fmt::Debug; +// Check that, even though `Foo` is not part +// of the actual type, we do allow this to be a defining scope +fn g() -> DropType { + let _: Foo = 42; + DropType(std::marker::PhantomData) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defining-scopes.stderr b/tests/ui/type-alias-impl-trait/defining-scopes.stderr new file mode 100644 index 0000000000000..93a3670606cd1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/defining-scopes.rs:10:26 + | +LL | type Foo = impl Send; + | --------- the expected opaque type +... +LL | let _: Foo = (); + | --- ^^ expected opaque type, found `()` + | | + | expected due to this + | + = note: expected opaque type `in_type::Foo` + found unit type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs index 2062f8b97c838..5bd674cc6a0b6 100644 --- a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs +++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs @@ -6,15 +6,7 @@ #![feature(type_alias_impl_trait)] -pub type Closure = impl FnOnce(); - -fn foo() -where - Closure: FnOnce(), -{ - || -> Closure { || () }; -} - fn main() { - foo(); + pub type Closure = impl FnOnce(); + || -> Closure { || () }; } From ddfdbe0d468ae9a2890935d3f4a7226f6e5e8dc3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 23 Jan 2023 17:20:01 +0000 Subject: [PATCH 3/7] Remove an unnecessary argument --- compiler/rustc_infer/src/infer/opaque_types.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 447f1e6116463..df05df0d0c194 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -380,7 +380,6 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, param_env: ty::ParamEnv<'tcx>, ) -> Option { - let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = match self.defining_use_anchor { DefiningAnchor::Bubble | DefiningAnchor::Error => return None, DefiningAnchor::Bind(bind) => bind, @@ -402,7 +401,7 @@ impl<'tcx> InferCtxt<'tcx> { hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` hir::OpaqueTyOrigin::TyAlias => { - may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id, def_id, param_env) + may_define_opaque_type(self.tcx, parent_def_id, def_id, param_env) } }; trace!(?origin); @@ -650,10 +649,10 @@ impl<'tcx> InferCtxt<'tcx> { fn may_define_opaque_type<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, - opaque_hir_id: hir::HirId, opaque_def_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, ) -> bool { + let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id); let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); // Named opaque types can be defined by any siblings or children of siblings. From 6e354fb13db18c1af8bda4c2208d78caf7b17af6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 23 Jan 2023 17:25:05 +0000 Subject: [PATCH 4/7] Remove another unneeded argument --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../rustc_infer/src/infer/opaque_types.rs | 24 +++++++------------ 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c69c73d1e5101..6ed8adb47425a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -680,7 +680,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind() && let Some(def_id) = def_id.as_local() - && self.opaque_type_origin(def_id, DUMMY_SP, self.param_env).is_some() { + && self.opaque_type_origin(def_id, DUMMY_SP).is_some() { return None; } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index df05df0d0c194..5e370f6803026 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -60,7 +60,7 @@ impl<'tcx> InferCtxt<'tcx> { let replace_opaque_type = |def_id: DefId| { def_id .as_local() - .map_or(false, |def_id| self.opaque_type_origin(def_id, span, param_env).is_some()) + .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some()) }; let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, @@ -145,7 +145,7 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - self.opaque_type_origin(def_id, cause.span, param_env)? + self.opaque_type_origin(def_id, cause.span)? } DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span), DefiningAnchor::Error => return None, @@ -156,10 +156,9 @@ impl<'tcx> InferCtxt<'tcx> { // no one encounters it in practice. // It does occur however in `fn fut() -> impl Future { async { 42 } }`, // where it is of no concern, so we only check for TAITs. - if let Some(OpaqueTyOrigin::TyAlias) = - b_def_id.as_local().and_then(|b_def_id| { - self.opaque_type_origin(b_def_id, cause.span, param_env) - }) + if let Some(OpaqueTyOrigin::TyAlias) = b_def_id + .as_local() + .and_then(|b_def_id| self.opaque_type_origin(b_def_id, cause.span)) { self.tcx.sess.emit_err(OpaqueHiddenTypeDiag { span: cause.span, @@ -374,12 +373,7 @@ impl<'tcx> InferCtxt<'tcx> { } #[instrument(skip(self), level = "trace", ret)] - pub fn opaque_type_origin( - &self, - def_id: LocalDefId, - span: Span, - param_env: ty::ParamEnv<'tcx>, - ) -> Option { + pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option { let parent_def_id = match self.defining_use_anchor { DefiningAnchor::Bubble | DefiningAnchor::Error => return None, DefiningAnchor::Bind(bind) => bind, @@ -400,9 +394,7 @@ impl<'tcx> InferCtxt<'tcx> { // Anonymous `impl Trait` hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` - hir::OpaqueTyOrigin::TyAlias => { - may_define_opaque_type(self.tcx, parent_def_id, def_id, param_env) - } + hir::OpaqueTyOrigin::TyAlias => may_define_opaque_type(self.tcx, parent_def_id, def_id), }; trace!(?origin); in_definition_scope.then_some(*origin) @@ -650,8 +642,8 @@ fn may_define_opaque_type<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, opaque_def_id: LocalDefId, - param_env: ty::ParamEnv<'tcx>, ) -> bool { + let param_env = tcx.param_env(def_id); let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id); let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); From b105e2aff7954093741493a5a7f5c48eef849b81 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 23 Jan 2023 17:52:00 +0000 Subject: [PATCH 5/7] Actually prevent cycle errors --- .../rustc_hir_analysis/src/collect/type_of.rs | 7 +++++ .../rustc_infer/src/infer/opaque_types.rs | 10 ++++++- .../auto-trait-leakage3.rs | 3 +- .../auto-trait-leakage3.stderr | 22 -------------- .../defining-scopes-cycle-prevention.rs | 3 +- .../defining-scopes-cycle-prevention.stderr | 28 ------------------ .../defining-scopes-syntactic.rs | 2 ++ .../defining-scopes-syntactic.stderr | 12 ++++++-- .../defining-scopes.stderr | 17 ----------- .../impl_trait_for_tait_bound.rs | 17 ++++++----- .../impl_trait_for_tait_bound.stderr | 6 ++-- .../impl_trait_for_tait_bound2.rs | 9 +++--- .../impl_trait_for_tait_bound2.stderr | 6 ++-- .../type-alias-impl-trait/inference-cycle.rs | 2 +- .../inference-cycle.stderr | 24 +++++---------- tests/ui/type-alias-impl-trait/nested.rs | 1 + tests/ui/type-alias-impl-trait/nested.stderr | 12 ++++++-- .../ui/type-alias-impl-trait/reveal_local.rs | 1 - .../type-alias-impl-trait/reveal_local.stderr | 29 ++----------------- 19 files changed, 73 insertions(+), 138 deletions(-) delete mode 100644 tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr delete mode 100644 tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr delete mode 100644 tests/ui/type-alias-impl-trait/defining-scopes.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 1f9a9f80302e3..c66c0bdeb1ca4 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -4,6 +4,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::{HirId, Node}; +use rustc_infer::infer::opaque_types::may_define_opaque_type; use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; @@ -589,6 +590,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T debug!("no constraint: no typeck results"); return; } + + if !may_define_opaque_type(self.tcx, item_def_id, self.def_id) { + debug!("no constraint: does not have TAIT in signature"); + return; + } + // Calling `mir_borrowck` can lead to cycle errors through // const-checking, avoid calling it if we don't have to. // ```rust diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 5e370f6803026..149ddf0b3ce39 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -638,11 +638,19 @@ impl<'tcx> InferCtxt<'tcx> { /// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. /// For the above example, this function returns `true` for `f1` and `false` for `f2`. #[instrument(skip(tcx), level = "trace", ret)] -fn may_define_opaque_type<'tcx>( +pub fn may_define_opaque_type<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, opaque_def_id: LocalDefId, ) -> bool { + if tcx.is_closure(def_id.to_def_id()) { + return may_define_opaque_type( + tcx, + tcx.parent(def_id.to_def_id()).expect_local(), + opaque_def_id, + ); + } + let param_env = tcx.param_env(def_id); let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id); let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs index 5fb7a9473d3df..5f0b3963b5004 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -1,11 +1,10 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] -// FIXME This should compile, but it currently doesn't +// check-pass mod m { type Foo = impl std::fmt::Debug; - //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] pub fn foo() -> Foo { 22_u32 diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr deleted file mode 100644 index 1e9a45aac79e9..0000000000000 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` - --> $DIR/auto-trait-leakage3.rs:7:16 - | -LL | type Foo = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires type-checking `m::bar`... - --> $DIR/auto-trait-leakage3.rs:15:9 - | -LL | is_send(foo()); - | ^^^^^^^ - = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`... - = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in module `m` - --> $DIR/auto-trait-leakage3.rs:6:1 - | -LL | mod m { - | ^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs b/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs index 6728553d71cab..8819b068c6be1 100644 --- a/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs +++ b/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs @@ -1,10 +1,11 @@ #![feature(type_alias_impl_trait)] +// check-pass + // Check that, even within the defining scope, we can get the // `Send` or `Sync` bound of a TAIT, as long as the current function // doesn't mention those TAITs in the signature type Foo = impl std::fmt::Debug; -//~^ ERROR cycle detected fn is_send() {} diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr b/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr deleted file mode 100644 index 00b5d3f6eb781..0000000000000 --- a/tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/defining-scopes-cycle-prevention.rs:6:12 - | -LL | type Foo = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires type-checking `bar`... - --> $DIR/defining-scopes-cycle-prevention.rs:16:5 - | -LL | is_send::(); - | ^^^^^^^^^^^^^^ - = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`... - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/defining-scopes-cycle-prevention.rs:1:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | // Check that, even within the defining scope, we can get the -LL | | // `Send` or `Sync` bound of a TAIT, as long as the current function -... | -LL | | -LL | | fn main() {} - | |____________^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs index 9daa3c00afd82..85280c905ef11 100644 --- a/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs +++ b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs @@ -7,6 +7,8 @@ type DropType = (); //~^ ERROR type parameter `T` is unused type Foo = impl std::fmt::Debug; +//~^ ERROR unconstrained opaque type + // Check that, even though `Foo` is not part // of the actual type, we do allow this to be a defining scope fn g() -> DropType { diff --git a/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr index d345b9efbbe9b..d0639ac013617 100644 --- a/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr +++ b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr @@ -4,8 +4,16 @@ error[E0091]: type parameter `T` is unused LL | type DropType = (); | ^ unused type parameter +error: unconstrained opaque type + --> $DIR/defining-scopes-syntactic.rs:9:12 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + error[E0308]: mismatched types - --> $DIR/defining-scopes-syntactic.rs:13:18 + --> $DIR/defining-scopes-syntactic.rs:15:18 | LL | type Foo = impl std::fmt::Debug; | -------------------- the expected opaque type @@ -18,7 +26,7 @@ LL | let _: Foo = 42; = note: expected opaque type `Foo` found type `{integer}` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0091, E0308. For more information about an error, try `rustc --explain E0091`. diff --git a/tests/ui/type-alias-impl-trait/defining-scopes.stderr b/tests/ui/type-alias-impl-trait/defining-scopes.stderr deleted file mode 100644 index 93a3670606cd1..0000000000000 --- a/tests/ui/type-alias-impl-trait/defining-scopes.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/defining-scopes.rs:10:26 - | -LL | type Foo = impl Send; - | --------- the expected opaque type -... -LL | let _: Foo = (); - | --- ^^ expected opaque type, found `()` - | | - | expected due to this - | - = note: expected opaque type `in_type::Foo` - found unit type `()` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs index 8ec20acef4de6..0f564ea74e4e5 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs @@ -3,17 +3,20 @@ use std::fmt::Debug; type Foo = impl Debug; -pub trait Yay { } -impl Yay for Foo { } +pub trait Yay {} +impl Yay for Foo {} -fn foo() { - is_yay::(); //~ ERROR: the trait bound `u32: Yay` is not satisfied +fn foo() +where + Foo: Debug, +{ + is_yay::(); //~ ERROR: the trait bound `u32: Yay` is not satisfied is_debug::(); // OK - is_yay::(); // OK + is_yay::(); // OK is_debug::(); // OK } -fn is_yay() { } -fn is_debug() { } +fn is_yay() {} +fn is_debug() {} fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr index 1c83105a18aff..fbcf863e9c5ee 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `u32: Yay` is not satisfied - --> $DIR/impl_trait_for_tait_bound.rs:10:14 + --> $DIR/impl_trait_for_tait_bound.rs:13:14 | LL | is_yay::(); | ^^^ the trait `Yay` is not implemented for `u32` | = help: the trait `Yay` is implemented for `Foo` note: required by a bound in `is_yay` - --> $DIR/impl_trait_for_tait_bound.rs:16:14 + --> $DIR/impl_trait_for_tait_bound.rs:19:14 | -LL | fn is_yay() { } +LL | fn is_yay() {} | ^^^ required by this bound in `is_yay` error: aborting due to previous error diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs index a4b8c2d190db9..d83c65093779b 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs @@ -2,15 +2,14 @@ use std::fmt::Debug; -type Foo = impl Debug; - -pub trait Yay { } -impl Yay for u32 { } +pub trait Yay {} +impl Yay for u32 {} fn foo() { + type Foo = impl Debug; is_yay::(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied } -fn is_yay() { } +fn is_yay() {} fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr index a6440f02c27d8..cae8b2246b5d9 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `Foo: Yay` is not satisfied - --> $DIR/impl_trait_for_tait_bound2.rs:11:14 + --> $DIR/impl_trait_for_tait_bound2.rs:10:14 | LL | is_yay::(); | ^^^ the trait `Yay` is not implemented for `Foo` | = help: the trait `Yay` is implemented for `u32` note: required by a bound in `is_yay` - --> $DIR/impl_trait_for_tait_bound2.rs:14:14 + --> $DIR/impl_trait_for_tait_bound2.rs:13:14 | -LL | fn is_yay() { } +LL | fn is_yay() {} | ^^^ required by this bound in `is_yay` error: aborting due to previous error diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs index 34a68631d23b5..8af12cac25e5e 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.rs +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -3,7 +3,6 @@ mod m { type Foo = impl std::fmt::Debug; - //~^ ERROR cycle detected // Cycle: error today, but it'd be nice if it eventually worked @@ -17,6 +16,7 @@ mod m { fn baz() -> Foo { let f: Foo = 22_u32; + //~^ ERROR concrete type differs f } diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr index b9d646b927a6f..4538f2a269791 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -1,22 +1,14 @@ -error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` - --> $DIR/inference-cycle.rs:5:16 +error: concrete type differs from previous defining opaque type use + --> $DIR/inference-cycle.rs:18:22 | -LL | type Foo = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ +LL | let f: Foo = 22_u32; + | ^^^^^^ expected `()`, got `u32` | -note: ...which requires type-checking `m::bar`... - --> $DIR/inference-cycle.rs:15:9 +note: previous use here + --> $DIR/inference-cycle.rs:10:9 | -LL | is_send(foo()); // Today: error - | ^^^^^^^ - = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`... - = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in module `m` - --> $DIR/inference-cycle.rs:4:1 - | -LL | mod m { - | ^^^^^ +LL | is_send(bar()) + | ^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/nested.rs b/tests/ui/type-alias-impl-trait/nested.rs index 6b866be7d173f..7f1999eb46e45 100644 --- a/tests/ui/type-alias-impl-trait/nested.rs +++ b/tests/ui/type-alias-impl-trait/nested.rs @@ -1,6 +1,7 @@ #![feature(type_alias_impl_trait)] type Foo = impl std::fmt::Debug; +//~^ ERROR: unconstrained opaque type type Bar = impl Trait; trait Trait {} diff --git a/tests/ui/type-alias-impl-trait/nested.stderr b/tests/ui/type-alias-impl-trait/nested.stderr index 732af5c0b561f..58c032f738f3a 100644 --- a/tests/ui/type-alias-impl-trait/nested.stderr +++ b/tests/ui/type-alias-impl-trait/nested.stderr @@ -1,5 +1,13 @@ +error: unconstrained opaque type + --> $DIR/nested.rs:3:12 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + error[E0277]: `Bar` doesn't implement `Debug` - --> $DIR/nested.rs:15:22 + --> $DIR/nested.rs:16:22 | LL | println!("{:?}", bar()); | ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` @@ -7,6 +15,6 @@ LL | println!("{:?}", bar()); = help: the trait `Debug` is not implemented for `Bar` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs index 475ca88747b7a..74160fc5a7d5f 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.rs +++ b/tests/ui/type-alias-impl-trait/reveal_local.rs @@ -4,7 +4,6 @@ use std::fmt::Debug; type Foo = impl Debug; //~^ ERROR cycle detected -//~| ERROR cycle detected fn is_send() {} diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr index 4047cf4be2045..5bbb3ca0f15d4 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.stderr +++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr @@ -1,28 +1,3 @@ -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/reveal_local.rs:5:12 - | -LL | type Foo = impl Debug; - | ^^^^^^^^^^ - | -note: ...which requires type-checking `not_good`... - --> $DIR/reveal_local.rs:14:5 - | -LL | is_send::(); - | ^^^^^^^^^^^^^^ - = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`... - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/reveal_local.rs:1:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | use std::fmt::Debug; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` --> $DIR/reveal_local.rs:5:12 | @@ -30,7 +5,7 @@ LL | type Foo = impl Debug; | ^^^^^^^^^^ | note: ...which requires type-checking `not_gooder`... - --> $DIR/reveal_local.rs:26:5 + --> $DIR/reveal_local.rs:25:5 | LL | is_send::(); | ^^^^^^^^^^^^^^ @@ -48,6 +23,6 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0391`. From 0d6dcd0c1613bf7cad42837d10990cc4ae9ca0d7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 24 Jan 2023 10:33:24 +0000 Subject: [PATCH 6/7] Generalize infinite recursion avoidance logic --- .../rustc_infer/src/infer/opaque_types.rs | 47 ++++++++++--------- tests/ui/impl-trait/issues/issue-74282.stderr | 32 ++++++------- 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 149ddf0b3ce39..cb484d48f3c8c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -4,6 +4,7 @@ use crate::traits; use hir::def::DefKind; use hir::def_id::{DefId, LocalDefId}; use hir::{HirId, OpaqueTyOrigin}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; @@ -16,7 +17,6 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{DefIdTree, GenericArgKind}; use rustc_span::Span; -use smallvec::SmallVec; use std::ops::ControlFlow; @@ -673,29 +673,37 @@ pub fn may_define_opaque_type<'tcx>( struct Visitor<'tcx> { opaque_def_id: DefId, tcx: TyCtxt<'tcx>, - ignore_nested: SmallVec<[DefId; 1]>, + seen: FxHashSet>, param_env: ty::ParamEnv<'tcx>, } impl<'tcx> TypeVisitor<'tcx> for Visitor<'tcx> { type BreakTy = (); + #[instrument(skip(self), level = "trace", ret)] fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + // Erase all lifetimes, they can't affect anything, but recursion + // may cause late bound regions to differ, because the type visitor + // can't erase them in `visit_binder`. + let t = t.fold_with(&mut BottomUpFolder { + tcx: self.tcx, + ct_op: |c| c, + ty_op: |t| t, + lt_op: |_| self.tcx.lifetimes.re_erased, + }); + if !self.seen.insert(t) { + return ControlFlow::Continue(()); + } match t.kind() { ty::Alias(ty::Opaque, alias) => { if alias.def_id == self.opaque_def_id { return ControlFlow::Break(()); } - if !self.ignore_nested.contains(&alias.def_id) { - // avoid infinite recursion since the opaque type shows - // up in its own bounds. - self.ignore_nested.push(alias.def_id); - for (pred, _span) in self - .tcx - .bound_explicit_item_bounds(alias.def_id) - .subst_iter_copied(self.tcx, alias.substs) - { - pred.visit_with(self)?; - } + for (pred, _span) in self + .tcx + .bound_explicit_item_bounds(alias.def_id) + .subst_iter_copied(self.tcx, alias.substs) + { + pred.visit_with(self)?; } } ty::Alias(ty::Projection, _) => { @@ -708,14 +716,9 @@ pub fn may_define_opaque_type<'tcx>( // Types that have opaque type fields must get walked manually, they // would not be seen by the type visitor otherwise. ty::Adt(adt_def, substs) => { - if !self.ignore_nested.contains(&adt_def.did()) { - // avoid infinite recursion since adts can recursively refer - // to themselves - self.ignore_nested.push(adt_def.did()); - for variant in adt_def.variants() { - for field in &variant.fields { - field.ty(self.tcx, substs).visit_with(self)?; - } + for variant in adt_def.variants() { + for field in &variant.fields { + field.ty(self.tcx, substs).visit_with(self)?; } } } @@ -727,7 +730,7 @@ pub fn may_define_opaque_type<'tcx>( val.visit_with(&mut Visitor { opaque_def_id: opaque_def_id.to_def_id(), tcx, - ignore_nested: SmallVec::new(), + seen: Default::default(), param_env, }) .is_break() diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr index 785d4919b1cea..f18dc4d73af03 100644 --- a/tests/ui/impl-trait/issues/issue-74282.stderr +++ b/tests/ui/impl-trait/issues/issue-74282.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/issue-74282.rs:11:15 + --> $DIR/issue-74282.rs:7:15 | -LL | type Closure = impl Fn() -> u64; - | ---------------- the expected opaque type +LL | type Closure = impl Fn() -> u64; + | ---------------- the expected opaque type ... LL | Anonymous(|| { | _____---------_^ @@ -15,33 +15,29 @@ LL | | }) | |_____^ expected closure, found a different closure | = note: expected opaque type `Closure` - found closure `[closure@$DIR/issue-74282.rs:11:15: 11:17]` + found closure `[closure@$DIR/issue-74282.rs:7:15: 7:17]` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object note: tuple struct defined here - --> $DIR/issue-74282.rs:4:8 + --> $DIR/issue-74282.rs:5:12 | -LL | struct Anonymous(Closure); - | ^^^^^^^^^ +LL | struct Anonymous(Closure); + | ^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/issue-74282.rs:11:5 + --> $DIR/issue-74282.rs:7:5 | +LL | fn main() { + | - expected `()` because of default return type +... LL | / Anonymous(|| { LL | | LL | | LL | | 3 LL | | }) - | |______^ expected `()`, found struct `Anonymous` - | -help: consider using a semicolon here - | -LL | }); - | + -help: try adding a return type - | -LL | -> Anonymous where - | ++++++++++++ + | | ^- help: consider using a semicolon here: `;` + | |______| + | expected `()`, found struct `Anonymous` error: aborting due to 2 previous errors From 28c5fe764a28e646f1643f9e1d5a0fd65ca002b6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 24 Jan 2023 10:38:01 +0000 Subject: [PATCH 7/7] Add a regression test --- .../defining-scope-self.rs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/defining-scope-self.rs diff --git a/tests/ui/type-alias-impl-trait/defining-scope-self.rs b/tests/ui/type-alias-impl-trait/defining-scope-self.rs new file mode 100644 index 0000000000000..c913c381beb14 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scope-self.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +// edition: 2021 +// check-pass + +type MyIter = impl Iterator; + +struct Foo { + iter: MyIter, +} + +// ensure that `self` is seen as `Foo` and thus +// counts as a defining use for `MyIter` due to the +// struct field. +impl Foo { + fn set_iter(&mut self) { + self.iter = [1, 2, 3].into_iter(); + } +} + +fn main() {}