diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index c893b34b4ac25..e28555b6dedaf 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -524,6 +524,8 @@ declare_features! ( (active, try_blocks, "1.29.0", Some(31436), None), /// Allows `impl Trait` to be used inside type aliases (RFC 2515). (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + /// Allows functions with TAITs in their where bounds to register hidden types. + (active, type_alias_impl_trait_in_where_bounds, "CURRENT_RUSTC_VERSION", Some(63063), None), /// Allows the use of type ascription in expressions. (active, type_ascription, "1.6.0", Some(23416), None), /// Allows creation of instances of a struct by moving fields that have diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 0105cbf36dee2..cb8a17d6865bb 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -69,6 +69,12 @@ hir_analysis_trait_object_declared_with_no_traits = at least one trait is required for an object type .alias_span = this alias does not contain a trait +hir_analysis_opaque_type_constrained_but_not_in_sig = opaque type constrained without being represented in the signature + .item_label = this item must mention the opaque type in its signature or where bounds + +hir_analysis_opaque_type_constrained_but_not_in_sibling = opaque type constrained in nested item + .item_label = this item is not a sibling of the opaque type + hir_analysis_missing_type_params = the type {$parameterCount -> [one] parameter diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index fe44fabf57df9..1a2af8a8d9409 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -1,3 +1,7 @@ +use std::ops::ControlFlow; + +use hir::def::DefKind; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, StashKey}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -9,15 +13,18 @@ use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{ - self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use rustc_session::parse::feature_err; use rustc_span::symbol::Ident; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{sym, Span, DUMMY_SP}; use super::ItemCtxt; use super::{bad_placeholder, is_suggestable_infer_ty}; -use crate::errors::UnconstrainedOpaqueType; +use crate::errors::{ + OpaqueTypeConstrainedButNotInSig, OpaqueTypeConstrainedInNonSibling, UnconstrainedOpaqueType, +}; /// Computes the relevant generic parameter for a potential generic const argument. /// @@ -635,6 +642,21 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types; debug!(?concrete_opaque_types); if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) { + if let Err((item_def_id, sibling)) = + may_define_opaque_type(self.tcx, item_def_id, self.def_id, concrete_type.span) + { + if sibling { + self.tcx.sess.emit_err(OpaqueTypeConstrainedButNotInSig { + span: concrete_type.span, + item_span: self.tcx.def_span(item_def_id), + }); + } else { + self.tcx.sess.emit_err(OpaqueTypeConstrainedInNonSibling { + span: concrete_type.span, + item_span: self.tcx.def_span(item_def_id), + }); + } + } debug!(?concrete_type, "found constraint"); if let Some(prev) = &mut self.found { if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() { @@ -655,8 +677,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T self.tcx.hir() } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - if let hir::ExprKind::Closure(closure) = ex.kind { - self.check(closure.def_id); + match ex.kind { + hir::ExprKind::Closure(closure) => { + self.check(closure.def_id); + } + hir::ExprKind::ConstBlock(anon) => self.check(anon.def_id), + _ => (), } intravisit::walk_expr(self, ex); } @@ -743,6 +769,176 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T hidden.ty } +#[instrument(skip(tcx), level = "trace", ret)] +fn may_define_opaque_type<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + opaque_def_id: LocalDefId, + span: Span, +) -> Result<(), (LocalDefId, bool)> { + let mut parent = tcx.local_parent(opaque_def_id); + loop { + trace!(?parent); + match tcx.def_kind(parent) { + DefKind::AssocTy | DefKind::TyAlias => { + parent = tcx.local_parent(parent); + break; + } + // Skip nested opaque types + DefKind::OpaqueTy => { + parent = tcx.local_parent(parent); + } + def_kind => { + trace!(?def_kind); + return Err((def_id, false)); + } + } + } + trace!(?parent); + if parent == def_id { + // If the opaque type is defined in the body of a function, that function + // may constrain the opaque type since it can't mention it in bounds. + return Ok(()); + } + + if tcx.is_typeck_child(def_id.to_def_id()) { + return may_define_opaque_type(tcx, tcx.local_parent(def_id), opaque_def_id, span); + } + + let mut item_parent = tcx.local_parent(def_id); + while item_parent != parent { + trace!(?item_parent); + match tcx.def_kind(item_parent) { + // Skip impls, to allow methods to constrain opaque types from the surrounding module. + DefKind::Impl { .. } | DefKind::Trait => { + item_parent = tcx.local_parent(item_parent); + } + // Skip modules, to allow constraining opaque types in child modules + DefKind::Mod => { + item_parent = tcx.local_parent(item_parent); + } + def_kind => { + trace!(?def_kind); + break; + } + } + } + + if item_parent != parent { + return Err((def_id, false)); + } + + let param_env = tcx.param_env(def_id); + + fn has_tait<'tcx>( + val: impl TypeVisitable>, + opaque_def_id: LocalDefId, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + struct Visitor<'tcx> { + opaque_def_id: DefId, + tcx: TyCtxt<'tcx>, + seen: FxHashSet>, + param_env: ty::ParamEnv<'tcx>, + } + impl<'tcx> TypeVisitor> 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 ty::fold::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(()); + } + 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) => { + 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, + seen: Default::default(), + 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()).skip_binder(), 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()).skip_binder(), 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 { + return Ok(()); + } + let tait_in_where_bounds = + has_tait(tcx.predicates_of(def_id.to_def_id()).predicates, opaque_def_id, tcx, param_env); + if tcx.features().type_alias_impl_trait_in_where_bounds { + if tait_in_where_bounds { Ok(()) } else { Err((def_id, true)) } + } else { + if tait_in_where_bounds { + feature_err( + &tcx.sess.parse_sess, + sym::type_alias_impl_trait_in_where_bounds, + span, + "type alias impl trait is only usable in argument or return types", + ) + .emit(); + } + Err((def_id, true)) + } +} + fn find_opaque_ty_constraints_for_rpit( tcx: TyCtxt<'_>, def_id: LocalDefId, @@ -951,8 +1147,6 @@ fn infer_placeholder_type<'a>( fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { if !tcx.features().inherent_associated_types { - use rustc_session::parse::feature_err; - use rustc_span::symbol::sym; feature_err( &tcx.sess.parse_sess, sym::inherent_associated_types, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f57197edeb74d..8aa15858bbf10 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -176,6 +176,23 @@ pub struct UnconstrainedOpaqueType { pub what: &'static str, } +#[derive(Diagnostic)] +#[diag(hir_analysis_opaque_type_constrained_but_not_in_sig)] +pub struct OpaqueTypeConstrainedButNotInSig { + #[primary_span] + pub span: Span, + #[label(hir_analysis_item_label)] + pub item_span: Span, +} +#[derive(Diagnostic)] +#[diag(hir_analysis_opaque_type_constrained_but_not_in_sibling)] +pub struct OpaqueTypeConstrainedInNonSibling { + #[primary_span] + pub span: Span, + #[label(hir_analysis_item_label)] + pub item_span: Span, +} + pub struct MissingTypeParams { pub span: Span, pub def_span: Span, diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 4110b176b41b1..08f95587c2ee8 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -73,13 +73,17 @@ impl<'tcx> Deref for Inherited<'tcx> { } impl<'tcx> Inherited<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + mk_defining_use_anchor: impl FnOnce(LocalDefId) -> DefiningAnchor, + ) -> Self { let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner; let 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)) .build(); let 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 d9c56134b662e..18d5a812f59ed 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -47,6 +47,7 @@ mod writeback; pub use fn_ctxt::FnCtxt; pub use inherited::Inherited; +use rustc_infer::infer::DefiningAnchor; use crate::check::check_fn; use crate::coercion::DynamicCoerceMany; @@ -212,11 +213,21 @@ fn typeck_with_fallback<'tcx>( } else { param_env }; - let inh = Inherited::new(tcx, def_id); + 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 inh = Inherited::new(tcx, def_id, mk_defining_use_anchor); let mut fcx = FnCtxt::new(&inh, param_env, def_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).subst_identity() diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d5c824d4c41c8..5d06034f001fc 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -372,7 +372,6 @@ impl<'tcx> InferCtxt<'tcx> { /// in its defining scope. #[instrument(skip(self), level = "trace", ret)] pub fn opaque_type_origin(&self, def_id: LocalDefId) -> 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, @@ -385,9 +384,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, opaque_hir_id) - } + hir::OpaqueTyOrigin::TyAlias => may_define_opaque_type(self.tcx, parent_def_id, def_id), }; in_definition_scope.then_some(origin) } @@ -634,7 +631,13 @@ 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_def_id: LocalDefId, +) -> 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. diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 578cd82aa4c2a..405f06fcaf520 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -223,7 +223,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/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d8b5b25aaeebd..3414b860e4211 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1509,6 +1509,7 @@ symbols! { ty, type_alias_enum_variants, type_alias_impl_trait, + type_alias_impl_trait_in_where_bounds, type_ascribe, type_ascription, type_changing_struct_update, 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 4c4c003ca4691..2ee1091c07fbd 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; @@ -369,7 +370,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< Node::Item(item) => { if let ItemKind::Fn(_, _, body_id) = &item.kind && let output_ty = return_ty(cx, item.owner_id) - && let inherited = Inherited::new(cx.tcx, item.owner_id.def_id) + && let inherited = Inherited::new(cx.tcx, item.owner_id.def_id, DefiningAnchor::Bind) && let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, item.owner_id.def_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 62efd13b8d909..ed7233a1de189 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 @@ -33,7 +34,7 @@ pub(super) fn check_cast<'tcx>( let hir_id = e.hir_id; let local_def_id = hir_id.owner.def_id; - let inherited = Inherited::new(cx.tcx, local_def_id); + let inherited = Inherited::new(cx.tcx, local_def_id, DefiningAnchor::Bind); let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_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..be3a323c6f6ae 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,11 +3,17 @@ // 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)] -#![feature(adt_const_params, extern_types, inline_const, type_alias_impl_trait)] +#![feature( + adt_const_params, + extern_types, + inline_const, + type_alias_impl_trait, + type_alias_impl_trait_in_where_bounds +)] extern crate core; use core::ffi::c_void; @@ -29,23 +35,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 +67,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 +90,7 @@ pub fn fn1<'a>() { let _: Type2 = Foo; // Type in extern path - extern { + extern "C" { fn foo(); } let _: Type3 = foo; @@ -85,12 +104,12 @@ pub fn fn1<'a>() { // Type in const path const { pub struct Foo; - fn foo() -> Type5 { Foo } + let _: Type5 = Foo; }; // Type in impl path impl Struct1 { - fn foo(&self) { } + fn foo(&self) {} } let _: Type6 = >::foo; @@ -138,305 +157,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..376b99f1ed830 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 @@ -10,9 +10,8 @@ fn define() -> Bar { Bar(42) } -type Foo2 = impl Debug; - fn define2() { + type Foo2 = impl Debug; let x = || -> Foo2 { 42 }; } @@ -21,13 +20,9 @@ type Foo3 = impl Debug; fn define3(x: Foo3) { let y: i32 = x; } -fn define3_1() { - define3(42) -} - -type Foo4 = impl Debug; fn define4() { + type Foo4 = impl Debug; let y: Foo4 = 42; } diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait_in_where_bounds.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait_in_where_bounds.rs new file mode 100644 index 0000000000000..1d537efdc16ff --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait_in_where_bounds.rs @@ -0,0 +1,43 @@ +// ignore-compare-mode-chalk +// check-pass +#![feature(type_alias_impl_trait, type_alias_impl_trait_in_where_bounds)] +use std::fmt::Debug; + +type Foo = impl Debug; + +struct Bar(Foo); +fn define() -> Bar { + Bar(42) +} + +type Foo2 = impl Debug; + +fn define2() +where + Foo2: Debug, +{ + let x = || -> Foo2 { 42 }; +} + +type Foo3 = impl Debug; + +fn define3(x: Foo3) { + let y: i32 = x; +} +fn define3_1() +where + Foo3: Debug, +{ + define3(42) +} + +type Foo4 = impl Debug; + +fn define4() +where + Foo4: Debug, +{ + let y: Foo4 = 42; +} + +fn main() {} diff --git a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs index d2c3479203573..9d0c7ebc9362e 100644 --- a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs +++ b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(type_alias_impl_trait)] +#![feature(type_alias_impl_trait, type_alias_impl_trait_in_where_bounds)] trait SuperExpectation: Fn(i32) {} @@ -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/issue-55872-2.stderr b/tests/ui/impl-trait/issue-55872-2.stderr deleted file mode 100644 index 477c964bd40fd..0000000000000 --- a/tests/ui/impl-trait/issue-55872-2.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:17:9 - | -LL | async {} - | ^^^^^^^^ - -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..00c5cc723ac87 100644 --- a/tests/ui/impl-trait/issues/issue-74282.rs +++ b/tests/ui/impl-trait/issues/issue-74282.rs @@ -1,11 +1,12 @@ #![feature(type_alias_impl_trait)] -type Closure = impl Fn() -> u64; -struct Anonymous(Closure); - fn main() { + type Closure = impl Fn() -> u64; + struct Anonymous(Closure); let y = || -> Closure { || 3 }; - Anonymous(|| { //~ ERROR mismatched types - 3 //~^ ERROR mismatched types + Anonymous(|| { + //~^ ERROR mismatched types + //~| ERROR mismatched types + 3 }) } diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr index 724f3c5d6747c..9316588ff0050 100644 --- a/tests/ui/impl-trait/issues/issue-74282.stderr +++ b/tests/ui/impl-trait/issues/issue-74282.stderr @@ -1,34 +1,38 @@ error[E0308]: mismatched types - --> $DIR/issue-74282.rs:8: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(|| { | _____---------_^ | | | | | arguments to this struct are incorrect +LL | | +LL | | LL | | 3 LL | | }) | |_____^ expected opaque type, found closure | = note: expected opaque type `Closure` - found closure `[closure@$DIR/issue-74282.rs:8:15: 8: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:8:5 + --> $DIR/issue-74282.rs:7: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: `;` diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.global.stderr similarity index 75% rename from tests/ui/impl-trait/issues/issue-78722.stderr rename to tests/ui/impl-trait/issues/issue-78722.global.stderr index 05a2c135cf7c7..af1d6e04ff18a 100644 --- a/tests/ui/impl-trait/issues/issue-78722.stderr +++ b/tests/ui/impl-trait/issues/issue-78722.global.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 }; | ^^^^^^^^^^^ @@ -7,8 +7,8 @@ LL | let f: F = async { 1 }; = note: see issue #85368 for more information = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable -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.in_const.stderr b/tests/ui/impl-trait/issues/issue-78722.in_const.stderr new file mode 100644 index 0000000000000..af1d6e04ff18a --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-78722.in_const.stderr @@ -0,0 +1,19 @@ +error[E0658]: `async` blocks are not allowed in constants + --> $DIR/issue-78722.rs:18:20 + | +LL | let f: F = async { 1 }; + | ^^^^^^^^^^^ + | + = note: see issue #85368 for more information + = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable + +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` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0658. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/issues/issue-78722.rs b/tests/ui/impl-trait/issues/issue-78722.rs index 7b5ab5f229835..e4ad3b62fdf77 100644 --- a/tests/ui/impl-trait/issues/issue-78722.rs +++ b/tests/ui/impl-trait/issues/issue-78722.rs @@ -1,11 +1,16 @@ // 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 `()` async {} diff --git a/tests/ui/type-alias-impl-trait/almost_in_scope.rs b/tests/ui/type-alias-impl-trait/almost_in_scope.rs new file mode 100644 index 0000000000000..1776d3315a1f0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/almost_in_scope.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +trait Blah { + type Output; + fn method(); +} + +impl Blah for u32 { + type Output = Foo; + fn method() { + let x: Foo = 22_u32; + //~^ ERROR: opaque type constrained without being represented in the signature + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/almost_in_scope.stderr b/tests/ui/type-alias-impl-trait/almost_in_scope.stderr new file mode 100644 index 0000000000000..31f2e6e45e674 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/almost_in_scope.stderr @@ -0,0 +1,10 @@ +error: opaque type constrained without being represented in the signature + --> $DIR/almost_in_scope.rs:13:22 + | +LL | fn method() { + | ----------- this item must mention the opaque type in its signature or where bounds +LL | let x: Foo = 22_u32; + | ^^^^^^ + +error: aborting due to previous error + 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..9555779800cf1 100644 --- a/tests/ui/type-alias-impl-trait/closure_args.rs +++ b/tests/ui/type-alias-impl-trait/closure_args.rs @@ -2,7 +2,7 @@ // regression test for https://github.com/rust-lang/rust/issues/100800 -#![feature(type_alias_impl_trait)] +#![feature(type_alias_impl_trait, type_alias_impl_trait_in_where_bounds)] trait Anything {} impl Anything for T {} @@ -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..9c7903ebc2ecc 100644 --- a/tests/ui/type-alias-impl-trait/closure_args2.rs +++ b/tests/ui/type-alias-impl-trait/closure_args2.rs @@ -1,10 +1,12 @@ // run-pass -#![feature(type_alias_impl_trait)] +#![feature(type_alias_impl_trait, type_alias_impl_trait_in_where_bounds)] 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/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() {} 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..f43718bca4981 --- /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; +//~^ ERROR unconstrained opaque type + +#[rustfmt::skip] +struct Struct< + const C: usize = { + let _: Foo = (); + 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..6497af1f187e8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-in_type.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/defining-scopes-in_type.rs:5:12 + | +LL | type Foo = impl Send; + | ^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + 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..000571d4f9b1c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs @@ -0,0 +1,19 @@ +#![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: constrained without being represented in the signature + () +} + +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..d525db0b34630 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr @@ -0,0 +1,17 @@ +error[E0091]: type parameter `T` is unused + --> $DIR/defining-scopes-syntactic.rs:6:15 + | +LL | type DropType = (); + | ^ unused type parameter + +error: opaque type constrained without being represented in the signature + --> $DIR/defining-scopes-syntactic.rs:14:12 + | +LL | fn g() -> DropType { + | ----------------------- this item must mention the opaque type in its signature or where bounds +LL | let _: Foo = 42; + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this 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-use-item-child.rs b/tests/ui/type-alias-impl-trait/defining-use-item-child.rs new file mode 100644 index 0000000000000..c2f384a9c2b7a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-use-item-child.rs @@ -0,0 +1,30 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type Foo = impl std::fmt::Display; + +fn bar() { + pub fn foo() -> Foo { + "foo" + //~^ ERROR: opaque type constrained in nested item + } +} + +fn baz() -> Foo { + pub fn foo() -> Foo { + "foo" + //~^ ERROR: opaque type constrained in nested item + } + "baz" +} + +struct Bak { + x: [u8; { + fn blob() -> Foo { + "blob" + //~^ ERROR: opaque type constrained in nested item + } + 5 + }], +} diff --git a/tests/ui/type-alias-impl-trait/defining-use-item-child.stderr b/tests/ui/type-alias-impl-trait/defining-use-item-child.stderr new file mode 100644 index 0000000000000..74595f2935465 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-use-item-child.stderr @@ -0,0 +1,26 @@ +error: opaque type constrained in nested item + --> $DIR/defining-use-item-child.rs:9:9 + | +LL | pub fn foo() -> Foo { + | ------------------- this item is not a sibling of the opaque type +LL | "foo" + | ^^^^^ + +error: opaque type constrained in nested item + --> $DIR/defining-use-item-child.rs:16:9 + | +LL | pub fn foo() -> Foo { + | ------------------- this item is not a sibling of the opaque type +LL | "foo" + | ^^^^^ + +error: opaque type constrained in nested item + --> $DIR/defining-use-item-child.rs:25:13 + | +LL | fn blob() -> Foo { + | ---------------- this item is not a sibling of the opaque type +LL | "blob" + | ^^^^^^ + +error: aborting due to 3 previous errors + 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 cdd8f6f1976a5..f81c1516879d5 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)] +#![feature(type_alias_impl_trait, type_alias_impl_trait_in_where_bounds)] -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 fa79e51e9f79f..70b81a2e0dbe2 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 `&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/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 79caddf791320..3f5e8f161a711 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.rs +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -15,8 +15,14 @@ mod m { is_send(foo()); // Today: error } - fn baz() { + fn baz() -> Foo { let f: Foo = 22_u32; + f + } + + fn bak() { + let f: Foo = 22_u32; + //~^ ERROR constrained without being represented in the signature } fn is_send(_: T) {} diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr index b9d646b927a6f..322d5f3248027 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -17,6 +17,14 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: aborting due to previous error +error: opaque type constrained without being represented in the signature + --> $DIR/inference-cycle.rs:24:22 + | +LL | fn bak() { + | -------- this item must mention the opaque type in its signature or where bounds +LL | let f: Foo = 22_u32; + | ^^^^^^ + +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/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-anon-const-fail.rs b/tests/ui/type-alias-impl-trait/issue-63263-anon-const-fail.rs new file mode 100644 index 0000000000000..3b3ec98f663d5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63263-anon-const-fail.rs @@ -0,0 +1,14 @@ +// Regression test for issue #63263. +// Tests that we properly handle closures with an explicit return type +// that return an opaque type. + +#![feature(type_alias_impl_trait, inline_const)] + +pub type Closure = impl FnOnce(); + +fn main() { + const { + let x: Closure = || {}; + //~^ ERROR: opaque type constrained without being represented in the signature + } +} diff --git a/tests/ui/type-alias-impl-trait/issue-63263-anon-const-fail.stderr b/tests/ui/type-alias-impl-trait/issue-63263-anon-const-fail.stderr new file mode 100644 index 0000000000000..5286ddc4edbb2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63263-anon-const-fail.stderr @@ -0,0 +1,11 @@ +error: opaque type constrained without being represented in the signature + --> $DIR/issue-63263-anon-const-fail.rs:11:26 + | +LL | fn main() { + | --------- this item must mention the opaque type in its signature or where bounds +LL | const { +LL | let x: Closure = || {}; + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-63263-anon-const.rs b/tests/ui/type-alias-impl-trait/issue-63263-anon-const.rs new file mode 100644 index 0000000000000..5954ec93b965a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63263-anon-const.rs @@ -0,0 +1,14 @@ +// Regression test for issue #63263. +// Tests that we properly handle closures with an explicit return type +// that return an opaque type. + +// check-pass + +#![feature(type_alias_impl_trait, inline_const)] + +fn main() { + pub type Closure = impl FnOnce(); + const { + let x: Closure = || {}; + } +} diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return-fail.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return-fail.rs new file mode 100644 index 0000000000000..c30322e4d10da --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return-fail.rs @@ -0,0 +1,11 @@ +// Tests that we don't allow closures to constrain opaque types +// unless their surrounding item has the opaque type in its signature. + +#![feature(type_alias_impl_trait)] + +pub type Closure = impl FnOnce(); + +fn main() { + || -> Closure { || () }; + //~^ ERROR: opaque type constrained without being represented in the signature +} diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return-fail.stderr b/tests/ui/type-alias-impl-trait/issue-63263-closure-return-fail.stderr new file mode 100644 index 0000000000000..298233f68caee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return-fail.stderr @@ -0,0 +1,10 @@ +error: opaque type constrained without being represented in the signature + --> $DIR/issue-63263-closure-return-fail.rs:9:21 + | +LL | fn main() { + | --------- this item must mention the opaque type in its signature or where bounds +LL | || -> Closure { || () }; + | ^^^^^ + +error: aborting due to previous error + 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..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,8 +6,7 @@ #![feature(type_alias_impl_trait)] -pub type Closure = impl FnOnce(); - fn main() { + pub type Closure = impl FnOnce(); || -> Closure { || () }; } 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 b91cbce3727f6..deac07e8a454d 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 @@ -1,6 +1,6 @@ // check-pass -#![feature(type_alias_impl_trait, rustc_attrs)] +#![feature(type_alias_impl_trait, rustc_attrs, type_alias_impl_trait_in_where_bounds)] type T = impl Sized; // The concrete type referred by impl-trait-type-alias(`T`) is guaranteed @@ -11,7 +11,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/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..f2e8044611bb8 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 @@ -1,16 +1,22 @@ -#![feature(type_alias_impl_trait)] +#![feature(type_alias_impl_trait, type_alias_impl_trait_in_where_bounds)] #![allow(dead_code)] 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