From 1da411e750c7350d8a639ef9fbc73f29c2c1a856 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Dec 2024 20:10:47 +0000 Subject: [PATCH 1/2] Split UserTypeAnnotation to have a kind --- .../src/type_check/canonical.rs | 2 +- .../src/type_check/input_output.rs | 4 +-- compiler/rustc_borrowck/src/type_check/mod.rs | 10 +++++-- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 12 ++++---- .../rustc_hir_typeck/src/gather_locals.rs | 6 ++-- .../rustc_hir_typeck/src/method/confirm.rs | 6 ++-- compiler/rustc_hir_typeck/src/writeback.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- .../rustc_middle/src/ty/typeck_results.rs | 30 ++++++++++++++++--- .../src/build/matches/match_pair.rs | 5 ++-- compiler/rustc_mir_build/src/thir/cx/expr.rs | 5 ++-- compiler/rustc_mir_build/src/thir/util.rs | 4 +-- .../traits/query/type_op/ascribe_user_type.rs | 8 ++--- 13 files changed, 60 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 585d0eabf5b97..3903c45fda529 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -275,7 +275,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_ty: ty::UserType<'tcx>, span: Span, ) { - let ty::UserType::Ty(user_ty) = user_ty else { bug!() }; + let ty::UserTypeKind::Ty(user_ty) = user_ty.kind else { bug!() }; // A fast path for a common case with closure input/output types. if let ty::Infer(_) = user_ty.kind() { diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index bbe2b55d8c448..1f2ec168f0322 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) { self.ascribe_user_type_skip_wf( arg_decl.ty, - ty::UserType::Ty(user_ty), + ty::UserType::new(ty::UserTypeKind::Ty(user_ty)), arg_decl.source_info.span, ); } @@ -119,7 +119,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let output_decl = &body.local_decls[RETURN_PLACE]; self.ascribe_user_type_skip_wf( output_decl.ty, - ty::UserType::Ty(user_provided_sig.output()), + ty::UserType::new(ty::UserTypeKind::Ty(user_provided_sig.output())), output_decl.source_info.span, ); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 89e683b8ae3dc..b274818299a10 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -31,7 +31,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt, Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs, - UserType, UserTypeAnnotationIndex, + UserTypeAnnotationIndex, }; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::ResultsCursor; @@ -370,7 +370,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } else { self.cx.ascribe_user_type( constant.const_.ty(), - UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }), + ty::UserType::new(ty::UserTypeKind::TypeOf(uv.def, UserArgs { + args: uv.args, + user_self_ty: None, + })), locations.span(self.cx.body), ); } @@ -991,9 +994,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; let annotation = self.instantiate_canonical(span, user_ty); - if let ty::UserType::TypeOf(def, args) = annotation + if let ty::UserTypeKind::TypeOf(def, args) = annotation.kind && let DefKind::InlineConst = tcx.def_kind(def) { + // TODO: self.check_inline_const(inferred_ty, def.expect_local(), args, span); } else { self.ascribe_user_type(inferred_ty, annotation, span); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 863be3bdcb290..4195a42cd7ef5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -25,7 +25,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{ self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind, - IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy, UserType, + IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -216,11 +216,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("fcx {}", self.tag()); if Self::can_contain_user_lifetime_bounds((args, user_self_ty)) { - let canonicalized = - self.canonicalize_user_type_annotation(UserType::TypeOf(def_id, UserArgs { - args, - user_self_ty, - })); + let canonicalized = self.canonicalize_user_type_annotation(ty::UserType::new( + ty::UserTypeKind::TypeOf(def_id, UserArgs { args, user_self_ty }), + )); debug!(?canonicalized); self.write_user_type_annotation(hir_id, canonicalized); } @@ -468,7 +466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?ty); if Self::can_contain_user_lifetime_bounds(ty.raw) { - let c_ty = self.canonicalize_response(UserType::Ty(ty.raw)); + let c_ty = self.canonicalize_response(ty::UserType::new(ty::UserTypeKind::Ty(ty.raw))); debug!(?c_ty); self.typeck_results.borrow_mut().user_provided_types_mut().insert(hir_ty.hir_id, c_ty); } diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index f427b0b805eb5..849c200ab0a9c 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -2,7 +2,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{HirId, PatKind}; use rustc_infer::traits::ObligationCauseCode; -use rustc_middle::ty::{Ty, UserType}; +use rustc_middle::ty::{self, Ty}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; use tracing::debug; @@ -92,7 +92,9 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { Some(ref ty) => { let o_ty = self.fcx.lower_ty(ty); - let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); + let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(ty::UserType::new( + ty::UserTypeKind::Ty(o_ty.raw), + )); debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx .typeck_results diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index b31ee1a55d63b..ef431c852e94b 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::adjustment::{ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, UserArgs, - UserType, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Span}; @@ -491,9 +490,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { user_self_ty: None, // not relevant here }; - self.fcx.canonicalize_user_type_annotation(UserType::TypeOf( - pick.item.def_id, - user_args, + self.fcx.canonicalize_user_type_annotation(ty::UserType::new( + ty::UserTypeKind::TypeOf(pick.item.def_id, user_args), )) }); diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index e17a68c869215..6f1e3a0cf8c7b 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -476,7 +476,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { for (local_id, c_ty) in sorted_user_provided_types { let hir_id = HirId { owner: common_hir_owner, local_id }; - if let ty::UserType::TypeOf(_, user_args) = c_ty.value { + if let ty::UserTypeKind::TypeOf(_, user_args) = c_ty.value.kind { // This is a unit-testing mechanism. let span = self.tcx().hir().span(hir_id); // We need to buffer the errors in order to guarantee a consistent diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8051aa017151e..e47b0cf0b3bb6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -95,7 +95,7 @@ pub use self::sty::{ pub use self::trait_def::TraitDef; pub use self::typeck_results::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity, - TypeckResults, UserType, UserTypeAnnotationIndex, + TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, }; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 8cba5f332784c..744a7384e8bf7 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -700,12 +700,24 @@ pub struct CanonicalUserTypeAnnotation<'tcx> { /// Canonical user type annotation. pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>; +#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] +#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct UserType<'tcx> { + pub kind: UserTypeKind<'tcx>, +} + +impl<'tcx> UserType<'tcx> { + pub fn new(kind: UserTypeKind<'tcx>) -> UserType<'tcx> { + UserType { kind } + } +} + /// A user-given type annotation attached to a constant. These arise /// from constants that are named via paths, like `Foo::::new` and /// so forth. #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] #[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum UserType<'tcx> { +pub enum UserTypeKind<'tcx> { Ty(Ty<'tcx>), /// The canonical type is the result of `type_of(def_id)` with the @@ -721,9 +733,11 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { /// Returns `true` if this represents the generic parameters of the form `[?0, ?1, ?2]`, /// i.e., each thing is mapped to a canonical variable with the same index. fn is_identity(&self) -> bool { - match self.value { - UserType::Ty(_) => false, - UserType::TypeOf(_, user_args) => { + // TODO: + + match self.value.kind { + UserTypeKind::Ty(_) => false, + UserTypeKind::TypeOf(_, user_args) => { if user_args.user_self_ty.is_some() { return false; } @@ -764,6 +778,14 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { } impl<'tcx> std::fmt::Display for UserType<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // TODO: + + self.kind.fmt(f) + } +} + +impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Ty(arg0) => { diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index 2815b39037513..33fbd7b1a3f2c 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -176,9 +176,8 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { ty: cx.infcx.next_ty_var(span), }) .args; - let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf( - def_id, - ty::UserArgs { args, user_self_ty: None }, + let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new( + ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }), )); let annotation = ty::CanonicalUserTypeAnnotation { inferred_ty: pattern.ty, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 3cbf1e2055c9c..6770e562d5010 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -15,7 +15,6 @@ use rustc_middle::ty::adjustment::{ }; use rustc_middle::ty::{ self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, - UserType, }; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, sym}; @@ -443,7 +442,9 @@ impl<'tcx> Cx<'tcx> { let user_provided_types = self.typeck_results().user_provided_types(); let user_ty = user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { - if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value { + if let ty::UserTypeKind::TypeOf(ref mut did, _) = + &mut u_ty.value.kind + { *did = adt_def.did(); } Box::new(u_ty) diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs index 53a2a0852eb49..ed7c7e4099304 100644 --- a/compiler/rustc_mir_build/src/thir/util.rs +++ b/compiler/rustc_mir_build/src/thir/util.rs @@ -1,6 +1,6 @@ use rustc_hir as hir; use rustc_middle::bug; -use rustc_middle::ty::{self, CanonicalUserType, TyCtxt, UserType}; +use rustc_middle::ty::{self, CanonicalUserType, TyCtxt}; use tracing::debug; pub(crate) trait UserAnnotatedTyHelpers<'tcx> { @@ -21,7 +21,7 @@ pub(crate) trait UserAnnotatedTyHelpers<'tcx> { let ty = self.typeck_results().node_type(hir_id); match ty.kind() { ty::Adt(adt_def, ..) => { - if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value { + if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind { *did = adt_def.did(); } Some(user_ty) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index dc3f5544613ad..319c7ece42bfc 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -3,7 +3,7 @@ use rustc_infer::traits::Obligation; use rustc_middle::traits::query::NoSolution; pub use rustc_middle::traits::query::type_op::AscribeUserType; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserType}; +use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserTypeKind}; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument}; @@ -46,9 +46,9 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>( let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts(); debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty); let span = span.unwrap_or(DUMMY_SP); - match user_ty { - UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?, - UserType::TypeOf(def_id, user_args) => { + match user_ty.kind { + UserTypeKind::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?, + UserTypeKind::TypeOf(def_id, user_args) => { relate_mir_and_user_args(ocx, param_env, span, mir_ty, def_id, user_args)? } }; From d714a22e7bc38b158d09ee6294d1716acd1a727d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Dec 2024 22:18:39 +0000 Subject: [PATCH 2/2] (Re-)Implement impl_trait_in_bindings --- compiler/rustc_ast_lowering/src/block.rs | 19 ++++++++--- compiler/rustc_ast_lowering/src/lib.rs | 10 ++++++ compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_feature/src/removed.rs | 3 -- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_hir/src/hir.rs | 2 ++ compiler/rustc_hir/src/intravisit.rs | 3 ++ compiler/rustc_hir_analysis/src/collect.rs | 11 +++++- .../src/collect/resolve_bound_vars.rs | 15 ++++++++ .../src/hir_ty_lowering/mod.rs | 26 ++++++++++++++ compiler/rustc_hir_pretty/src/lib.rs | 3 ++ .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 33 ++++++++++++++++-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 34 ++++++++++++++++++- .../rustc_hir_typeck/src/gather_locals.rs | 9 +++-- compiler/rustc_middle/src/query/plumbing.rs | 2 +- .../rustc_middle/src/ty/typeck_results.rs | 23 ++++++++++--- compiler/rustc_passes/src/input_stats.rs | 1 + .../traits/query/type_op/ascribe_user_type.rs | 6 ++++ src/librustdoc/clean/mod.rs | 8 +++-- .../clippy/clippy_lints/src/dereference.rs | 1 + .../clippy/clippy_utils/src/hir_utils.rs | 3 +- .../feature-gate-impl-trait-in-bindings.rs | 4 +++ ...feature-gate-impl-trait-in-bindings.stderr | 14 ++++++++ .../ui/impl-trait/in-bindings/bad-nesting.rs | 10 ++++++ .../impl-trait/in-bindings/bad-nesting.stderr | 12 +++++++ .../in-bindings/escaping-bound-var.rs | 14 ++++++++ .../in-bindings/escaping-bound-var.stderr | 8 +++++ .../in-bindings/lifetime-failure.rs | 12 +++++++ .../in-bindings/lifetime-failure.stderr | 16 +++++++++ .../in-bindings/nesting-lifetime-failure.rs | 10 ++++++ .../nesting-lifetime-failure.stderr | 16 +++++++++ tests/ui/impl-trait/in-bindings/nesting.rs | 7 ++++ tests/ui/impl-trait/in-bindings/simple.rs | 10 ++++++ .../impl-trait/in-bindings/trait-failure.rs | 13 +++++++ .../in-bindings/trait-failure.stderr | 24 +++++++++++++ tests/ui/impl-trait/issues/issue-54600.stderr | 3 ++ tests/ui/impl-trait/issues/issue-54840.stderr | 3 ++ tests/ui/impl-trait/issues/issue-58504.stderr | 3 ++ tests/ui/impl-trait/issues/issue-58956.stderr | 3 ++ tests/ui/impl-trait/issues/issue-70971.stderr | 3 ++ tests/ui/impl-trait/issues/issue-79099.stderr | 3 ++ tests/ui/impl-trait/issues/issue-84919.stderr | 3 ++ tests/ui/impl-trait/issues/issue-87295.stderr | 3 ++ tests/ui/impl-trait/where-allowed.stderr | 3 ++ tests/ui/typeck/issue-104513-ice.stderr | 3 ++ 45 files changed, 391 insertions(+), 25 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs create mode 100644 tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr create mode 100644 tests/ui/impl-trait/in-bindings/bad-nesting.rs create mode 100644 tests/ui/impl-trait/in-bindings/bad-nesting.stderr create mode 100644 tests/ui/impl-trait/in-bindings/escaping-bound-var.rs create mode 100644 tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr create mode 100644 tests/ui/impl-trait/in-bindings/lifetime-failure.rs create mode 100644 tests/ui/impl-trait/in-bindings/lifetime-failure.stderr create mode 100644 tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs create mode 100644 tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr create mode 100644 tests/ui/impl-trait/in-bindings/nesting.rs create mode 100644 tests/ui/impl-trait/in-bindings/simple.rs create mode 100644 tests/ui/impl-trait/in-bindings/trait-failure.rs create mode 100644 tests/ui/impl-trait/in-bindings/trait-failure.stderr diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 20d3ce65facc7..88ce6f80e10bd 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,5 +1,6 @@ use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; +use rustc_span::sym; use smallvec::SmallVec; use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; @@ -82,11 +83,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (self.arena.alloc_from_iter(stmts), expr) } + /// Return an `ImplTraitContext` that allows impl trait in bindings if + /// the feature gate is enabled, or issues a feature error if it is not. + fn impl_trait_in_bindings_ctxt(&self, position: ImplTraitPosition) -> ImplTraitContext { + if self.tcx.features().impl_trait_in_bindings() { + ImplTraitContext::InBinding + } else { + ImplTraitContext::FeatureGated(position, sym::impl_trait_in_bindings) + } + } + fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> { - let ty = l - .ty - .as_ref() - .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + // Let statements are allowed to have impl trait in bindings. + let ty = l.ty.as_ref().map(|t| { + self.lower_ty(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable)) + }); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3cbd3e1b63785..e4600b0f6363c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -260,6 +260,13 @@ enum ImplTraitContext { /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`. /// OpaqueTy { origin: hir::OpaqueTyOrigin }, + + /// Treat `impl Trait` as a "trait ascription", which is like a type + /// variable but that also enforces that a set of trait goals hold. + /// + /// This is useful to guide inference for unnameable types. + InBinding, + /// `impl Trait` is unstably accepted in this position. FeatureGated(ImplTraitPosition, Symbol), /// `impl Trait` is not accepted in this position. @@ -1327,6 +1334,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } + ImplTraitContext::InBinding => { + hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx)) + } ImplTraitContext::FeatureGated(position, feature) => { let guar = self .tcx diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index b274818299a10..90d327b0ad20d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -997,7 +997,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let ty::UserTypeKind::TypeOf(def, args) = annotation.kind && let DefKind::InlineConst = tcx.def_kind(def) { - // TODO: + assert!(annotation.bounds.is_empty()); self.check_inline_const(inferred_ty, def.expect_local(), args, span); } else { self.ascribe_user_type(inferred_ty, annotation, span); diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 8b4f441dafe22..e25840ba5fcb6 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -126,9 +126,6 @@ declare_features! ( better implied higher-ranked implied bounds support" ) ), - /// Allows `impl Trait` in bindings (`let`, `const`, `static`). - (removed, impl_trait_in_bindings, "1.55.0", Some(63065), - Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), (removed, import_shadowing, "1.0.0", None, None), /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). (removed, in_band_lifetimes, "1.23.0", Some(44524), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8fa75eac9dbc6..45c63b03fe98b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -517,6 +517,8 @@ declare_features! ( (unstable, if_let_guard, "1.47.0", Some(51114)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), + /// Allows `impl Trait` in bindings (`let`). + (unstable, impl_trait_in_bindings, "1.64.0", Some(63065)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)), /// Allows associated types in inherent impls. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c7d83760b7829..357033a9e183b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2906,6 +2906,8 @@ pub enum TyKind<'hir> { Path(QPath<'hir>), /// An opaque type definition itself. This is only used for `impl Trait`. OpaqueDef(&'hir OpaqueTy<'hir>), + /// A trait ascription type, which is `impl Trait` within a local binding. + TraitAscription(GenericBounds<'hir>), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 482940eb5ca76..6d481f7536ac2 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -900,6 +900,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul TyKind::OpaqueDef(opaque) => { try_visit!(visitor.visit_opaque_ty(opaque)); } + TyKind::TraitAscription(bounds) => { + walk_list!(visitor, visit_param_bound, bounds); + } TyKind::Array(ref ty, ref length) => { try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_const_arg(length)); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index debfe6af0fbf9..37dfb818f8dbf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -29,7 +29,7 @@ use rustc_errors::{ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor, walk_generics}; -use rustc_hir::{self as hir, GenericParamKind, Node}; +use rustc_hir::{self as hir, GenericParamKind, HirId, Node}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; @@ -436,6 +436,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant") } + fn register_trait_ascription_bounds( + &self, + _: Vec<(ty::Clause<'tcx>, Span)>, + _: HirId, + span: Span, + ) { + self.dcx().span_delayed_bug(span, "trait ascription type not allowed here"); + } + fn probe_ty_param_bounds( &self, span: Span, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 923d2b1fe6758..0f797bcdae428 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -852,6 +852,21 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }; self.with(scope, |this| this.visit_ty(mt.ty)); } + hir::TyKind::TraitAscription(bounds) => { + let scope = Scope::TraitRefBoundary { s: self.scope }; + self.with(scope, |this| { + let scope = Scope::LateBoundary { + s: this.scope, + what: "`impl Trait` in binding", + deny_late_regions: true, + }; + this.with(scope, |this| { + for bound in bounds { + this.visit_param_bound(bound); + } + }) + }); + } _ => intravisit::walk_ty(self, ty), } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 1bdbde3003717..a357ade02945f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -123,6 +123,13 @@ pub trait HirTyLowerer<'tcx> { /// Returns the const to use when a const is omitted. fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>; + fn register_trait_ascription_bounds( + &self, + bounds: Vec<(ty::Clause<'tcx>, Span)>, + hir_id: HirId, + span: Span, + ); + /// Probe bounds in scope where the bounded type coincides with the given type parameter. /// /// Rephrased, this returns bounds of the form `T: Trait`, where `T` is a type parameter @@ -2375,6 +2382,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_opaque_ty(opaque_ty.def_id, in_trait) } + hir::TyKind::TraitAscription(hir_bounds) => { + // Impl trait in bindings lower as an infer var with additional + // set of type bounds. + let self_ty = self.ty_infer(None, hir_ty.span); + let mut bounds = Bounds::default(); + self.lower_bounds( + self_ty, + hir_bounds.iter(), + &mut bounds, + ty::List::empty(), + PredicateFilter::All, + ); + self.register_trait_ascription_bounds( + bounds.clauses().collect(), + hir_ty.hir_id, + hir_ty.span, + ); + self_ty + } // If we encounter a type relative path with RTN generics, then it must have // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore // it's certainly in an illegal position. diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a17b6321ce835..8dd8a5c98ef51 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -292,6 +292,9 @@ impl<'a> State<'a> { self.print_unsafe_binder(unsafe_binder); } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), + hir::TyKind::TraitAscription(bounds) => { + self.print_bounds("impl", bounds); + } hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 4195a42cd7ef5..0dacfc9b7bf90 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -4,11 +4,11 @@ use std::slice; use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey}; -use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath}; +use rustc_hir::{self as hir, ExprKind, GenericArg, HirId, Node, QPath, intravisit}; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, @@ -460,8 +460,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { LoweredTy::from_raw(self, hir_ty.span, ty) } + /// Walk a `hir_ty` and collect any clauses that may have come from a type + /// within the `hir_ty`. These clauses will be canonicalized with a user type + /// annotation so that we can enforce these bounds in borrowck, too. + pub(crate) fn collect_impl_trait_clauses_from_hir_ty( + &self, + hir_ty: &'tcx hir::Ty<'tcx>, + ) -> ty::Clauses<'tcx> { + struct CollectClauses<'a, 'tcx> { + clauses: Vec>, + fcx: &'a FnCtxt<'a, 'tcx>, + } + + impl<'tcx> intravisit::Visitor<'tcx> for CollectClauses<'_, 'tcx> { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { + if let Some(clauses) = self.fcx.trait_ascriptions.borrow().get(&ty.hir_id.local_id) + { + self.clauses.extend(clauses.iter().cloned()); + } + intravisit::walk_ty(self, ty) + } + } + + let mut clauses = CollectClauses { clauses: vec![], fcx: self }; + clauses.visit_ty(hir_ty); + self.tcx.mk_clauses(&clauses.clauses) + } + #[instrument(level = "debug", skip_all)] - pub(crate) fn lower_ty_saving_user_provided_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { + pub(crate) fn lower_ty_saving_user_provided_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> Ty<'tcx> { let ty = self.lower_ty(hir_ty); debug!(?ty); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index aacdcf027b6ec..b9011e89f04ef 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -10,10 +10,11 @@ use std::ops::Deref; use hir::def_id::CRATE_DEF_ID; use rustc_errors::DiagCtxtHandle; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{self as hir, HirId, ItemLocalMap}; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; use rustc_infer::infer; +use rustc_infer::traits::Obligation; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; use rustc_span::symbol::Ident; @@ -114,6 +115,12 @@ pub(crate) struct FnCtxt<'a, 'tcx> { pub(super) diverging_fallback_behavior: DivergingFallbackBehavior, pub(super) diverging_block_behavior: DivergingBlockBehavior, + + /// Clauses that we lowered as part of the `impl_trait_in_bindings` feature. + /// + /// These are stored here so we may collect them when canonicalizing user + /// type ascriptions later. + pub(super) trait_ascriptions: RefCell>>>, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -141,6 +148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: Cell::new(false), diverging_fallback_behavior, diverging_block_behavior, + trait_ascriptions: Default::default(), } } @@ -252,6 +260,30 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { } } + fn register_trait_ascription_bounds( + &self, + bounds: Vec<(ty::Clause<'tcx>, Span)>, + hir_id: HirId, + _span: Span, + ) { + for (clause, span) in bounds { + if clause.has_escaping_bound_vars() { + self.dcx().span_delayed_bug(span, "clause should have no escaping bound vars"); + continue; + } + + self.trait_ascriptions.borrow_mut().entry(hir_id.local_id).or_default().push(clause); + + let clause = self.normalize(span, clause); + self.register_predicate(Obligation::new( + self.tcx, + self.misc(span), + self.param_env, + clause, + )); + } + } + fn probe_ty_param_bounds( &self, _: Span, diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 849c200ab0a9c..48fd5f1f98249 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -92,9 +92,12 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { Some(ref ty) => { let o_ty = self.fcx.lower_ty(ty); - let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(ty::UserType::new( - ty::UserTypeKind::Ty(o_ty.raw), - )); + let c_ty = self.fcx.infcx.canonicalize_user_type_annotation( + ty::UserType::new_with_bounds( + ty::UserTypeKind::Ty(o_ty.raw), + self.fcx.collect_impl_trait_clauses_from_hir_ty(ty), + ), + ); debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx .typeck_results diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index f4135d8dbc690..3337f7ceee7d7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -323,7 +323,7 @@ macro_rules! define_callbacks { // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(target_pointer_width = "64")] const _: () = { - if mem::size_of::>() > 80 { + if mem::size_of::>() > 88 { panic!("{}", concat!( "the query `", stringify!($name), diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 744a7384e8bf7..551c113aa5922 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -704,11 +704,18 @@ pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>; #[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct UserType<'tcx> { pub kind: UserTypeKind<'tcx>, + pub bounds: ty::Clauses<'tcx>, } impl<'tcx> UserType<'tcx> { pub fn new(kind: UserTypeKind<'tcx>) -> UserType<'tcx> { - UserType { kind } + UserType { kind, bounds: ty::ListWithCachedTypeInfo::empty() } + } + + /// A user type annotation with additional bounds that need to be enforced. + /// These bounds are lowered from `impl Trait` in bindings. + pub fn new_with_bounds(kind: UserTypeKind<'tcx>, bounds: ty::Clauses<'tcx>) -> UserType<'tcx> { + UserType { kind, bounds } } } @@ -733,7 +740,9 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { /// Returns `true` if this represents the generic parameters of the form `[?0, ?1, ?2]`, /// i.e., each thing is mapped to a canonical variable with the same index. fn is_identity(&self) -> bool { - // TODO: + if !self.value.bounds.is_empty() { + return false; + } match self.value.kind { UserTypeKind::Ty(_) => false, @@ -779,9 +788,13 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { impl<'tcx> std::fmt::Display for UserType<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // TODO: - - self.kind.fmt(f) + if self.bounds.is_empty() { + self.kind.fmt(f) + } else { + self.kind.fmt(f)?; + write!(f, " + ")?; + std::fmt::Debug::fmt(&self.bounds, f) + } } } diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 164cbc69595bc..7ccbc7bdc5722 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -371,6 +371,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Tup, Path, OpaqueDef, + TraitAscription, TraitObject, Typeof, Infer, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index 319c7ece42bfc..254dee794f1bc 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -52,6 +52,12 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>( relate_mir_and_user_args(ocx, param_env, span, mir_ty, def_id, user_args)? } }; + + // Enforce any bounds that come from impl trait in bindings. + ocx.register_obligations(user_ty.bounds.iter().map(|clause| { + Obligation::new(ocx.infcx.tcx, ObligationCause::dummy_with_span(span), param_env, clause) + })); + Ok(()) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a201a9bbfedc6..25f88c8797f8a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1839,11 +1839,15 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T DynTrait(bounds, lifetime) } TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), - // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. - TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer, TyKind::UnsafeBinder(..) => { unimplemented!("unsafe binders are not supported yet") } + // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. + TyKind::Infer + | TyKind::Err(_) + | TyKind::Typeof(..) + | TyKind::InferDelegation(..) + | TyKind::TraitAscription(_) => Infer, } } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index bd4ce7ab9225c..e3959903fddc9 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -814,6 +814,7 @@ impl TyCoercionStability { | TyKind::Tup(_) | TyKind::Path(_) => Self::Deref, TyKind::OpaqueDef(..) + | TyKind::TraitAscription(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 279025b9bf933..4b604f658b8d6 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1260,7 +1260,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) - | TyKind::OpaqueDef(_) => {}, + | TyKind::OpaqueDef(_) + | TyKind::TraitAscription(_) => {}, } } diff --git a/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs new file mode 100644 index 0000000000000..f6574b481203c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs @@ -0,0 +1,4 @@ +fn main() { + let x: impl Sized = (); + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings +} diff --git a/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr new file mode 100644 index 0000000000000..58f058fb56412 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr @@ -0,0 +1,14 @@ +error[E0562]: `impl Trait` is not allowed in the type of variable bindings + --> $DIR/feature-gate-impl-trait-in-bindings.rs:2:12 + | +LL | let x: impl Sized = (); + | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/in-bindings/bad-nesting.rs b/tests/ui/impl-trait/in-bindings/bad-nesting.rs new file mode 100644 index 0000000000000..7f4b44cc691f3 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/bad-nesting.rs @@ -0,0 +1,10 @@ +#![feature(impl_trait_in_bindings)] + +trait Foo {} + +impl Foo<()> for () {} + +fn main() { + let x: impl Foo = (); + //~^ ERROR nested `impl Trait` is not allowed +} diff --git a/tests/ui/impl-trait/in-bindings/bad-nesting.stderr b/tests/ui/impl-trait/in-bindings/bad-nesting.stderr new file mode 100644 index 0000000000000..d82ce733254db --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/bad-nesting.stderr @@ -0,0 +1,12 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/bad-nesting.rs:8:21 + | +LL | let x: impl Foo = (); + | ---------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0666`. diff --git a/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs b/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs new file mode 100644 index 0000000000000..b57fef9be21c2 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs @@ -0,0 +1,14 @@ +#![feature(impl_trait_in_bindings)] + +trait Foo<'a> { + type Out; +} + +impl<'a> Foo<'a> for () { + type Out = (); +} + +fn main() { + let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &(); + //~^ ERROR cannot capture late-bound lifetime in `impl Trait` in binding +} diff --git a/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr b/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr new file mode 100644 index 0000000000000..640f6f3692797 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr @@ -0,0 +1,8 @@ +error: cannot capture late-bound lifetime in `impl Trait` in binding + --> $DIR/escaping-bound-var.rs:12:52 + | +LL | let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &(); + | -- lifetime defined here ^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/in-bindings/lifetime-failure.rs b/tests/ui/impl-trait/in-bindings/lifetime-failure.rs new file mode 100644 index 0000000000000..df685c36c435e --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/lifetime-failure.rs @@ -0,0 +1,12 @@ +#![feature(impl_trait_in_bindings)] + +trait Static: 'static {} +impl Static for T {} + +struct W(T); + +fn main() { + let local = 0; + let _: W = W(&local); + //~^ ERROR `local` does not live long enough +} diff --git a/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr b/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr new file mode 100644 index 0000000000000..189efcbca8778 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr @@ -0,0 +1,16 @@ +error[E0597]: `local` does not live long enough + --> $DIR/lifetime-failure.rs:10:31 + | +LL | let local = 0; + | ----- binding `local` declared here +LL | let _: W = W(&local); + | -------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `local` is borrowed for `'static` +LL | +LL | } + | - `local` dropped here while still borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs new file mode 100644 index 0000000000000..7e5d2cf18bd7d --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs @@ -0,0 +1,10 @@ +#![feature(impl_trait_in_bindings)] + +trait Static {} +impl Static for T {} + +fn main() { + let local = 0; + let _: impl IntoIterator = [&local]; + //~^ ERROR `local` does not live long enough +} diff --git a/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr new file mode 100644 index 0000000000000..c0326b379499f --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr @@ -0,0 +1,16 @@ +error[E0597]: `local` does not live long enough + --> $DIR/nesting-lifetime-failure.rs:8:53 + | +LL | let local = 0; + | ----- binding `local` declared here +LL | let _: impl IntoIterator = [&local]; + | ------------------------------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `local` is borrowed for `'static` +LL | +LL | } + | - `local` dropped here while still borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/impl-trait/in-bindings/nesting.rs b/tests/ui/impl-trait/in-bindings/nesting.rs new file mode 100644 index 0000000000000..51ff42bcafe5d --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/nesting.rs @@ -0,0 +1,7 @@ +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +fn main() { + let _: impl IntoIterator = ["hello", " world"]; +} diff --git a/tests/ui/impl-trait/in-bindings/simple.rs b/tests/ui/impl-trait/in-bindings/simple.rs new file mode 100644 index 0000000000000..8052f5a188090 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/simple.rs @@ -0,0 +1,10 @@ +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +trait Foo {} +impl Foo for () {} + +fn main() { + let x: impl Foo = (); +} diff --git a/tests/ui/impl-trait/in-bindings/trait-failure.rs b/tests/ui/impl-trait/in-bindings/trait-failure.rs new file mode 100644 index 0000000000000..e4052437f2fae --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/trait-failure.rs @@ -0,0 +1,13 @@ +#![feature(impl_trait_in_bindings)] + +trait Foo {} + +struct W(T); +impl Foo for W where T: Foo {} + +fn main() { + let x: impl Foo = W(()); + //~^ ERROR the trait bound `(): Foo` is not satisfied + let x: W = W(()); + //~^ ERROR the trait bound `(): Foo` is not satisfied +} diff --git a/tests/ui/impl-trait/in-bindings/trait-failure.stderr b/tests/ui/impl-trait/in-bindings/trait-failure.stderr new file mode 100644 index 0000000000000..332cefd796d1d --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/trait-failure.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/trait-failure.rs:9:17 + | +LL | let x: impl Foo = W(()); + | ^^^ the trait `Foo` is not implemented for `()` + | + = help: the trait `Foo` is implemented for `W` +note: required for `W<()>` to implement `Foo` + --> $DIR/trait-failure.rs:6:9 + | +LL | impl Foo for W where T: Foo {} + | ^^^ ^^^^ --- unsatisfied trait bound introduced here + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/trait-failure.rs:11:19 + | +LL | let x: W = W(()); + | ^^^ the trait `Foo` is not implemented for `()` + | + = help: the trait `Foo` is implemented for `W` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr index c75c0fa0f055d..02d609602336d 100644 --- a/tests/ui/impl-trait/issues/issue-54600.stderr +++ b/tests/ui/impl-trait/issues/issue-54600.stderr @@ -5,6 +5,9 @@ LL | let x: Option = Some(44_u32); | ^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr index de75256d5a939..805ea04f0bcf6 100644 --- a/tests/ui/impl-trait/issues/issue-54840.stderr +++ b/tests/ui/impl-trait/issues/issue-54840.stderr @@ -5,6 +5,9 @@ LL | let j: &impl Add = &i; | ^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr index 8231732bba1c2..bc921d5cd2c87 100644 --- a/tests/ui/impl-trait/issues/issue-58504.stderr +++ b/tests/ui/impl-trait/issues/issue-58504.stderr @@ -5,6 +5,9 @@ LL | let gens: [impl Coroutine;2] = [ mk_gen(), mk_gen() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr index 0c81c69def3aa..825777e492344 100644 --- a/tests/ui/impl-trait/issues/issue-58956.stderr +++ b/tests/ui/impl-trait/issues/issue-58956.stderr @@ -13,6 +13,9 @@ LL | let x: Wrap = Wrap(B); | ^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr index 28c463cea8504..10e5fffa43051 100644 --- a/tests/ui/impl-trait/issues/issue-70971.stderr +++ b/tests/ui/impl-trait/issues/issue-70971.stderr @@ -5,6 +5,9 @@ LL | let x : (impl Copy,) = (true,); | ^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr index 96825eabec7ed..d7c0c494454c4 100644 --- a/tests/ui/impl-trait/issues/issue-79099.stderr +++ b/tests/ui/impl-trait/issues/issue-79099.stderr @@ -16,6 +16,9 @@ LL | let f: impl core::future::Future = async { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr index 02d2ce28fb3ed..21dd355065ddf 100644 --- a/tests/ui/impl-trait/issues/issue-84919.stderr +++ b/tests/ui/impl-trait/issues/issue-84919.stderr @@ -5,6 +5,9 @@ LL | let _x: impl Trait = (); | ^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr index 78274a056ec68..31f3b2f5bf28e 100644 --- a/tests/ui/impl-trait/issues/issue-87295.stderr +++ b/tests/ui/impl-trait/issues/issue-87295.stderr @@ -5,6 +5,9 @@ LL | let _do_not_waste: Struct> = Struct::new(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 13f50fcea7b3f..400df87ca3ffa 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -333,6 +333,9 @@ LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in closure return types --> $DIR/where-allowed.rs:253:46 diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr index 37d38a76a4034..c3872ea89681b 100644 --- a/tests/ui/typeck/issue-104513-ice.stderr +++ b/tests/ui/typeck/issue-104513-ice.stderr @@ -11,6 +11,9 @@ LL | let _: S = S; | ^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors