diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8ad3270c5103e..9d0e97e99e1fd 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2102,6 +2102,9 @@ pub enum TyKind { Err, /// Placeholder for a `va_list`. CVarArgs, + /// Pattern types like `u32 as 1..=`, which is the same as `NonZeroU32`, + /// just as part of the type system. + Pat(P, P), } impl TyKind { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 1dd62626b8f5e..307db6420eeab 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -476,6 +476,10 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { } TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), TyKind::Paren(ty) => vis.visit_ty(ty), + TyKind::Pat(ty, pat) => { + vis.visit_ty(ty); + vis.visit_pat(pat); + } TyKind::Path(qself, path) => { vis.visit_qself(qself); vis.visit_path(path); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e7b2e4b1cb4b0..279fda1cc5c9a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -416,6 +416,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { } visitor.visit_path(path, typ.id); } + TyKind::Pat(ty, pat) => { + visitor.visit_ty(ty); + visitor.visit_pat(pat); + } TyKind::Array(ty, length) => { visitor.visit_ty(ty); visitor.visit_anon_const(length) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a04a259529310..2314e393cd135 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1372,7 +1372,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } } - TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), + TyKind::MacCall(_) => { + span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now") + } TyKind::CVarArgs => { self.tcx.sess.delay_span_bug( t.span, @@ -1380,6 +1382,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); hir::TyKind::Err } + TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)), }; hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 89ba6f936d144..1b226b884abd4 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -313,6 +313,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::DynStar, ..) => { gate_feature_post!(&self, dyn_star, ty.span, "dyn* trait objects are unstable"); } + ast::TyKind::Pat(..) => { + gate_feature_post!(&self, pattern_types, ty.span, "pattern types are unstable"); + } _ => {} } visit::walk_ty(self, ty) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index fa8567eac6090..fb1316140a162 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1092,6 +1092,11 @@ impl<'a> State<'a> { ast::TyKind::CVarArgs => { self.word("..."); } + ast::TyKind::Pat(ty, pat) => { + self.print_type(ty); + self.word(" is "); + self.print_pat(pat); + } } self.end(); } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index b0e007ce0097b..82ec963489304 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -194,6 +194,15 @@ fn push_debuginfo_type_name<'tcx>( } } } + ty::Pat(inner_type, pat) => { + if cpp_like_debuginfo { + output.push_str("pat$<"); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + write!(output, ",{:?}>", pat).unwrap(); + } else { + write!(output, "{:?}", t).unwrap(); + } + } ty::Slice(inner_type) => { if cpp_like_debuginfo { output.push_str("slice2$<"); diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index c52886b77e64b..ac783b87c3e5f 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -96,6 +96,8 @@ pub(crate) fn const_to_valtree_inner<'tcx>( Ok(ty::ValTree::Leaf(val.assert_int())) } + ty::Pat(..) => const_to_valtree_inner(ecx, &ecx.mplace_field(&place, 0).unwrap(), num_nodes), + // Raw pointers are not allowed in type level constants, as we cannot properly test them for // equality at compile-time (see `ptr_guaranteed_cmp`). // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to @@ -265,7 +267,7 @@ pub fn valtree_to_const_value<'tcx>( let (param_env, ty) = param_env_ty.into_parts(); let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); - match ty.kind() { + match *ty.kind() { ty::FnDef(..) => { assert!(valtree.unwrap_branch().is_empty()); ConstValue::ZeroSized @@ -276,6 +278,7 @@ pub fn valtree_to_const_value<'tcx>( "ValTrees for Bool, Int, Uint, Float or Char should have the form ValTree::Leaf" ), }, + ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree), ty::Ref(_, _, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => { let mut place = match ty.kind() { ty::Ref(_, inner_ty, _) => { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 907f014dfb518..192ac70bb2dca 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -83,6 +83,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => { throw_inval!(TooGeneric) } + ty::Pat(..) => { + unimplemented!("pattern types need to calculate pattern from their pattern") + } ty::Bound(_, _) => bug!("bound ty during ctfe"), ty::Bool | ty::Char diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index aa539516d5e50..8aaedddb6ae62 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -584,6 +584,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Nothing to check. Ok(true) } + ty::Pat(..) => unimplemented!(), // The above should be all the primitive types. The rest is compound, we // check them by visiting their fields/variants. ty::Adt(..) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 4e80a28518668..3f99a52d276cf 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -40,6 +40,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Uint(_) | ty::Float(_) | ty::Str + | ty::Pat(_, _) | ty::Array(_, _) | ty::Slice(_) | ty::RawPtr(_) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 41f458f6c1785..3d6fcabd74a42 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -124,3 +124,8 @@ hir_analysis_linkage_type = hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` .label = deref recursion limit reached .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) + +hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pattern types" + .label = "this type is the same as the inner type without a pattern" + +hir_analysis_pattern_type_non_const_range = "range patterns must have constant range start and end" diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index dca678dff7a79..f6c9462b572c4 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -239,6 +239,9 @@ lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stab lint_improper_ctypes_char_reason = the `char` type has no C equivalent lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead +lint_improper_ctypes_pat_reason = pattern types have no C equivalent +lint_improper_ctypes_pat_help = consider using the patterned type instead + lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 323f5a368fc09..2b4679ee3b54a 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -477,6 +477,8 @@ declare_features! ( (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), /// Allows using `#[optimize(X)]`. (active, optimize_attribute, "1.34.0", Some(54882), None), + /// Allows using pattern types. + (incomplete, pattern_types, "CURRENT_RUSTC_VERSION", Some(54882), None), /// Allows `extern "platform-intrinsic" { ... }`. (active, platform_intrinsics, "1.4.0", Some(27731), None), /// Allows using `#![plugin(myplugin)]`. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a063307af0cb4..d49153201b503 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -256,7 +256,7 @@ pub struct InferArg { } impl InferArg { - pub fn to_ty(&self) -> Ty<'_> { + pub fn to_ty(&self) -> Ty<'static> { Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id } } } @@ -2682,6 +2682,8 @@ pub enum TyKind<'hir> { Infer, /// Placeholder for a type that has failed to be defined. Err, + /// Pattern types (`u32 as 1..`) + Pat(&'hir Ty<'hir>, &'hir Pat<'hir>), } #[derive(Debug, HashStable_Generic)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index f632babab0b24..963dabfc6e8d2 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -845,6 +845,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { } TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::Err => {} + TyKind::Pat(ty, pat) => { + visitor.visit_ty(ty); + visitor.visit_pat(pat) + } } } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 5e8f727df69da..96a9a0907c982 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -169,7 +169,7 @@ fn generic_arg_mismatch_err( /// instantiate a `GenericArg`. /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then /// creates a suitable inference variable. -pub fn create_substs_for_generic_args<'tcx, 'a>( +pub fn create_substs_for_generic_args<'tcx: 'a, 'a>( tcx: TyCtxt<'tcx>, def_id: DefId, parent_substs: &[subst::GenericArg<'tcx>], diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index bec9f0ff0772c..59ff3abe6b3a6 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -11,8 +11,9 @@ use crate::astconv::generics::{ use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; use crate::errors::{ - AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits, - TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified, + AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, NonConstRange, + TraitObjectDeclaredWithNoTraits, TypeofReservedKeywordUsed, + ValueOfAssociatedStructAlreadySpecified, WildPatTy, }; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; @@ -29,6 +30,7 @@ use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_middle::middle::stability::AllowUnstable; +use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitable}; @@ -106,7 +108,7 @@ pub trait AstConv<'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx>; @@ -140,14 +142,14 @@ struct ConvertedBinding<'a, 'tcx> { hir_id: hir::HirId, item_name: Ident, kind: ConvertedBindingKind<'a, 'tcx>, - gen_args: &'a GenericArgs<'a>, + gen_args: &'tcx GenericArgs<'tcx>, span: Span, } #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { Equality(ty::Term<'tcx>), - Constraint(&'a [hir::GenericBound<'a>]), + Constraint(&'a [hir::GenericBound<'tcx>]), } /// New-typed boolean indicating whether explicit late-bound lifetimes @@ -199,12 +201,12 @@ pub struct GenericArgCountResult { } pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> { - fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'a>>, bool); + fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool); fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> subst::GenericArg<'tcx>; fn inferred_kind( @@ -279,7 +281,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, ) -> SubstsRef<'tcx> { let (substs, _) = self.create_substs_for_ast_path( span, @@ -336,7 +338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id: DefId, parent_substs: &[subst::GenericArg<'tcx>], seg: &hir::PathSegment<'_>, - generic_args: &'a hir::GenericArgs<'_>, + generic_args: &'a hir::GenericArgs<'tcx>, infer_args: bool, self_ty: Option>, constness: ty::BoundConstness, @@ -385,14 +387,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { struct SubstsForAstPathCtxt<'a, 'tcx> { astconv: &'a (dyn AstConv<'tcx> + 'a), def_id: DefId, - generic_args: &'a GenericArgs<'a>, + generic_args: &'a GenericArgs<'tcx>, span: Span, inferred_params: Vec, infer_args: bool, } impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> { - fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'a>>, bool) { + fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) { if did == self.def_id { (Some(self.generic_args), self.infer_args) } else { @@ -404,11 +406,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> subst::GenericArg<'tcx> { let tcx = self.astconv.tcx(); - let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| { + let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| { if has_default { tcx.check_optional_stability( param.def_id, @@ -556,7 +558,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn create_assoc_bindings_for_generic_args<'a>( &self, - generic_args: &'a hir::GenericArgs<'_>, + generic_args: &'a hir::GenericArgs<'tcx>, ) -> Vec> { // Convert associated-type bindings or constraints into a separate vector. // Example: Given this: @@ -602,7 +604,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, parent_substs: SubstsRef<'tcx>, ) -> SubstsRef<'tcx> { debug!( @@ -635,7 +637,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// are disallowed. Otherwise, they are pushed onto the vector given. pub fn instantiate_mono_trait_ref( &self, - trait_ref: &hir::TraitRef<'_>, + trait_ref: &hir::TraitRef<'tcx>, self_ty: Ty<'tcx>, constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { @@ -662,7 +664,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_ref_span: Span, trait_def_id: DefId, trait_segment: &hir::PathSegment<'_>, - args: &GenericArgs<'_>, + args: &GenericArgs<'tcx>, infer_args: bool, self_ty: Ty<'tcx>, ) -> GenericArgCountResult { @@ -730,7 +732,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))] pub(crate) fn instantiate_poly_trait_ref( &self, - trait_ref: &hir::TraitRef<'_>, + trait_ref: &hir::TraitRef<'tcx>, span: Span, constness: ty::BoundConstness, self_ty: Ty<'tcx>, @@ -769,7 +771,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { lang_item: hir::LangItem, span: Span, hir_id: hir::HirId, - args: &GenericArgs<'_>, + args: &GenericArgs<'tcx>, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, ) { @@ -802,7 +804,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, - trait_segment: &hir::PathSegment<'_>, + trait_segment: &hir::PathSegment<'tcx>, is_impl: bool, constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { @@ -826,7 +828,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, - trait_segment: &'a hir::PathSegment<'a>, + trait_segment: &'a hir::PathSegment<'tcx>, is_impl: bool, constness: ty::BoundConstness, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { @@ -937,13 +939,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. #[instrument(level = "debug", skip(self, ast_bounds, bounds))] - pub(crate) fn add_bounds<'hir, I: Iterator>>( + pub(crate) fn add_bounds<'hir, I: Iterator>>( &self, param_ty: Ty<'tcx>, ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, - ) { + ) where + 'tcx: 'hir, + { for ast_bound in ast_bounds { match ast_bound { hir::GenericBound::Trait(poly_trait_ref, modifier) => { @@ -1001,7 +1005,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub(crate) fn compute_bounds( &self, param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'tcx>], ) -> Bounds<'tcx> { self.compute_bounds_inner(param_ty, ast_bounds) } @@ -1011,7 +1015,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub(crate) fn compute_bounds_that_match_assoc_type( &self, param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'tcx>], assoc_name: Ident, ) -> Bounds<'tcx> { let mut result = Vec::new(); @@ -1031,7 +1035,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn compute_bounds_inner( &self, param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'tcx>], ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); @@ -1269,7 +1273,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, did: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, ) -> Ty<'tcx> { let substs = self.ast_path_substs_for_ty(span, did, item_segment); self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs) @@ -1278,7 +1282,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn conv_object_ty_poly_trait_ref( &self, span: Span, - hir_trait_bounds: &[hir::PolyTraitRef<'_>], + hir_trait_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, borrowed: bool, representation: DynKind, @@ -1925,7 +1929,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, qself_ty: Ty<'tcx>, qself: &hir::Ty<'_>, - assoc_segment: &hir::PathSegment<'_>, + assoc_segment: &hir::PathSegment<'tcx>, permit_variants: bool, ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> { let tcx = self.tcx(); @@ -2286,8 +2290,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, opt_self_ty: Option>, item_def_id: DefId, - trait_segment: &hir::PathSegment<'_>, - item_segment: &hir::PathSegment<'_>, + trait_segment: &hir::PathSegment<'tcx>, + item_segment: &hir::PathSegment<'tcx>, constness: ty::BoundConstness, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2604,7 +2608,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn res_to_ty( &self, opt_self_ty: Option>, - path: &hir::Path<'_>, + path: &hir::Path<'tcx>, permit_variants: bool, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2843,20 +2847,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Parses the programmer's textual representation of a type into our /// internal notion of a type. - pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.ast_ty_to_ty_inner(ast_ty, false, false) } /// Parses the programmer's textual representation of a type into our /// internal notion of a type. This is meant to be used within a path. - pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.ast_ty_to_ty_inner(ast_ty, false, true) } /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. #[instrument(level = "debug", skip(self), ret)] - fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> { + fn ast_ty_to_ty_inner( + &self, + ast_ty: &hir::Ty<'tcx>, + borrowed: bool, + in_path: bool, + ) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match &ast_ty.kind { @@ -2961,6 +2970,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // handled specially and will not descend into this routine. self.ty_infer(None, ast_ty.span) } + hir::TyKind::Pat(ty, pat) => { + let ty = self.ast_ty_to_ty(ty); + let pat_ty = match pat.kind { + hir::PatKind::Wild => { + let err = tcx.sess.emit_err(WildPatTy { span: pat.span }); + tcx.ty_error_with_guaranteed(err) + } + hir::PatKind::Binding(_, _, _, _) => todo!(), + hir::PatKind::Struct(_, _, _) => todo!(), + hir::PatKind::TupleStruct(_, _, _) => todo!(), + hir::PatKind::Or(_) => todo!(), + hir::PatKind::Path(_) => todo!(), + hir::PatKind::Tuple(_, _) => todo!(), + hir::PatKind::Box(_) => todo!(), + hir::PatKind::Ref(_, _) => todo!(), + hir::PatKind::Lit(_) => todo!(), + hir::PatKind::Range(start, end, include_end) => { + let expr_to_const = |expr: &'tcx hir::Expr<'tcx>, neg| -> ty::Const<'tcx> { + match &expr.kind { + hir::ExprKind::Lit(lit) => { + let lit_input = LitToConstInput { lit: &lit.node, ty, neg }; + match tcx.lit_to_const(lit_input) { + Ok(c) => c, + Err(LitToConstError::Reported(err)) => { + tcx.const_error_with_guaranteed(ty, err) + } + Err(LitToConstError::TypeError) => todo!(), + } + } + _ => { + let err = tcx.sess.emit_err(NonConstRange { span: expr.span }); + tcx.const_error_with_guaranteed(ty, err) + } + } + }; + let expr_to_const = |expr, neg| { + let c = expr_to_const(expr, neg); + self.record_ty(expr.hir_id, c.ty(), expr.span); + c + }; + let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| match &expr.kind { + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => expr_to_const(expr, true), + _ => expr_to_const(expr, false), + }; + let expr_to_const = |expr| { + let c = expr_to_const(expr); + self.record_ty(expr.hir_id, c.ty(), expr.span); + c + }; + + let start = start.map(expr_to_const); + let end = end.map(expr_to_const); + + let include_end = match include_end { + hir::RangeEnd::Included => true, + hir::RangeEnd::Excluded => false, + }; + + let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end }); + tcx.mk_ty(ty::Pat(ty, pat)) + } + hir::PatKind::Slice(_, _, _) => todo!(), + }; + self.record_ty(pat.hir_id, ty, pat.span); + pat_ty + } hir::TyKind::Err => tcx.ty_error(), }; @@ -2997,7 +3072,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) } } - pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { + pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option>) -> Ty<'tcx> { match ty.kind { hir::TyKind::Infer if expected_ty.is_some() => { self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); @@ -3013,7 +3088,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir_id: hir::HirId, unsafety: hir::Unsafety, abi: abi::Abi, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, generics: Option<&hir::Generics<'_>>, hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 5b9b57da3820e..ff43f6c2b9838 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1815,7 +1815,7 @@ fn receiver_is_implemented<'tcx>( fn check_variances_for_type_defn<'tcx>( tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, - hir_generics: &hir::Generics<'_>, + hir_generics: &hir::Generics<'tcx>, ) { let ty = tcx.type_of(item.owner_id); if tcx.has_error_field(ty) { diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index c1b0237b2d1f1..26154b6d763c7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -208,6 +208,9 @@ impl<'tcx> InherentCollect<'tcx> { .note("define and implement a new trait or type instead") .emit(); } + ty::Pat(..) => { + self.tcx.sess.span_err(ty.span, "cannot define inherent `impl` for pattern types"); + } ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index cc7235a61c0b8..30e5837553c14 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -351,7 +351,7 @@ impl<'tcx> ItemCtxt<'tcx> { ItemCtxt { tcx, item_def_id } } - pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.astconv().ast_ty_to_ty(ast_ty) } @@ -410,7 +410,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { @@ -1179,7 +1179,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> fn infer_return_ty_for_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, - sig: &hir::FnSig<'_>, + sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'_>, def_id: LocalDefId, icx: &ItemCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 04f5f3f62765a..410d2ba5272c2 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -6,6 +6,10 @@ use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; +mod pattern_types; + +pub use pattern_types::*; + #[derive(Diagnostic)] #[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")] pub struct UnrecognizedAtomicOperation<'a> { diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs new file mode 100644 index 0000000000000..042c4b664f832 --- /dev/null +++ b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs @@ -0,0 +1,16 @@ +use rustc_macros::Diagnostic; +use rustc_span::Span; + +#[derive(Diagnostic)] +#[diag(hir_analysis_pattern_type_wild_pat)] +pub struct WildPatTy { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_pattern_type_non_const_range)] +pub struct NonConstRange { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index c2fa46e563e60..9105dbbf4c3fc 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -539,7 +539,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { /// A quasi-deprecated helper used in rustdoc and clippy to get /// the type from a HIR node. -pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { +pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { // In case there are any projections, etc., find the "environment" // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. @@ -550,7 +550,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { pub fn hir_trait_to_predicates<'tcx>( tcx: TyCtxt<'tcx>, - hir_trait: &hir::TraitRef<'_>, + hir_trait: &hir::TraitRef<'tcx>, self_ty: Ty<'tcx>, ) -> Bounds<'tcx> { // In case there are any projections, etc., find the "environment" diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 165782f209a0c..09cdbba0ec1b2 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -234,6 +234,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_ty(current, typ, variance); } + ty::Pat(typ, pat) => { + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + if let Some(start) = start { + self.add_constraints_from_const(current, start, variance); + } + if let Some(end) = end { + self.add_constraints_from_const(current, end, variance); + } + } + } + self.add_constraints_from_ty(current, typ, variance); + } + ty::Slice(typ) => { self.add_constraints_from_ty(current, typ, variance); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 7dcf9d8299f14..8fcc5c788dab8 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -366,6 +366,11 @@ impl<'a> State<'a> { hir::TyKind::Infer => { self.word("_"); } + hir::TyKind::Pat(ty, pat) => { + self.print_type(ty); + self.word(" is "); + self.print_pat(pat); + } } self.end() } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 8e21c084841d0..688b884d734eb 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -133,6 +133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::GeneratorWitnessMIR(..) | ty::RawPtr(_) | ty::Ref(..) + | ty::Pat(..) | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 90c4e5b6540b0..fb8640a1599fb 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -339,7 +339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, body: &hir::Body<'_>, expected_sig: Option>, ) -> ClosureSignatures<'tcx> { @@ -356,7 +356,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_no_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, body: &hir::Body<'_>, ) -> ClosureSignatures<'tcx> { let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); @@ -415,7 +415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_with_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, body: &hir::Body<'_>, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { @@ -468,7 +468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_with_mismatched_number_of_arguments( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, body: &hir::Body<'_>, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { @@ -510,7 +510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn merge_supplied_sig_with_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, body: &hir::Body<'_>, mut expected_sigs: ClosureSignatures<'tcx>, ) -> InferResult<'tcx, ClosureSignatures<'tcx>> { @@ -599,7 +599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn supplied_sig_of_closure( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, body: &hir::Body<'_>, ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; @@ -789,7 +789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Converts the types that the user supplied, in case that doing /// so should yield an error, but returns back a signature where /// all parameters are of type `TyErr`. - fn error_sig_of_closure(&self, decl: &hir::FnDecl<'_>) -> ty::PolyFnSig<'tcx> { + fn error_sig_of_closure(&self, decl: &hir::FnDecl<'tcx>) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; let supplied_arguments = decl.inputs.iter().map(|a| { diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ade9c037c5194..e870e3d8d4891 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1779,7 +1779,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx: &FnCtxt<'a, 'tcx>, expected: Ty<'tcx>, sp: Span, - fn_output: &hir::FnRetTy<'_>, + fn_output: &hir::FnRetTy<'tcx>, ) { let return_sp = fn_output.span(); err.span_label(return_sp, "expected because this return type..."); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 3561992e86ab4..0945f97dbca45 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1220,7 +1220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_method_call( &self, expr: &'tcx hir::Expr<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, rcvr: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, @@ -1505,7 +1505,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &hir::Expr<'_>, expected: Expectation<'tcx>, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a355a54d6959a..442050999636e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -376,13 +376,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { RawTy { raw: ty, normalized: self.normalize(span, ty) } } - pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> { + pub fn to_ty(&self, ast_t: &hir::Ty<'tcx>) -> RawTy<'tcx> { let t = self.astconv().ast_ty_to_ty(ast_t); self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None)); self.handle_raw_ty(ast_t.span, t) } - pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { let ty = self.to_ty(ast_ty); debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); @@ -987,7 +987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self, span), level = "debug")] pub fn instantiate_value_path( &self, - segments: &[hir::PathSegment<'_>], + segments: &'tcx [hir::PathSegment<'tcx>], self_ty: Option>, res: Res, span: Span, @@ -1166,13 +1166,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, path_segs: &'a [PathSeg], infer_args_for_err: &'a FxHashSet, - segments: &'a [hir::PathSegment<'a>], + segments: &'tcx [hir::PathSegment<'tcx>], } impl<'tcx, 'a> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for CreateCtorSubstsContext<'a, 'tcx> { fn args_for_def_id( &mut self, def_id: DefId, - ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { + ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) { if let Some(&PathSeg(_, index)) = self.path_segs.iter().find(|&PathSeg(did, _)| *did == def_id) { @@ -1193,7 +1193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 47ef106e75032..ec5a3086b3ce7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1225,7 +1225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_struct_path( &self, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, hir_id: hir::HirId, ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> { let path_span = qpath.span(); @@ -1663,7 +1663,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The newly resolved definition is written into `type_dependent_defs`. fn finish_resolving_struct_path( &self, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, path_span: Span, hir_id: hir::HirId, ) -> (Res, RawTy<'tcx>) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 4940015ddd571..79219b5cef1e0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -285,7 +285,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { let trait_ref = self.replace_bound_vars_with_fresh_vars( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6046e55c65c18..9587c4ab4a87b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -665,7 +665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn suggest_missing_return_type( &self, err: &mut Diagnostic, - fn_decl: &hir::FnDecl<'_>, + fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, can_suggest: bool, @@ -832,7 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diagnostic, expr: &'tcx hir::Expr<'tcx>, - fn_decl: &hir::FnDecl<'_>, + fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, id: hir::HirId, @@ -1242,7 +1242,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn suggest_associated_const( &self, err: &mut Diagnostic, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, expected_ty: Ty<'tcx>, ) -> bool { let Some((DefKind::AssocFn, old_def_id)) = self.typeck_results.borrow().type_dependent_def(expr.hir_id) else { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 65ca47bfe538b..79f41a85e8293 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -49,7 +49,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { debug!( "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})", @@ -75,7 +75,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { &mut self, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { // Adjust the self expression the user provided and obtain the adjusted type. let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick); @@ -325,7 +325,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn instantiate_method_substs( &mut self, pick: &probe::Pick<'tcx>, - seg: &hir::PathSegment<'_>, + seg: &'tcx hir::PathSegment<'tcx>, parent_substs: SubstsRef<'tcx>, ) -> SubstsRef<'tcx> { // Determine the values for the generic parameters of the method. @@ -349,13 +349,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { struct MethodSubstsCtxt<'a, 'tcx> { cfcx: &'a ConfirmContext<'a, 'tcx>, pick: &'a probe::Pick<'tcx>, - seg: &'a hir::PathSegment<'a>, + seg: &'tcx hir::PathSegment<'tcx>, } impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for MethodSubstsCtxt<'a, 'tcx> { fn args_for_def_id( &mut self, def_id: DefId, - ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { + ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) { if def_id == self.pick.item.def_id { if let Some(data) = self.seg.args { return (Some(data), false); @@ -367,7 +367,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> subst::GenericArg<'tcx> { match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 60d4dc326eea1..64c67b074eee3 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lookup_method( &self, self_ty: Ty<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 46799245222dc..1de321f742062 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -827,7 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_struct( &self, pat: &'tcx Pat<'tcx>, - qpath: &hir::QPath<'_>, + qpath: &hir::QPath<'tcx>, fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, expected: Ty<'tcx>, diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 87c6dfad5fa2b..ad1eced37668f 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -455,6 +455,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { | ty::Tuple(..) | ty::Alias(..) | ty::Foreign(..) + | ty::Pat(..) | ty::Param(..) => { if t.flags().intersects(self.needs_canonical_flags) { t.super_fold_with(self) diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 83d71edc2abd9..1981ff205317e 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -201,6 +201,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) + | ty::Pat(..) | ty::FnPtr(_) | ty::Dynamic(..) | ty::Never diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index e3d9566917125..5ce62e6104139 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -92,6 +92,7 @@ fn compute_components<'tcx>( } } + ty::Pat(element, _) | ty::Array(element, _) => { // Don't look into the len const as it doesn't affect regions compute_components(tcx, element, out, visited); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index b0a5d3674ad27..0d75437cb6fdb 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1000,6 +1000,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { help: Some(fluent::lint_improper_ctypes_char_help), }, + ty::Pat(..) => FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_pat_reason, + help: Some(fluent::lint_improper_ctypes_pat_help), + }, + ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => { FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None } } diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs index 89ea89cf502e5..29e6eb8686859 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_macros/src/newtype.rs @@ -93,7 +93,7 @@ impl Parse for Newtype { } impl ::rustc_serialize::Encodable for #name { fn encode(&self, e: &mut E) { - e.emit_u32(self.private); + e.emit_u32(self.as_u32()); } } } @@ -150,7 +150,7 @@ impl Parse for Newtype { #[inline] fn eq(l: &Option, r: &Option) -> bool { if #max_val < u32::MAX { - l.map(|i| i.private).unwrap_or(#max_val+1) == r.map(|i| i.private).unwrap_or(#max_val+1) + l.map(|i| i.as_u32()).unwrap_or(#max_val+1) == r.map(|i| i.as_u32()).unwrap_or(#max_val+1) } else { match (l, r) { (Some(l), Some(r)) => r == l, @@ -174,7 +174,7 @@ impl Parse for Newtype { #[rustc_layout_scalar_valid_range_end(#max)] #[rustc_pass_by_value] #vis struct #name { - private: u32, + private_use_as_methods_instead: u32, } #(#consts)* @@ -224,7 +224,7 @@ impl Parse for Newtype { /// Prefer using `from_u32`. #[inline] #vis const unsafe fn from_u32_unchecked(value: u32) -> Self { - Self { private: value } + Self { private_use_as_methods_instead: value as _ } } /// Extracts the value of this index as a `usize`. @@ -236,7 +236,7 @@ impl Parse for Newtype { /// Extracts the value of this index as a `u32`. #[inline] #vis const fn as_u32(self) -> u32 { - self.private + self.private_use_as_methods_instead as u32 } /// Extracts the value of this index as a `usize`. diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 72f4f6e649bcf..eaab900eef600 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -99,6 +99,7 @@ macro_rules! arena_types { [] tys: rustc_type_ir::WithCachedTypeInfo>, [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] consts: rustc_middle::ty::ConstData<'tcx>, + [] pats: rustc_middle::ty::PatternKind<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index b9a1e23879cca..4f62bccedcdb2 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -139,6 +139,12 @@ impl<'tcx, E: TyEncoder>> Encodable for ty::Const<'tcx> { } } +impl<'tcx, E: TyEncoder>> Encodable for ty::Pattern<'tcx> { + fn encode(&self, e: &mut E) { + self.0.0.encode(e); + } +} + impl<'tcx, E: TyEncoder>> Encodable for ConstAllocation<'tcx> { fn encode(&self, e: &mut E) { self.inner().encode(e) @@ -332,6 +338,12 @@ impl<'tcx, D: TyDecoder>> Decodable for ty::Const<'tcx> { } } +impl<'tcx, D: TyDecoder>> Decodable for ty::Pattern<'tcx> { + fn decode(decoder: &mut D) -> Self { + decoder.interner().mk_pat(Decodable::decode(decoder)) + } +} + impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] { fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc_from_iter( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b63b9e754cf46..5dc3360a5bdd6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -21,9 +21,9 @@ use crate::ty::query::{self, TyCtxtAt}; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar, FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, - ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, - ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, - Visibility, + ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, + TypeckResults, UintTy, Visibility, }; use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; use rustc_ast as ast; @@ -100,6 +100,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type SubstsRef = ty::SubstsRef<'tcx>; type DefId = DefId; type Ty = Ty<'tcx>; + type Pat = Pattern<'tcx>; type Const = ty::Const<'tcx>; type Region = Region<'tcx>; type TypeAndMut = TypeAndMut<'tcx>; @@ -144,6 +145,7 @@ pub struct CtxtInterners<'tcx> { projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, ConstData<'tcx>>, + pat: InternedSet<'tcx, PatternKind<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, LayoutS>, @@ -165,6 +167,7 @@ impl<'tcx> CtxtInterners<'tcx> { projs: Default::default(), place_elems: Default::default(), const_: Default::default(), + pat: Default::default(), const_allocation: Default::default(), bound_variable_kinds: Default::default(), layout: Default::default(), @@ -1204,6 +1207,7 @@ macro_rules! nop_list_lift { nop_lift! {type_; Ty<'a> => Ty<'tcx>} nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; Const<'a> => Const<'tcx>} +nop_lift! {pat; Pattern<'a> => Pattern<'tcx>} nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} @@ -1320,6 +1324,7 @@ impl<'tcx> TyCtxt<'tcx> { Param, Infer, Alias, + Pat, Foreign )?; @@ -1446,6 +1451,7 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>, const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>, + pat: mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>, const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: intern_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index bd78705cdb59b..8a9fad3fcc948 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -296,6 +296,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(def, _) => def.descr().into(), ty::Foreign(_) => "extern type".into(), ty::Array(..) => "array".into(), + ty::Pat(..) => "pattern type".into(), ty::Slice(_) => "slice".into(), ty::RawPtr(_) => "raw pointer".into(), ty::Ref(.., mutbl) => match mutbl { diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 9afa37e9ef3ee..6066126573698 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -21,6 +21,7 @@ pub enum SimplifiedType { StrSimplifiedType, ArraySimplifiedType, SliceSimplifiedType, + PatSimplifiedType, RefSimplifiedType(Mutability), PtrSimplifiedType(Mutability), NeverSimplifiedType, @@ -98,6 +99,7 @@ pub fn simplify_type<'tcx>( ty::Str => Some(StrSimplifiedType), ty::Array(..) => Some(ArraySimplifiedType), ty::Slice(..) => Some(SliceSimplifiedType), + ty::Pat(..) => Some(PatSimplifiedType), ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { @@ -202,6 +204,7 @@ impl DeepRejectCtxt { | ty::Slice(..) | ty::RawPtr(..) | ty::Dynamic(..) + | ty::Pat(..) | ty::Ref(..) | ty::Never | ty::Tuple(..) @@ -242,6 +245,9 @@ impl DeepRejectCtxt { } _ => false, }, + ty::Pat(obl_ty, _) => { + matches!(k, &ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty)) + } ty::Slice(obl_ty) => { matches!(k, &ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty)) } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index dc6f5851b7d88..85de344bb436a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -205,6 +205,20 @@ impl FlagComputation { self.add_const(len); } + &ty::Pat(ty, pat) => { + self.add_ty(ty); + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + if let Some(start) = start { + self.add_const(start) + } + if let Some(end) = end { + self.add_const(end) + } + } + } + } + &ty::Slice(tt) => self.add_ty(tt), ty::RawPtr(m) => { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cdcd6281f209b..4fd6280d01be3 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -647,6 +647,7 @@ where | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Foreign(..) + | ty::Pat(_, _) | ty::Dynamic(_, _, ty::Dyn) => { bug!("TyAndLayout::field({:?}): not applicable", this) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 09c3d5b736cf1..4e53cbe9c8731 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -87,6 +87,7 @@ pub use self::context::{ pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; pub use self::parameterized::ParameterizedOverTcx; +pub use self::pattern::{Pattern, PatternKind}; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ @@ -118,6 +119,7 @@ pub mod fold; pub mod inhabitedness; pub mod layout; pub mod normalize_erasing_regions; +pub mod pattern; pub mod print; pub mod query; pub mod relate; diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs new file mode 100644 index 0000000000000..ab1cc9f0a979f --- /dev/null +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -0,0 +1,48 @@ +use std::fmt; + +use crate::ty; +use rustc_data_structures::intern::Interned; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>); + +impl<'tcx> std::ops::Deref for Pattern<'tcx> { + type Target = PatternKind<'tcx>; + + fn deref(&self) -> &Self::Target { + &*self.0 + } +} + +impl<'tcx> fmt::Debug for Pattern<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", **self) + } +} + +impl<'tcx> fmt::Debug for PatternKind<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + PatternKind::Range { start, end, include_end } => { + if let Some(start) = start { + write!(f, "{start}")?; + } + write!(f, "..")?; + if include_end { + write!(f, "=")?; + } + if let Some(end) = end { + write!(f, "{end}")?; + } + Ok(()) + } + } + } +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] +pub enum PatternKind<'tcx> { + Range { start: Option>, end: Option>, include_end: bool }, +} diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 90bf3288ccf54..71f4dadfff3d4 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -247,7 +247,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::Dynamic(data, ..) => data.principal_def_id(), - ty::Array(subty, _) | ty::Slice(subty) => { + ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => { characteristic_def_id_of_type_cached(subty, visited) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e8e00d5feb873..0754647ec48e1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -649,6 +649,9 @@ pub trait PrettyPrinter<'tcx>: ty::Int(t) => p!(write("{}", t.name_str())), ty::Uint(t) => p!(write("{}", t.name_str())), ty::Float(t) => p!(write("{}", t.name_str())), + ty::Pat(ty, pat) => { + p!("(", print(ty), ") is ", write("{pat:?}")) + } ty::RawPtr(ref tm) => { p!(write( "*{} ", diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index fa87301df7e77..06370dbb7c1b8 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -13,6 +13,8 @@ use rustc_span::DUMMY_SP; use rustc_target::spec::abi; use std::iter; +use super::Pattern; + pub type RelateResult<'tcx, T> = Result>; #[derive(Clone, Debug)] @@ -394,6 +396,29 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> { } } +impl<'tcx> Relate<'tcx> for Pattern<'tcx> { + #[inline] + fn relate>( + relation: &mut R, + a: Self, + b: Self, + ) -> RelateResult<'tcx, Self> { + match (&*a, &*b) { + ( + &ty::PatternKind::Range { start: start_a, end: end_a, include_end: inc_a }, + &ty::PatternKind::Range { start: start_b, end: end_b, include_end: inc_b }, + ) => { + let start = relation.relate(start_a, start_b)?; + let end = relation.relate(end_a, end_b)?; + if inc_a != inc_b { + todo!() + } + Ok(relation.tcx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a })) + } + } + } +} + /// The main "type relation" routine. Note that this does not handle /// inference artifacts, so you should filter those out before calling /// it. @@ -579,6 +604,12 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( } } + (&ty::Pat(a_ty, a_pat), &ty::Pat(b_ty, b_pat)) => { + let ty = relation.relate(a_ty, b_ty)?; + let pat = relation.relate(a_pat, b_pat)?; + Ok(tcx.mk_ty(ty::Pat(ty, pat))) + } + _ => Err(TypeError::Sorts(expected_found(relation, a, b))), } } @@ -807,6 +838,20 @@ impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> { } } +impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Option { + fn relate>( + relation: &mut R, + a: Self, + b: Self, + ) -> RelateResult<'tcx, Self> { + match (a, b) { + (None, None) => Ok(None), + (Some(a), Some(b)) => relation.relate(a, b).map(Some), + _ => Err(TypeError::Mismatch), + } + } +} + impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { fn relate>( relation: &mut R, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8df639750c701..430fec70ce442 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -19,6 +19,8 @@ use std::ops::ControlFlow; use std::rc::Rc; use std::sync::Arc; +use super::Pattern; + impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { @@ -575,6 +577,19 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> { } } +impl<'tcx> TypeFoldable<'tcx> for Pattern<'tcx> { + fn try_fold_with>(self, folder: &mut F) -> Result { + let pat = (*self).clone().try_fold_with(folder)?; + Ok(if pat == *self { self } else { folder.tcx().mk_pat(pat) }) + } +} + +impl<'tcx> TypeVisitable<'tcx> for Pattern<'tcx> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + (**self).visit_with(visitor) + } +} + impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_binder(self) @@ -662,6 +677,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> { } ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), + ty::Pat(ty, pat) => ty::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?), ty::Bool | ty::Char @@ -709,6 +725,11 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> { ty::Closure(_did, ref substs) => substs.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), + ty::Pat(ty, pat) => { + ty.visit_with(visitor)?; + pat.visit_with(visitor) + } + ty::Bool | ty::Char | ty::Str diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 060d864389cb0..1caf401cc7262 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2167,6 +2167,8 @@ impl<'tcx> Ty<'tcx> { tcx.mk_projection(assoc_items[0], tcx.intern_substs(&[self.into()])) } + ty::Pat(ty, _) => ty.discriminant_ty(tcx), + ty::Bool | ty::Char | ty::Int(_) @@ -2245,6 +2247,7 @@ impl<'tcx> Ty<'tcx> { ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true), ty::Infer(ty::TyVar(_)) + | ty::Pat(..) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { @@ -2317,6 +2320,8 @@ impl<'tcx> Ty<'tcx> { ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)), + ty::Pat(ty, _) => ty.is_trivially_sized(tcx), + ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(), ty::Alias(..) | ty::Param(_) => false, @@ -2361,6 +2366,8 @@ impl<'tcx> Ty<'tcx> { field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy) } + ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(), + // Sometimes traits aren't implemented for every ABI or arity, // because we can't be generic over everything yet. ty::FnPtr(..) => false, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 796164b0d6af3..1cf7e39981d14 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -259,6 +259,11 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(_) => break, + ty::Pat(inner, _) => { + f(); + ty = inner; + } + ty::Alias(..) => { let normalized = normalize(ty); if ty == normalized { @@ -957,7 +962,7 @@ impl<'tcx> Ty<'tcx> { | ty::Error(_) | ty::FnPtr(_) => true, ty::Tuple(fields) => fields.iter().all(Self::is_trivially_freeze), - ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(), + ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_freeze(), ty::Adt(..) | ty::Bound(..) | ty::Closure(..) @@ -997,7 +1002,7 @@ impl<'tcx> Ty<'tcx> { | ty::Error(_) | ty::FnPtr(_) => true, ty::Tuple(fields) => fields.iter().all(Self::is_trivially_unpin), - ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), + ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_unpin(), ty::Adt(..) | ty::Bound(..) | ty::Closure(..) @@ -1112,7 +1117,7 @@ impl<'tcx> Ty<'tcx> { // // Because this function is "shallow", we return `true` for these composites regardless // of the type(s) contained within. - ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true, + ty::Pat(..) | ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true, // Raw pointers use bitwise comparison. ty::RawPtr(_) | ty::FnPtr(_) => true, @@ -1242,7 +1247,7 @@ pub fn needs_drop_components<'tcx>( ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop), - ty::Slice(ty) => needs_drop_components(*ty, target_layout), + ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components(*ty, target_layout), ty::Array(elem_ty, size) => { match needs_drop_components(*elem_ty, target_layout) { Ok(v) if v.is_empty() => Ok(v), @@ -1309,7 +1314,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { | ty::GeneratorWitnessMIR(..) | ty::Adt(..) => false, - ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), + ty::Array(ty, _) | ty::Slice(ty) | ty::Pat(ty, _) => is_trivially_const_drop(ty), ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty)), } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 182945b9c3db1..105cda8a330cc 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -151,6 +151,15 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::Bound(..) | ty::Foreign(..) => {} + ty::Pat(ty, pat) => { + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + stack.extend(start.map(Into::into)); + stack.extend(end.map(Into::into)); + } + } + stack.push(ty.into()); + } ty::Array(ty, len) => { stack.push(len.into()); stack.push(ty.into()); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 306cbcff149f7..11e6593fcaec9 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -342,6 +342,12 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_token.span); let mut ty = self.mk_ty(span, kind); + if self.eat_keyword(sym::is) { + let pat = self.parse_pat_no_top_alt(None)?; + let span = lo.to(self.prev_token.span); + ty = self.mk_ty(span, TyKind::Pat(ty, pat)); + } + // Try to recover from use of `+` with incorrect priority. match allow_plus { AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?, diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 51a19c8e3c02b..efbaca90ea002 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -334,6 +334,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { TraitObject, Typeof, Infer, + Pat, Err ] ); @@ -586,6 +587,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Never, Tup, Path, + Pat, TraitObject, ImplTrait, Paren, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4355286153223..fc0babd342477 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -268,6 +268,7 @@ where | ty::Tuple(..) | ty::RawPtr(..) | ty::Ref(..) + | ty::Pat(..) | ty::FnPtr(..) | ty::Param(..) | ty::Error(_) diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index a50a8178de38b..ef96b1ff05cca 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -322,7 +322,10 @@ impl<'hir> Sig for hir::Ty<'hir> { let item = scx.tcx.hir().item(item_id); item.make(offset, Some(item_id.hir_id()), scx) } - hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"), + hir::TyKind::Pat(..) + | hir::TyKind::Typeof(_) + | hir::TyKind::Infer + | hir::TyKind::Err => Err("Ty"), } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f1119214be44d..d456d84d927b2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -831,6 +831,7 @@ symbols! { intra_doc_pointers, intrinsics, irrefutable_let_patterns, + is, isa_attribute, isize, issue, @@ -1076,6 +1077,7 @@ symbols! { pat_param, path, pattern_parentheses, + pattern_types, phantom_data, pin, platform_intrinsics, diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index c9b4ab0a38d6e..26a96fb6598d3 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -521,6 +521,16 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } + ty::Pat(ty0, pat) => { + // u3patIE as vendor extended type + let mut s = String::from("u3patI"); + s.push_str(&encode_ty(tcx, *ty0, dict, options)); + write!(s, "{:?}", **pat).unwrap(); + s.push('E'); + compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); + typeid.push_str(&s); + } + ty::Slice(ty0) => { // u5sliceIE as vendor extended type let mut s = String::from("u5sliceI"); @@ -677,8 +687,11 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } ty::Array(ty0, len) => { - let len = len.kind().try_to_scalar().unwrap().to_u64().unwrap(); - ty = tcx.mk_array(transform_ty(tcx, *ty0, options), len); + ty = tcx.mk_ty(ty::Array(transform_ty(tcx, *ty0, options), *len)); + } + + ty::Pat(ty0, pat) => { + ty = tcx.mk_ty(ty::Pat(transform_ty(tcx, *ty0, options), *pat)); } ty::Slice(ty0) => { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 00d1ff5ceedf7..6376186daea90 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -419,6 +419,25 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { self = mt.ty.print(self)?; } + ty::Pat(ty, pat) => { + self.push("T"); + self = ty.print(self)?; + match *pat { + ty::PatternKind::Range { start, end, include_end } => { + if let Some(start) = start { + self = self.print_const(start)?; + } + let _ = write!(self.out, "_"); + if let Some(end) = end { + self = self.print_const(end)?; + } + + let _ = write!(self.out, "{:x}_", include_end as u8); + } + } + self.push("E"); + } + ty::Array(ty, len) => { self.push("A"); self = ty.print(self)?; diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 5690b6536bbc0..e153a024e794f 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -378,6 +378,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Dynamic(..) | ty::Closure(..) | ty::Generator(..) + | ty::Pat(..) | ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(..) | ty::Never @@ -425,6 +426,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::RawPtr(_) | ty::Ref(_, _, _) | ty::FnDef(_, _) + | ty::Pat(_, _) | ty::FnPtr(_) | ty::Alias(..) | ty::Closure(..) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index a23fdd24b4e42..a8fe208ebeffc 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -424,6 +424,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { | ty::Float(..) | ty::Array(..) | ty::RawPtr(..) + | ty::Pat(..) | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(..) diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index 5007a019e1892..d6fbefc732dd6 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -39,7 +39,9 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>( Ok(vec![element_ty]) } - ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]), + ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => { + Ok(vec![element_ty]) + } ty::Tuple(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet @@ -111,6 +113,7 @@ pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>( } ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Pat(ty, _) => Ok(vec![ty]), ty::Adt(def, substs) => { let sized_crit = def.sized_constraint(infcx.tcx); @@ -161,6 +164,7 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( } ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Pat(ty, _) => Ok(vec![ty]), ty::Closure(_, substs) => Ok(vec![substs.as_closure().tupled_upvars_ty()]), @@ -224,6 +228,7 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( | ty::Never | ty::Tuple(_) | ty::Alias(_, _) + | ty::Pat(_, _) | ty::Param(_) | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 61f508a7a0750..653df5b0deb65 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -642,6 +642,7 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { | ty::Float(..) | ty::Str | ty::FnDef(..) + | ty::Pat(..) | ty::FnPtr(_) | ty::Array(..) | ty::Slice(..) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index f6d0b9713f0d0..ca50e8d1a44e3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1927,6 +1927,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Foreign(..) => Some(17), ty::GeneratorWitness(..) => Some(18), ty::GeneratorWitnessMIR(..) => Some(19), + ty::Pat(..) => Some(20), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 53cae3e720c5a..480cb6bc6e519 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1596,6 +1596,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Foreign(_) | ty::Str | ty::Array(..) + | ty::Pat(..) | ty::Slice(_) | ty::RawPtr(..) | ty::Ref(..) @@ -1646,7 +1647,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Float(_) | ty::Str | ty::Array(..) - | ty::Slice(_) + | ty::Pat(..) + | ty::Slice(_) | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 455b53bfb7d8f..66a1ba1711d22 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -38,8 +38,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Foreign(..) | ty::Error(_) => true, - // [T; N] and [T] have same properties as T. - ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty), + // `T is PAT` [T; N] and [T] have same properties as T. + ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty), // (T1..Tn) and closures have same properties as T1..Tn -- // check if *all* of them are trivial. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 7b7abcf552ab7..4215b30556cbd 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -761,6 +761,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Foreign(_) | ty::Array(..) + | ty::Pat(..) | ty::Slice(_) | ty::Closure(..) | ty::Generator(..) @@ -822,6 +823,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(_) | ty::Ref(_, _, _) | ty::FnDef(_, _) + | ty::Pat(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ad7d479896fd0..be5cd125a1bce 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2082,6 +2082,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])), ), + ty::Pat(ty, _) => Where(obligation.predicate.rebind(vec![*ty])), + ty::Adt(def, substs) => { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here @@ -2146,6 +2148,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Where(obligation.predicate.rebind(tys.iter().collect())) } + ty::Pat(ty, _) => { + // (*) binder moved here + Where(obligation.predicate.rebind(vec![ty])) + } + ty::Generator(_, substs, hir::Movability::Movable) => { if self.tcx().features().generator_clone { let resolved_upvars = @@ -2267,7 +2274,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { t.rebind(vec![element_ty]) } - ty::Array(element_ty, _) | ty::Slice(element_ty) => t.rebind(vec![element_ty]), + ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => t.rebind(vec![ty]), ty::Tuple(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 69b965f3a389a..65f5440a8c4b1 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -161,7 +161,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { } } - ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => { + ty::Pat(..) | ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => { // First check all contained types and then tell the caller to continue searching. return ty.super_visit_with(self); } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7c5e147a950f1..6fd77dc8f7ec1 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -566,11 +566,7 @@ impl<'tcx> WfPredicates<'tcx> { // Can only infer to `ty::Float(_)`. ty::Infer(ty::FloatVar(_)) => {} - ty::Slice(subty) => { - self.require_sized(subty, traits::SliceOrArrayElem); - } - - ty::Array(subty, _) => { + ty::Pat(subty, _) | ty::Slice(subty) | ty::Array(subty, _) => { self.require_sized(subty, traits::SliceOrArrayElem); // Note that we handle the len is implicitly checked while walking `arg`. } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 9c5db3314c5cd..804cfc227721e 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -344,6 +344,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ), ty::GeneratorWitness(_) => unimplemented!(), ty::GeneratorWitnessMIR(..) => unimplemented!(), + ty::Pat(..) => unimplemented!(), ty::Never => chalk_ir::TyKind::Never, ty::Tuple(types) => { chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner)) diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 8b7f8033bface..e7984465ec1d8 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -169,7 +169,7 @@ fn dtorck_constraint_for_ty<'tcx>( // these types never have a destructor } - ty::Array(ety, _) | ty::Slice(ety) => { + ty::Pat(ety, _) | ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element rustc_data_structures::stack::ensure_sufficient_stack(|| { dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, *ety, constraints) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 93c9c675c9a6b..5b3d474fbfa11 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -112,6 +112,32 @@ fn layout_of_uncached<'tcx>( debug_assert!(!ty.has_non_region_infer()); Ok(match *ty.kind() { + ty::Pat(ty, pat) => { + let layout = cx.layout_of(ty)?.layout; + let mut abi = layout.abi(); + match *pat { + ty::PatternKind::Range { start, end, include_end } => { + if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut abi { + if let Some(start) = start { + scalar.valid_range_mut().start = + start.eval_bits(tcx, param_env, start.ty()); + } + if let Some(end) = end { + let mut end = end.eval_bits(tcx, param_env, end.ty()); + if !include_end { + end = end.wrapping_sub(1); + } + scalar.valid_range_mut().end = end; + } + + tcx.intern_layout(LayoutS { abi, ..LayoutS::clone(&layout.0) }) + } else { + bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}") + } + } + } + } + // Basic scalars. ty::Bool => tcx.intern_layout(LayoutS::scalar( cx, diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 41e837e8b754e..1e19c0808b0da 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -33,6 +33,8 @@ fn sized_constraint_for_ty<'tcx>( Some(&ty) => sized_constraint_for_ty(tcx, adtdef, ty), }, + Pat(ty, _) => sized_constraint_for_ty(tcx, adtdef, *ty), + Adt(adt, substs) => { // recursive case let adt_tys = adt.sized_constraint(tcx); diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index d5de457a82ce9..4f81a6fabce30 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -33,6 +33,8 @@ pub trait Interner { type SubstsRef: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type DefId: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type Ty: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; + /// A pattern type pattern. + type Pat: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type Const: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type Region: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type TypeAndMut: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; @@ -819,20 +821,20 @@ impl UniverseIndex { /// name the region `'a`, but that region was not nameable from /// `U` because it was not in scope there. pub fn next_universe(self) -> UniverseIndex { - UniverseIndex::from_u32(self.private.checked_add(1).unwrap()) + UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap()) } /// Returns `true` if `self` can name a name from `other` -- in other words, /// if the set of names in `self` is a superset of those in /// `other` (`self >= other`). pub fn can_name(self, other: UniverseIndex) -> bool { - self.private >= other.private + self >= other } /// Returns `true` if `self` cannot name some names from `other` -- in other /// words, if the set of names in `self` is a strict subset of /// those in `other` (`self < other`). pub fn cannot_name(self, other: UniverseIndex) -> bool { - self.private < other.private + self < other } } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index e7bb30553736c..0f602f3778ba8 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -227,6 +227,10 @@ pub enum TyKind { /// A placeholder for a type which could not be computed; this is /// propagated to avoid useless error messages. Error(I::ErrorGuaranteed), + + /// A pattern subtype. Takes any type and restricts it to its pattern. + /// Only supports integer range patterns for now. + Pat(I::Ty, I::Pat), } impl TyKind { @@ -268,6 +272,7 @@ const fn tykind_discriminant(value: &TyKind) -> usize { Infer(_) => 24, Error(_) => 25, GeneratorWitnessMIR(_, _) => 26, + Pat(_, _) => 27, } } @@ -281,6 +286,7 @@ impl Clone for TyKind { Uint(u) => Uint(*u), Float(f) => Float(*f), Adt(d, s) => Adt(d.clone(), s.clone()), + Pat(t, c) => Pat(t.clone(), c.clone()), Foreign(d) => Foreign(d.clone()), Str => Str, Array(t, c) => Array(t.clone(), c.clone()), @@ -318,6 +324,7 @@ impl PartialEq for TyKind { (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s, (Foreign(a_d), Foreign(b_d)) => a_d == b_d, (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c, + (Pat(a_t, a_c), Pat(b_t, b_c)) => a_t == b_t && a_c == b_c, (Slice(a_t), Slice(b_t)) => a_t == b_t, (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t, (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m, @@ -377,6 +384,7 @@ impl Ord for TyKind { (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)), (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d), (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)), + (Pat(a_t, a_c), Pat(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)), (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t), (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t), (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => { @@ -465,6 +473,10 @@ impl hash::Hash for TyKind { s.hash(state); } Tuple(t) => t.hash(state), + Pat(t, p) => { + t.hash(state); + p.hash(state); + } Alias(i, p) => { i.hash(state); p.hash(state); @@ -492,6 +504,7 @@ impl fmt::Debug for TyKind { Uint(u) => f.debug_tuple_field1_finish("Uint", u), Float(float) => f.debug_tuple_field1_finish("Float", float), Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s), + Pat(f0, f1) => f.debug_tuple_field2_finish("Pat", f0, f1), Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), Str => f.write_str("Str"), Array(t, c) => f.debug_tuple_field2_finish("Array", t, c), @@ -525,6 +538,7 @@ where I::SubstsRef: Encodable, I::DefId: Encodable, I::Ty: Encodable, + I::Pat: Encodable, I::Const: Encodable, I::Region: Encodable, I::TypeAndMut: Encodable, @@ -560,6 +574,10 @@ where adt.encode(e); substs.encode(e); }), + Pat(ty, pat) => e.emit_enum_variant(disc, |e| { + ty.encode(e); + pat.encode(e); + }), Foreign(def_id) => e.emit_enum_variant(disc, |e| { def_id.encode(e); }), @@ -660,6 +678,7 @@ where I::InferTy: Decodable, I::PredicateKind: Decodable, I::AllocId: Decodable, + I::Pat: Decodable, { fn decode(d: &mut D) -> Self { match Decoder::read_usize(d) { @@ -690,6 +709,7 @@ where 24 => Infer(Decodable::decode(d)), 25 => Error(Decodable::decode(d)), 26 => GeneratorWitnessMIR(Decodable::decode(d), Decodable::decode(d)), + 27 => Pat(Decodable::decode(d), Decodable::decode(d)), _ => panic!( "{}", format!( @@ -709,6 +729,7 @@ where I::DefId: HashStable, I::SubstsRef: HashStable, I::Ty: HashStable, + I::Pat: HashStable, I::Const: HashStable, I::TypeAndMut: HashStable, I::PolyFnSig: HashStable, @@ -748,6 +769,10 @@ where adt.hash_stable(__hcx, __hasher); substs.hash_stable(__hcx, __hasher); } + Pat(ty, pat) => { + ty.hash_stable(__hcx, __hasher); + pat.hash_stable(__hcx, __hasher); + } Foreign(def_id) => { def_id.hash_stable(__hcx, __hasher); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e2ced191a00c0..7993fa2db0120 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1609,6 +1609,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) } } TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), + TyKind::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()), TyKind::Array(ty, ref length) => { let length = match length { hir::ArrayLen::Infer(_, _) => "_".to_string(), @@ -1698,6 +1699,10 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Float(float_ty) => Primitive(float_ty.into()), ty::Str => Primitive(PrimitiveType::Str), ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))), + ty::Pat(ty, pat) => Type::Pat( + Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), + format!("{pat:?}").into_boxed_str(), + ), ty::Array(ty, mut n) => { n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 85dd3881593ac..dfbd16086833f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1602,7 +1602,9 @@ pub(crate) enum Type { /// /// This is mostly Rustdoc's version of [`hir::Path`]. /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics. - Path { path: Path }, + Path { + path: Path, + }, /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static` DynTrait(Vec, Option), /// A type parameter. @@ -1619,10 +1621,15 @@ pub(crate) enum Type { /// /// The `String` field is a stringified version of the array's length parameter. Array(Box, Box), + Pat(Box, Box), /// A raw pointer type: `*const i32`, `*mut i32` RawPointer(Mutability, Box), /// A reference type: `&i32`, `&'a mut Foo` - BorrowedRef { lifetime: Option, mutability: Mutability, type_: Box }, + BorrowedRef { + lifetime: Option, + mutability: Mutability, + type_: Box, + }, /// A qualified path to an associated item: `::Name` QPath(Box), @@ -1747,6 +1754,7 @@ impl Type { BareFunction(..) => PrimitiveType::Fn, Slice(..) => PrimitiveType::Slice, Array(..) => PrimitiveType::Array, + Type::Pat(..) => PrimitiveType::Pat, RawPointer(..) => PrimitiveType::RawPointer, QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache), Generic(_) | Infer | ImplTrait(_) => return None, @@ -1798,6 +1806,7 @@ pub(crate) enum PrimitiveType { Str, Slice, Array, + Pat, Tuple, Unit, RawPointer, @@ -1945,6 +1954,7 @@ impl PrimitiveType { Bool => sym::bool, Char => sym::char, Array => sym::array, + Pat => sym::pat, Slice => sym::slice, Tuple => sym::tuple, Unit => sym::unit, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 33404a7683597..a67782525d4e7 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1012,6 +1012,10 @@ fn fmt_type<'cx>( write!(f, "]") } }, + clean::Type::Pat(ref t, ref pat) => { + fmt::Display::fmt(&t.print(cx), f)?; + write!(f, " is {pat}") + } clean::Array(ref t, ref n) => match **t { clean::Generic(name) if !f.alternate() => primitive_link( f, diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 5b0caac099bc3..f7521145478c8 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -368,6 +368,7 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option { | clean::ImplTrait(_) | clean::Tuple(_) | clean::Slice(_) + | clean::Type::Pat(..) | clean::Array(_, _) | clean::QPath { .. } | clean::Infer => None, diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bd95ec18650b3..484ab78f5bb0d 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -500,6 +500,9 @@ impl FromWithTcx for Type { Tuple(t) => Type::Tuple(t.into_tcx(tcx)), Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() }, + clean::Type::Pat(t, p) => { + Type::Pat { type_: Box::new((*t).into_tcx(tcx)), pat: p.to_string() } + } ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8435972bb11f2..b33b594492992 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -528,6 +528,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::Str => Res::Primitive(Str), ty::Tuple(tys) if tys.is_empty() => Res::Primitive(Unit), ty::Tuple(_) => Res::Primitive(Tuple), + ty::Pat(..) => Res::Primitive(Pat), ty::Array(..) => Res::Primitive(Array), ty::Slice(_) => Res::Primitive(Slice), ty::RawPtr(_) => Res::Primitive(RawPointer), diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 387d5787dfcb2..e08eea595959b 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 24; +pub const FORMAT_VERSION: u32 = 25; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -565,6 +565,12 @@ pub enum Type { type_: Box, len: String, }, + /// `u32 is 1..` + Pat { + #[serde(rename = "type")] + type_: Box, + pat: String, + }, /// `impl TraitA + TraitB + ...` ImplTrait(Vec), /// `_` diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs index dec357ab75c36..d9c6e4fe16225 100644 --- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs +++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs @@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { } /// Returns true if the given item is a union with at least two non-ZST fields. -fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool { +fn is_union_with_two_non_zst_fields<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { if let ItemKind::Union(data, _) = &item.kind { data.fields().iter().filter(|f| !is_zst(cx, f.ty)).count() >= 2 } else { @@ -77,7 +77,7 @@ fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bo } } -fn is_zst(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) -> bool { +fn is_zst<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> bool { if hir_ty.span.from_expansion() { return false; } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 6c333afacc648..037ac64c2cd1c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1010,7 +1010,7 @@ fn binding_ty_auto_deref_stability<'tcx>( } }, TyKind::Slice(_) => Position::DerefStable(precedence, false), - TyKind::Array(..) | TyKind::Ptr(_) | TyKind::BareFn(_) => Position::DerefStable(precedence, true), + TyKind::Pat(..) | TyKind::Array(..) | TyKind::Ptr(_) | TyKind::BareFn(_) => Position::DerefStable(precedence, true), TyKind::Never | TyKind::Tup(_) | TyKind::Path(_) => Position::DerefStable( @@ -1410,6 +1410,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc | ty::Int(_) | ty::Uint(_) | ty::Array(..) + | ty::Pat(..) | ty::Float(_) | ty::RawPtr(..) | ty::FnPtr(_) => Position::DerefStable(precedence, true).into(), diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 64a4a3fa741bc..a0fb546141a53 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -213,7 +213,7 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a `BuildHasher`. - fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option { + fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Option { if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind { let params: Vec<_> = path .segments diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index 87bd007a26a24..d52a7ac0dee93 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { /// Returns true if any of the method parameters is a type that implements `Drop`. The method /// can't be made const then, because `drop` can't be const-evaluated. -fn method_accepts_droppable(cx: &LateContext<'_>, param_tys: &[hir::Ty<'_>]) -> bool { +fn method_accepts_droppable<'tcx>(cx: &LateContext<'tcx>, param_tys: &[hir::Ty<'tcx>]) -> bool { // If any of the params are droppable, return true param_tys.iter().any(|hir_ty| { let ty_ty = hir_ty_to_ty(cx.tcx, hir_ty); diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 585e2075fa904..f563441746360 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -314,9 +314,9 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn( &mut self, - cx: &LateContext<'_>, + cx: &LateContext<'tcx>, _: FnKind<'_>, - decl: &FnDecl<'_>, + decl: &FnDecl<'tcx>, _: &Body<'_>, _: Span, def_id: LocalDefId, @@ -345,7 +345,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); match item.kind { @@ -362,7 +362,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) { match item.kind { ImplItemKind::Const(ty, _) => { let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx @@ -391,7 +391,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { + fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) { let is_exported = cx .effective_visibilities .is_exported(field.def_id); @@ -406,7 +406,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); let context = CheckTyContext { @@ -423,7 +423,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) { if let Some(ty) = local.ty { self.check_ty( cx, @@ -446,7 +446,7 @@ impl Types { } } - fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) { + fn check_fn_decl<'tcx>(&mut self, cx: &LateContext<'tcx>, decl: &FnDecl<'tcx>, context: CheckTyContext) { // Ignore functions in trait implementations as they are usually forced by the trait definition. // // FIXME: ideally we would like to warn *if the complicated type can be simplified*, but it's hard @@ -468,7 +468,7 @@ impl Types { /// lint found. /// /// The parameter `is_local` distinguishes the context of the type. - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, mut context: CheckTyContext) { if hir_ty.span.from_expansion() { return; } diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index f9b9a66b5fa46..0d2869206a829 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -10,7 +10,7 @@ use rustc_span::symbol::sym; use super::{utils, REDUNDANT_ALLOCATION}; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool { let mut applicability = Applicability::MaybeIncorrect; let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() { "Box" diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 7a3c7cd8a99fc..e71f0d310b7ba 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -12,10 +12,10 @@ use rustc_span::symbol::sym; use super::VEC_BOX; -pub(super) fn check( - cx: &LateContext<'_>, +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, def_id: DefId, box_size_threshold: u64, ) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 3cd35838961f6..fb4700fd6d436 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -196,7 +196,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if_chain! { if !hir_ty.span.from_expansion(); if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS); diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index 6cf2a955fd5c6..77fa25532f088 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -45,7 +45,7 @@ declare_clippy_lint! { declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]); impl LateLintPass<'_> for ZeroSizedMapValues { - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if_chain! { if !hir_ty.span.from_expansion(); if !in_trait_impl(cx, hir_ty.hir_id); @@ -78,7 +78,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { false } -fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { +fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { cx.maybe_typeck_results() .and_then(|results| { if results.hir_owner == hir_ty.hir_id.owner { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 2bbe1a19b625a..b54cd2ffca7f3 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -946,6 +946,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(ty); self.hash_array_length(len); }, + TyKind::Pat(ty, pat) => { + self.hash_ty(ty); + self.hash_pat(pat); + }, TyKind::Ptr(ref mut_ty) => { self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 01e2fb6e61e15..7ce8e06fdbd1c 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -847,6 +847,11 @@ impl Rewrite for ast::Ty { self.span, shape, ), + ast::TyKind::Pat(ref ty, ref pat) => { + let ty = ty.rewrite(context, shape)?; + let pat = pat.rewrite(context, shape)?; + Some(format!("{ty} is {pat}")) + }, } } } diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index af92e6eb86376..f0c7dfe50c468 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -14,7 +14,7 @@ use std::collections::hash_map::{Entry, HashMap}; use std::fmt; use std::fs; use std::num::NonZeroU32; -use std::path::Path; +use std::path::{Path, PathBuf}; use regex::Regex; @@ -51,6 +51,8 @@ pub struct Feature { pub since: Option, pub has_gate_test: bool, pub tracking_issue: Option, + pub file: PathBuf, + pub line: usize, } impl Feature { fn tracking_issue_display(&self) -> impl fmt::Display { @@ -72,7 +74,7 @@ pub struct CollectedFeatures { pub fn collect_lib_features(base_src_path: &Path) -> Features { let mut lib_features = Features::new(); - map_lib_features(base_src_path, &mut |res, _, _| { + map_lib_features(base_src_path, &mut |res| { if let Ok((name, feature)) = res { lib_features.insert(name.to_owned(), feature); } @@ -185,23 +187,25 @@ pub fn check( .chain(lib_features.iter().map(|feat| (feat, "lib"))); for ((feature_name, feature), kind) in all_features_iter { let since = if let Some(since) = feature.since { since } else { continue }; + let file = feature.file.display(); + let line = feature.line; if since > version && since != Version::CurrentPlaceholder { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" ); } if channel == "nightly" && since == version { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", version::VERSION_PLACEHOLDER ); } if channel != "nightly" && since == Version::CurrentPlaceholder { tidy_error!( bad, - "The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", + "{file}:{line}: The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", ); } } @@ -435,7 +439,14 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba ); } Entry::Vacant(e) => { - e.insert(Feature { level, since, has_gate_test: false, tracking_issue }); + e.insert(Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: path.to_path_buf(), + line: line_number, + }); } } } @@ -447,7 +458,7 @@ fn get_and_check_lib_features( lang_features: &Features, ) -> Features { let mut lib_features = Features::new(); - map_lib_features(base_src_path, &mut |res, file, line| match res { + map_lib_features(base_src_path, &mut |res| match res { Ok((name, f)) => { let mut check_features = |f: &Feature, list: &Features, display: &str| { if let Some(ref s) = list.get(name) { @@ -455,8 +466,8 @@ fn get_and_check_lib_features( tidy_error!( bad, "{}:{}: `issue` \"{}\" mismatches the {} `issue` of \"{}\"", - file.display(), - line, + f.file.display(), + f.line, f.tracking_issue_display(), display, s.tracking_issue_display(), @@ -468,7 +479,7 @@ fn get_and_check_lib_features( check_features(&f, &lib_features, "previous"); lib_features.insert(name.to_owned(), f); } - Err(msg) => { + Err((msg, file, line)) => { tidy_error!(bad, "{}:{}: {}", file.display(), line, msg); } }); @@ -477,7 +488,7 @@ fn get_and_check_lib_features( fn map_lib_features( base_src_path: &Path, - mf: &mut dyn FnMut(Result<(&str, Feature), &str>, &Path, usize), + mf: &mut dyn FnMut(Result<(&str, Feature), (&str, &Path, usize)>), ) { walk( base_src_path, @@ -514,7 +525,7 @@ fn map_lib_features( while let Some((i, line)) = iter_lines.next() { macro_rules! err { ($msg:expr) => {{ - mf(Err($msg), file, i + 1); + mf(Err(($msg, file, i + 1))); continue; }}; } @@ -532,7 +543,10 @@ fn map_lib_features( f.tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none); } if line.ends_with(']') { - mf(Ok((name, f.clone())), file, i + 1); + let mut f = f.clone(); + f.file = file.to_path_buf(); + f.line = i + 1; + mf(Ok((name, f))); } else if !line.ends_with(',') && !line.ends_with('\\') && !line.ends_with('"') { // We need to bail here because we might have missed the @@ -561,8 +575,10 @@ fn map_lib_features( since: None, has_gate_test: false, tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), + file: file.to_path_buf(), + line: i + 1, }; - mf(Ok((feature_name, feature)), file, i + 1); + mf(Ok((feature_name, feature))); continue; } let level = if line.contains("[unstable(") { @@ -590,9 +606,16 @@ fn map_lib_features( }; let tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none); - let feature = Feature { level, since, has_gate_test: false, tracking_issue }; + let feature = Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: file.to_path_buf(), + line: i + 1, + }; if line.contains(']') { - mf(Ok((feature_name, feature)), file, i + 1); + mf(Ok((feature_name, feature))); } else { becoming_feature = Some((feature_name, feature)); } diff --git a/tests/ui/const-generics/bad-const-generic-exprs.stderr b/tests/ui/const-generics/bad-const-generic-exprs.stderr index 17a63a96fe4fe..7f2386594c874 100644 --- a/tests/ui/const-generics/bad-const-generic-exprs.stderr +++ b/tests/ui/const-generics/bad-const-generic-exprs.stderr @@ -142,11 +142,11 @@ help: expressions must be enclosed in braces to be used as const generic argumen LL | let _: Wow<{ (1 + 2) * 3 }>; | + + -error: expected one of `,` or `>`, found `0` +error: expected one of `,`, `>`, or `is`, found `0` --> $DIR/bad-const-generic-exprs.rs:43:17 | LL | let _: Wow; - | - ^ expected one of `,` or `>` + | - ^ expected one of `,`, `>`, or `is` | | | while parsing the type for `_` | diff --git a/tests/ui/fn/fn-recover-return-sign2.rs b/tests/ui/fn/fn-recover-return-sign2.rs index 31f56565c49a6..eb87849ea49dc 100644 --- a/tests/ui/fn/fn-recover-return-sign2.rs +++ b/tests/ui/fn/fn-recover-return-sign2.rs @@ -3,6 +3,6 @@ fn foo() => impl Fn() => bool { //~^ ERROR return types are denoted using `->` - //~| ERROR expected one of `+`, `->`, `::`, `where`, or `{`, found `=>` + //~| ERROR expected one of `+`, `->`, `::`, `is`, `where`, or `{`, found `=>` unimplemented!() } diff --git a/tests/ui/fn/fn-recover-return-sign2.stderr b/tests/ui/fn/fn-recover-return-sign2.stderr index 25ee8dd0c5dcd..9a67a84cddd11 100644 --- a/tests/ui/fn/fn-recover-return-sign2.stderr +++ b/tests/ui/fn/fn-recover-return-sign2.stderr @@ -4,11 +4,11 @@ error: return types are denoted using `->` LL | fn foo() => impl Fn() => bool { | ^^ help: use `->` instead -error: expected one of `+`, `->`, `::`, `where`, or `{`, found `=>` +error: expected one of `+`, `->`, `::`, `is`, `where`, or `{`, found `=>` --> $DIR/fn-recover-return-sign2.rs:4:23 | LL | fn foo() => impl Fn() => bool { - | ^^ expected one of `+`, `->`, `::`, `where`, or `{` + | ^^ expected one of `+`, `->`, `::`, `is`, `where`, or `{` error: aborting due to 2 previous errors diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs b/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs index cbb05189201da..990ba7e716822 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs @@ -3,6 +3,6 @@ trait X { } fn f1<'a>(arg : Box>) {} - //~^ ERROR: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` + //~^ ERROR: expected one of `!`, `(`, `+`, `,`, `::`, `<`, `>`, or `is`, found `=` fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr index 53d5f9de65754..82d6554ebdc46 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, `>`, or `is`, found `=` --> $DIR/trait-path-expected-token.rs:5:33 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of 7 possible tokens + | - ^ expected one of 8 possible tokens | | | maybe try to close unmatched angle bracket diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs index ecabf8943ea3c..c99ff4bcb7a72 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs @@ -6,7 +6,7 @@ const _: () = { fn f1<'a>(arg : Box>) {} //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `:` //~| ERROR: expected parameter name, found `>` - //~| ERROR: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` + //~| ERROR: expected one of `!`, `)`, `+`, `,`, `::`, or `is`, found `>` //~| ERROR: constant provided when a type was expected }; diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr index 10ceccedcac1b..0d3513c4f1346 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -15,13 +15,13 @@ error: expected parameter name, found `>` LL | fn f1<'a>(arg : Box>) {} | ^ expected parameter name -error: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` +error: expected one of `!`, `)`, `+`, `,`, `::`, or `is`, found `>` --> $DIR/trait-path-missing-gen_arg.rs:6:36 | LL | fn f1<'a>(arg : Box>) {} | ^ | | - | expected one of `!`, `)`, `+`, `,`, or `::` + | expected one of `!`, `)`, `+`, `,`, `::`, or `is` | help: missing `,` error: expected one of `>`, a const expression, lifetime, or type, found `=` diff --git a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr index 8bc737d675204..6e8f717ada34d 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `>`, or `is`, found `=` --> $DIR/trait-path-segments.rs:6:36 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of 8 possible tokens + | - ^ expected one of 9 possible tokens | | | maybe try to close unmatched angle bracket | @@ -11,11 +11,11 @@ help: you might have meant to end the type parameters here LL | fn f1<'a>(arg : Box = u32>>) {} | + -error: expected one of `,`, `::`, `:`, or `>`, found `=` +error: expected one of `,`, `::`, `:`, `>`, or `is`, found `=` --> $DIR/trait-path-segments.rs:17:35 | LL | impl::Y<'a> = &'a u32>> Z for T {} - | - ^ expected one of `,`, `::`, `:`, or `>` + | - ^ expected one of `,`, `::`, `:`, `>`, or `is` | | | maybe try to close unmatched angle bracket | @@ -24,11 +24,11 @@ help: you might have meant to end the type parameters here LL | impl::Y<'a>> = &'a u32>> Z for T {} | + -error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` +error: expected one of `!`, `+`, `,`, `::`, `:`, `>`, or `is`, found `=` --> $DIR/trait-path-segments.rs:28:25 | LL | impl = &'a u32>> Z for T {} - | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` + | - ^ expected one of 7 possible tokens | | | maybe try to close unmatched angle bracket | diff --git a/tests/ui/generic-associated-types/parse/trait-path-types.stderr b/tests/ui/generic-associated-types/parse/trait-path-types.stderr index 8f7a73c95b65f..455d6566c7190 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-types.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-types.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `:`, or `>`, found `=` +error: expected one of `,`, `:`, `>`, or `is`, found `=` --> $DIR/trait-path-types.rs:6:37 | LL | fn f<'a>(arg : Box>) {} - | - ^ expected one of `,`, `:`, or `>` + | - ^ expected one of `,`, `:`, `>`, or `is` | | | maybe try to close unmatched angle bracket | @@ -11,11 +11,11 @@ help: you might have meant to end the type parameters here LL | fn f<'a>(arg : Box = u32>>) {} | + -error: expected one of `,`, `:`, or `>`, found `=` +error: expected one of `,`, `:`, `>`, or `is`, found `=` --> $DIR/trait-path-types.rs:11:37 | LL | fn f1<'a>(arg : Box) = &'a ()>>) {} - | - ^ expected one of `,`, `:`, or `>` + | - ^ expected one of `,`, `:`, `>`, or `is` | | | maybe try to close unmatched angle bracket | diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr index 9d2c315e4dbca..1a081f5210fd0 100644 --- a/tests/ui/issues/issue-34334.stderr +++ b/tests/ui/issues/issue-34334.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `:`, or `>`, found `=` +error: expected one of `,`, `:`, `>`, or `is`, found `=` --> $DIR/issue-34334.rs:2:29 | LL | let sr: Vec<(u32, _, _) = vec![]; - | -- - ^ expected one of `,`, `:`, or `>` + | -- - ^ expected one of `,`, `:`, `>`, or `is` | | | | | maybe try to close unmatched angle bracket | while parsing the type for `sr` diff --git a/tests/ui/issues/issue-66706.rs b/tests/ui/issues/issue-66706.rs index 835fdfae86c03..eaa1f1de6df9b 100644 --- a/tests/ui/issues/issue-66706.rs +++ b/tests/ui/issues/issue-66706.rs @@ -1,6 +1,6 @@ fn a() { [0; [|_: _ &_| ()].len()] - //~^ ERROR expected `,`, found `&` + //~^ ERROR expected one of `,` or `is`, found `&` //~| ERROR type annotations needed } @@ -11,7 +11,7 @@ fn b() { fn c() { [0; [|&_: _ &_| {}; 0 ].len()] - //~^ ERROR expected `,`, found `&` + //~^ ERROR expected one of `,` or `is`, found `&` } fn d() { diff --git a/tests/ui/issues/issue-66706.stderr b/tests/ui/issues/issue-66706.stderr index 8a30c0cad39c5..ece40c70488e5 100644 --- a/tests/ui/issues/issue-66706.stderr +++ b/tests/ui/issues/issue-66706.stderr @@ -1,8 +1,8 @@ -error: expected `,`, found `&` +error: expected one of `,` or `is`, found `&` --> $DIR/issue-66706.rs:2:16 | LL | [0; [|_: _ &_| ()].len()] - | -^ expected `,` + | -^ expected one of `,` or `is` | | | help: missing `,` @@ -12,11 +12,11 @@ error: expected identifier, found reserved identifier `_` LL | [0; [|f @ &ref _| {} ; 0 ].len() ]; | ^ expected identifier, found reserved identifier -error: expected `,`, found `&` +error: expected one of `,` or `is`, found `&` --> $DIR/issue-66706.rs:13:17 | LL | [0; [|&_: _ &_| {}; 0 ].len()] - | -^ expected `,` + | -^ expected one of `,` or `is` | | | help: missing `,` diff --git a/tests/ui/parser/better-expected.rs b/tests/ui/parser/better-expected.rs index 16b61caa4dffc..c242cd5cbb03c 100644 --- a/tests/ui/parser/better-expected.rs +++ b/tests/ui/parser/better-expected.rs @@ -1,3 +1,3 @@ fn main() { - let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` + let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, `]`, or `is`, found `3` } diff --git a/tests/ui/parser/better-expected.stderr b/tests/ui/parser/better-expected.stderr index 21bf8d19a721e..17537f747e80b 100644 --- a/tests/ui/parser/better-expected.stderr +++ b/tests/ui/parser/better-expected.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, `]`, or `is`, found `3` --> $DIR/better-expected.rs:2:19 | LL | let x: [isize 3]; - | - ^ expected one of 7 possible tokens + | - ^ expected one of 8 possible tokens | | | while parsing the type for `x` diff --git a/tests/ui/parser/bounds-type-where.rs b/tests/ui/parser/bounds-type-where.rs index 2520ecb294c9a..bf636421cc158 100644 --- a/tests/ui/parser/bounds-type-where.rs +++ b/tests/ui/parser/bounds-type-where.rs @@ -6,6 +6,6 @@ type A where T: Trait + Trait = u8; // OK type A where = u8; // OK type A where T: Trait + = u8; // OK type A where T, = u8; -//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` +//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, `=`, or `is`, found `,` fn main() {} diff --git a/tests/ui/parser/bounds-type-where.stderr b/tests/ui/parser/bounds-type-where.stderr index 5636ee75c97a8..ab423ddebee28 100644 --- a/tests/ui/parser/bounds-type-where.stderr +++ b/tests/ui/parser/bounds-type-where.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` +error: expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, `=`, or `is`, found `,` --> $DIR/bounds-type-where.rs:8:15 | LL | type A where T, = u8; - | ^ expected one of 8 possible tokens + | ^ expected one of 9 possible tokens error: aborting due to previous error diff --git a/tests/ui/parser/issues/issue-24780.rs b/tests/ui/parser/issues/issue-24780.rs index 017521f570c82..928fffa5037b9 100644 --- a/tests/ui/parser/issues/issue-24780.rs +++ b/tests/ui/parser/issues/issue-24780.rs @@ -2,7 +2,7 @@ // to happen in #24780. For example, following should be an error: // expected one of ..., `>`, ... found `>`. -fn foo() -> Vec> { //~ ERROR expected one of `!`, `+`, `::`, `where`, or `{`, found `>` +fn foo() -> Vec> { //~ ERROR expected one of `!`, `+`, `::`, `is`, `where`, or `{`, found `>` Vec::new() } diff --git a/tests/ui/parser/issues/issue-24780.stderr b/tests/ui/parser/issues/issue-24780.stderr index d9470191b25a4..fa98fed786a07 100644 --- a/tests/ui/parser/issues/issue-24780.stderr +++ b/tests/ui/parser/issues/issue-24780.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `+`, `::`, `where`, or `{`, found `>` +error: expected one of `!`, `+`, `::`, `is`, `where`, or `{`, found `>` --> $DIR/issue-24780.rs:5:23 | LL | fn foo() -> Vec> { - | ^ expected one of `!`, `+`, `::`, `where`, or `{` + | ^ expected one of `!`, `+`, `::`, `is`, `where`, or `{` error: aborting due to previous error diff --git a/tests/ui/parser/issues/issue-62660.rs b/tests/ui/parser/issues/issue-62660.rs index 33c8a9fa328ca..816a83858968e 100644 --- a/tests/ui/parser/issues/issue-62660.rs +++ b/tests/ui/parser/issues/issue-62660.rs @@ -5,7 +5,7 @@ struct Foo; impl Foo { pub fn foo(_: i32, self: Box`, found `)` + //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, `>`, or `is`, found `)` } fn main() {} diff --git a/tests/ui/parser/issues/issue-62660.stderr b/tests/ui/parser/issues/issue-62660.stderr index 14c0bdcb111b8..3626efddded9c 100644 --- a/tests/ui/parser/issues/issue-62660.stderr +++ b/tests/ui/parser/issues/issue-62660.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)` +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, `>`, or `is`, found `)` --> $DIR/issue-62660.rs:7:38 | LL | pub fn foo(_: i32, self: Box $DIR/issue-63116.rs:3:12 | LL | impl W $DIR/issue-63116.rs:3:14 diff --git a/tests/ui/parser/issues/issue-68890.rs b/tests/ui/parser/issues/issue-68890.rs index bab4ed7f800c5..f38d2464d3d52 100644 --- a/tests/ui/parser/issues/issue-68890.rs +++ b/tests/ui/parser/issues/issue-68890.rs @@ -1,4 +1,4 @@ enum e{A((?'a a+?+l))} //~^ ERROR `?` may only modify trait bounds, not lifetime bounds -//~| ERROR expected one of `)`, `+`, or `,` +//~| ERROR expected one of `)`, `+`, `,`, or `is` //~| ERROR expected item, found `)` diff --git a/tests/ui/parser/issues/issue-68890.stderr b/tests/ui/parser/issues/issue-68890.stderr index 2a3bf6b41f02e..978a2955d3582 100644 --- a/tests/ui/parser/issues/issue-68890.stderr +++ b/tests/ui/parser/issues/issue-68890.stderr @@ -4,11 +4,11 @@ error: `?` may only modify trait bounds, not lifetime bounds LL | enum e{A((?'a a+?+l))} | ^ -error: expected one of `)`, `+`, or `,`, found `a` +error: expected one of `)`, `+`, `,`, or `is`, found `a` --> $DIR/issue-68890.rs:1:15 | LL | enum e{A((?'a a+?+l))} - | ^ expected one of `)`, `+`, or `,` + | ^ expected one of `)`, `+`, `,`, or `is` error: expected item, found `)` --> $DIR/issue-68890.rs:1:21 diff --git a/tests/ui/parser/issues/issue-76597.fixed b/tests/ui/parser/issues/issue-76597.fixed index 2d7a30b8361ad..99e56f2f95266 100644 --- a/tests/ui/parser/issues/issue-76597.fixed +++ b/tests/ui/parser/issues/issue-76597.fixed @@ -6,6 +6,6 @@ fn f( x: u8, y: u8, ) {} -//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y` +//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, `<`, or `is`, found `y` fn main() {} diff --git a/tests/ui/parser/issues/issue-76597.rs b/tests/ui/parser/issues/issue-76597.rs index 521b9c64b1c57..756cd8a23692e 100644 --- a/tests/ui/parser/issues/issue-76597.rs +++ b/tests/ui/parser/issues/issue-76597.rs @@ -6,6 +6,6 @@ fn f( x: u8 y: u8, ) {} -//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y` +//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, `<`, or `is`, found `y` fn main() {} diff --git a/tests/ui/parser/issues/issue-76597.stderr b/tests/ui/parser/issues/issue-76597.stderr index 50b23329f0ceb..fdc361236b710 100644 --- a/tests/ui/parser/issues/issue-76597.stderr +++ b/tests/ui/parser/issues/issue-76597.stderr @@ -1,10 +1,10 @@ -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y` +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, `<`, or `is`, found `y` --> $DIR/issue-76597.rs:7:38 | LL | ... x: u8 | - | | - | expected one of 7 possible tokens + | expected one of 8 possible tokens | help: missing `,` LL | ... y: u8, | ^ unexpected token diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index bad241634cbe6..b37e7c37b6479 100644 --- a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `:`, or `>`, found `=` +error: expected one of `,`, `:`, `>`, or `is`, found `=` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:23 | LL | let v : Vec<(u32,_) = vec![]; - | - - ^ expected one of `,`, `:`, or `>` + | - - ^ expected one of `,`, `:`, `>`, or `is` | | | | | maybe try to close unmatched angle bracket | while parsing the type for `v` @@ -12,11 +12,11 @@ help: you might have meant to end the type parameters here LL | let v : Vec<(u32,_)> = vec![]; | + -error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `{` +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, `>`, or `is`, found `{` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:13:32 | LL | let foo : Foo:: String { "hi".to_string() } } diff --git a/tests/ui/parser/multitrait.stderr b/tests/ui/parser/multitrait.stderr index 5a8bb2f7a457c..59def0532da9f 100644 --- a/tests/ui/parser/multitrait.stderr +++ b/tests/ui/parser/multitrait.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` +error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `is`, `where`, or `{`, found `,` --> $DIR/multitrait.rs:5:9 | LL | impl Cmp, ToString for S { - | ^ expected one of 8 possible tokens + | ^ expected one of 9 possible tokens error: aborting due to previous error diff --git a/tests/ui/parser/nested-missing-closing-angle-bracket.stderr b/tests/ui/parser/nested-missing-closing-angle-bracket.stderr index b85bc02568c77..0fb8537d5322c 100644 --- a/tests/ui/parser/nested-missing-closing-angle-bracket.stderr +++ b/tests/ui/parser/nested-missing-closing-angle-bracket.stderr @@ -1,8 +1,8 @@ -error: expected one of `,` or `>`, found `;` +error: expected one of `,`, `>`, or `is`, found `;` --> $DIR/nested-missing-closing-angle-bracket.rs:2:46 | LL | let v : Vec:: = vec![vec![]]; - | - while parsing the type for `v` ^ expected one of `,` or `>` + | - while parsing the type for `v` ^ expected one of `,`, `>`, or `is` error: aborting due to previous error diff --git a/tests/ui/parser/recover-enum2.stderr b/tests/ui/parser/recover-enum2.stderr index 7634bca921c86..14ec65e93d3a3 100644 --- a/tests/ui/parser/recover-enum2.stderr +++ b/tests/ui/parser/recover-enum2.stderr @@ -6,11 +6,11 @@ LL | Var3 { LL | abc: {}, | ^ expected type -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{` +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, `<`, or `is`, found `{` --> $DIR/recover-enum2.rs:25:22 | LL | Nope(i32 {}) - | ^ expected one of 7 possible tokens + | ^ expected one of 8 possible tokens error: aborting due to 2 previous errors diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.rs b/tests/ui/parser/removed-syntax-closure-lifetime.rs index e807a179473c4..1ce5fe1657024 100644 --- a/tests/ui/parser/removed-syntax-closure-lifetime.rs +++ b/tests/ui/parser/removed-syntax-closure-lifetime.rs @@ -1,2 +1,2 @@ type closure = Box; -//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` +//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, `>`, or `is`, found `/` diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.stderr b/tests/ui/parser/removed-syntax-closure-lifetime.stderr index e107c6b78b313..97504831b8587 100644 --- a/tests/ui/parser/removed-syntax-closure-lifetime.stderr +++ b/tests/ui/parser/removed-syntax-closure-lifetime.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, `>`, or `is`, found `/` --> $DIR/removed-syntax-closure-lifetime.rs:1:22 | LL | type closure = Box; - | ^ expected one of 9 possible tokens + | ^ expected one of 10 possible tokens | help: you might have meant to end the type parameters here | diff --git a/tests/ui/parser/removed-syntax-fixed-vec.rs b/tests/ui/parser/removed-syntax-fixed-vec.rs index 560efecb91cfc..ae4168ac81239 100644 --- a/tests/ui/parser/removed-syntax-fixed-vec.rs +++ b/tests/ui/parser/removed-syntax-fixed-vec.rs @@ -1 +1 @@ -type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` +type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, `]`, or `is`, found `*` diff --git a/tests/ui/parser/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax-fixed-vec.stderr index a2b97544f9e55..a593f6596c0c3 100644 --- a/tests/ui/parser/removed-syntax-fixed-vec.stderr +++ b/tests/ui/parser/removed-syntax-fixed-vec.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, `]`, or `is`, found `*` --> $DIR/removed-syntax-fixed-vec.rs:1:17 | LL | type v = [isize * 3]; - | ^ expected one of 7 possible tokens + | ^ expected one of 8 possible tokens error: aborting due to previous error diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.rs b/tests/ui/parser/removed-syntax-ptr-lifetime.rs index cc69af44a13ca..e9f891006b2ed 100644 --- a/tests/ui/parser/removed-syntax-ptr-lifetime.rs +++ b/tests/ui/parser/removed-syntax-ptr-lifetime.rs @@ -1 +1 @@ -type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` +type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, `<`, `is`, or `where`, found `/` diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr b/tests/ui/parser/removed-syntax-ptr-lifetime.stderr index 914de43e62d66..ae5c1da550c6a 100644 --- a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr +++ b/tests/ui/parser/removed-syntax-ptr-lifetime.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` +error: expected one of `!`, `(`, `::`, `;`, `<`, `is`, or `where`, found `/` --> $DIR/removed-syntax-ptr-lifetime.rs:1:22 | LL | type bptr = &lifetime/isize; - | ^ expected one of `!`, `(`, `::`, `;`, `<`, or `where` + | ^ expected one of 7 possible tokens error: aborting due to previous error diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs index c41cda18743c8..1ecfacf97c2ec 100644 --- a/tests/ui/parser/trait-object-delimiters.rs +++ b/tests/ui/parser/trait-object-delimiters.rs @@ -8,7 +8,7 @@ fn foo2(_: &dyn (Drop + AsRef)) {} //~ ERROR incorrect braces around trait fn foo2_no_space(_: &dyn(Drop + AsRef)) {} //~ ERROR incorrect braces around trait bounds fn foo3(_: &dyn {Drop + AsRef}) {} //~ ERROR expected parameter name, found `{` -//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` +//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `is`, `~`, lifetime, or path, found `{` //~| ERROR at least one trait is required for an object type fn foo4(_: &dyn >) {} //~ ERROR expected identifier, found `<` diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr index ccce3a8053e70..954e2e214e76b 100644 --- a/tests/ui/parser/trait-object-delimiters.stderr +++ b/tests/ui/parser/trait-object-delimiters.stderr @@ -34,11 +34,11 @@ error: expected parameter name, found `{` LL | fn foo3(_: &dyn {Drop + AsRef}) {} | ^ expected parameter name -error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` +error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `is`, `~`, lifetime, or path, found `{` --> $DIR/trait-object-delimiters.rs:10:17 | LL | fn foo3(_: &dyn {Drop + AsRef}) {} - | -^ expected one of 10 possible tokens + | -^ expected one of 11 possible tokens | | | help: missing `,` diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr index 27660ae406e29..7ff8898f6e577 100644 --- a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@` +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, `=`, or `is`, found `@` --> $DIR/nested-type-ascription-syntactically-invalid.rs:18:15 | LL | let a: u8 @ b = 0; - | ^ expected one of 7 possible tokens + | ^ expected one of 8 possible tokens error: expected one of `)`, `,`, `@`, or `|`, found `:` --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:15 @@ -10,17 +10,17 @@ error: expected one of `)`, `,`, `@`, or `|`, found `:` LL | let a @ (b: u8); | ^ expected one of `)`, `,`, `@`, or `|` -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `)` +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, `=`, or `is`, found `)` --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:19 | LL | let a @ (b: u8); - | ^ expected one of 7 possible tokens + | ^ expected one of 8 possible tokens -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@` +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, `=`, or `is`, found `@` --> $DIR/nested-type-ascription-syntactically-invalid.rs:31:15 | LL | let a: T1 @ Outer(b: T2); - | ^ expected one of 7 possible tokens + | ^ expected one of 8 possible tokens error: aborting due to 4 previous errors diff --git a/tests/ui/tuple/tuple-struct-fields/test.rs b/tests/ui/tuple/tuple-struct-fields/test.rs index 00677090d78c5..1fe070e446c3b 100644 --- a/tests/ui/tuple/tuple-struct-fields/test.rs +++ b/tests/ui/tuple/tuple-struct-fields/test.rs @@ -2,7 +2,7 @@ mod foo { type T = (); struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T))); struct S2(pub((foo)) ()); - //~^ ERROR expected one of `)` or `,`, found `(` + //~^ ERROR expected one of `)`, `,`, or `is`, found `(` //~| ERROR cannot find type `foo` in this scope } diff --git a/tests/ui/tuple/tuple-struct-fields/test.stderr b/tests/ui/tuple/tuple-struct-fields/test.stderr index bfa0b32fd458a..022892054037c 100644 --- a/tests/ui/tuple/tuple-struct-fields/test.stderr +++ b/tests/ui/tuple/tuple-struct-fields/test.stderr @@ -1,8 +1,8 @@ -error: expected one of `)` or `,`, found `(` +error: expected one of `)`, `,`, or `is`, found `(` --> $DIR/test.rs:4:26 | LL | struct S2(pub((foo)) ()); - | -^ expected one of `)` or `,` + | -^ expected one of `)`, `,`, or `is` | | | help: missing `,` diff --git a/tests/ui/tuple/tuple-struct-fields/test3.rs b/tests/ui/tuple/tuple-struct-fields/test3.rs index 98d19426e7733..a22eb5557451a 100644 --- a/tests/ui/tuple/tuple-struct-fields/test3.rs +++ b/tests/ui/tuple/tuple-struct-fields/test3.rs @@ -3,7 +3,7 @@ macro_rules! define_struct { struct S1(pub($t)); struct S2(pub (in foo) ()); struct S3(pub($t) ()); - //~^ ERROR expected one of `)` or `,`, found `(` + //~^ ERROR expected one of `)`, `,`, or `is`, found `(` } } diff --git a/tests/ui/tuple/tuple-struct-fields/test3.stderr b/tests/ui/tuple/tuple-struct-fields/test3.stderr index 75262ed5780e0..163b769f023e3 100644 --- a/tests/ui/tuple/tuple-struct-fields/test3.stderr +++ b/tests/ui/tuple/tuple-struct-fields/test3.stderr @@ -1,8 +1,8 @@ -error: expected one of `)` or `,`, found `(` +error: expected one of `)`, `,`, or `is`, found `(` --> $DIR/test3.rs:5:27 | LL | struct S3(pub($t) ()); - | -^ expected one of `)` or `,` + | -^ expected one of `)`, `,`, or `is` | | | help: missing `,` ... diff --git a/tests/ui/type/issue-102598.rs b/tests/ui/type/issue-102598.rs index 93808f18b9971..156dda9983821 100644 --- a/tests/ui/type/issue-102598.rs +++ b/tests/ui/type/issue-102598.rs @@ -1,7 +1,7 @@ fn foo<'a>(_: impl 'a Sized) {} //~^ ERROR: expected `+` between lifetime and Sized //~| ERROR: expected one of `:`, `@`, or `|`, found `)` -//~| ERROR: expected one of `)`, `+`, or `,`, found `Sized` +//~| ERROR: expected one of `)`, `+`, `,`, or `is`, found `Sized` //~| ERROR: at least one trait must be specified fn main(){ diff --git a/tests/ui/type/issue-102598.stderr b/tests/ui/type/issue-102598.stderr index a232395cedb1d..f55179ecefc79 100644 --- a/tests/ui/type/issue-102598.stderr +++ b/tests/ui/type/issue-102598.stderr @@ -25,11 +25,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn foo<'a>(_: impl 'a _: Sized) {} | ++ -error: expected one of `)`, `+`, or `,`, found `Sized` +error: expected one of `)`, `+`, `,`, or `is`, found `Sized` --> $DIR/issue-102598.rs:1:23 | LL | fn foo<'a>(_: impl 'a Sized) {} - | -^^^^^ expected one of `)`, `+`, or `,` + | -^^^^^ expected one of `)`, `+`, `,`, or `is` | | | help: missing `,` diff --git a/tests/ui/type/pattern_types/bad_pat.rs b/tests/ui/type/pattern_types/bad_pat.rs new file mode 100644 index 0000000000000..214942dc83317 --- /dev/null +++ b/tests/ui/type/pattern_types/bad_pat.rs @@ -0,0 +1,11 @@ +#![feature(pattern_types)] +#![allow(incomplete_features)] + +type NonNullU32_2 = u32 is 1..=; +//~^ ERROR: inclusive range with no end +type Positive2 = i32 is 0..=; +//~^ ERROR: inclusive range with no end +type Wild = () is _; +//~^ ERROR: wildcard patterns are not permitted for pattern types + +fn main() {} diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr new file mode 100644 index 0000000000000..2a97080171c90 --- /dev/null +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -0,0 +1,25 @@ +error[E0586]: inclusive range with no end + --> $DIR/bad_pat.rs:4:29 + | +LL | type NonNullU32_2 = u32 is 1..=; + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/bad_pat.rs:6:26 + | +LL | type Positive2 = i32 is 0..=; + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: "wildcard patterns are not permitted for pattern types" + --> $DIR/bad_pat.rs:8:19 + | +LL | type Wild = () is _; + | ^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs new file mode 100644 index 0000000000000..0c21389ef3fb0 --- /dev/null +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zno-analysis + +type NonNullU32 = u32 is 1..; +//~^ pattern types are unstable +type Percent = u32 is 0..=100; +//~^ pattern types are unstable +type Negative = i32 is ..=0; +//~^ pattern types are unstable +type Positive = i32 is 0..; +//~^ pattern types are unstable +type Always = Option is Some(_); +//~^ pattern types are unstable diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr new file mode 100644 index 0000000000000..d0648cd0106cc --- /dev/null +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr @@ -0,0 +1,48 @@ +error[E0658]: pattern types are unstable + --> $DIR/feature-gate-pattern_types.rs:3:19 + | +LL | type NonNullU32 = u32 is 1..; + | ^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(pattern_types)]` to the crate attributes to enable + +error[E0658]: pattern types are unstable + --> $DIR/feature-gate-pattern_types.rs:5:16 + | +LL | type Percent = u32 is 0..=100; + | ^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(pattern_types)]` to the crate attributes to enable + +error[E0658]: pattern types are unstable + --> $DIR/feature-gate-pattern_types.rs:7:17 + | +LL | type Negative = i32 is ..=0; + | ^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(pattern_types)]` to the crate attributes to enable + +error[E0658]: pattern types are unstable + --> $DIR/feature-gate-pattern_types.rs:9:17 + | +LL | type Positive = i32 is 0..; + | ^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(pattern_types)]` to the crate attributes to enable + +error[E0658]: pattern types are unstable + --> $DIR/feature-gate-pattern_types.rs:11:15 + | +LL | type Always = Option is Some(_); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(pattern_types)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/type/pattern_types/macros.active.stderr b/tests/ui/type/pattern_types/macros.active.stderr new file mode 100644 index 0000000000000..ef1585f6df4b8 --- /dev/null +++ b/tests/ui/type/pattern_types/macros.active.stderr @@ -0,0 +1,10 @@ +error: `$t:ty` is followed by `is`, which is not allowed for `ty` fragments + --> $DIR/macros.rs:10:12 + | +LL | ($t:ty is $p:pat) => {}; + | ^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: aborting due to previous error + diff --git a/tests/ui/type/pattern_types/macros.gated.stderr b/tests/ui/type/pattern_types/macros.gated.stderr new file mode 100644 index 0000000000000..ef1585f6df4b8 --- /dev/null +++ b/tests/ui/type/pattern_types/macros.gated.stderr @@ -0,0 +1,10 @@ +error: `$t:ty` is followed by `is`, which is not allowed for `ty` fragments + --> $DIR/macros.rs:10:12 + | +LL | ($t:ty is $p:pat) => {}; + | ^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: aborting due to previous error + diff --git a/tests/ui/type/pattern_types/macros.rs b/tests/ui/type/pattern_types/macros.rs new file mode 100644 index 0000000000000..2d90142322d9d --- /dev/null +++ b/tests/ui/type/pattern_types/macros.rs @@ -0,0 +1,15 @@ +// revisions: gated active + +#![cfg_attr(active, feature(pattern_types))] +#![allow(incomplete_features)] + +// Check that pattern types do not affect existing macros. +// They don't, because `is` was never legal after `ty` fragments. + +macro_rules! foo { + ($t:ty is $p:pat) => {}; //~ ERROR `$t:ty` is followed by `is`, which is not allowed for `ty` fragments +} + +fn main() { + foo!(u32 is 1..) +} diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs new file mode 100644 index 0000000000000..f62c4ff19b74b --- /dev/null +++ b/tests/ui/type/pattern_types/range_patterns.rs @@ -0,0 +1,15 @@ +#![feature(pattern_types, rustc_attrs)] +#![allow(incomplete_features)] + +#[rustc_layout(debug)] +type X = std::num::NonZeroU32; //~ ERROR layout_of +#[rustc_layout(debug)] +type Y = u32 is 1..; //~ ERROR layout_of +#[rustc_layout(debug)] +type Z = Option; //~ ERROR layout_of +#[rustc_layout(debug)] +type A = Option; //~ ERROR layout_of + +fn main() { + let x: u32 is 1.. = unsafe { std::mem::transmute(42_u32) }; +} diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr new file mode 100644 index 0000000000000..ac29e4ac0d524 --- /dev/null +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -0,0 +1,282 @@ +error: layout_of(std::num::NonZeroU32) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(8 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 1..=4294967295, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 1..=4294967295, + }, + ), + variants: Single { + index: 0, + }, + } + --> $DIR/range_patterns.rs:5:1 + | +LL | type X = std::num::NonZeroU32; + | ^^^^^^ + +error: layout_of((u32) is 1..=) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 1..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + variants: Single { + index: 0, + }, + } + --> $DIR/range_patterns.rs:7:1 + | +LL | type Y = u32 is 1..; + | ^^^^^^ + +error: layout_of(std::option::Option<(u32) is 1..=>) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(8 bytes), + }, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I32, + false, + ), + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(8 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(8 bytes), + }, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I32, + false, + ), + }, + ), + fields: Arbitrary { + offsets: [ + Size(4 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/range_patterns.rs:9:1 + | +LL | type Z = Option; + | ^^^^^^ + +error: layout_of(std::option::Option) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(8 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: (..=0) | (1..), + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Multiple { + tag: Initialized { + value: Int( + I32, + false, + ), + valid_range: (..=0) | (1..), + }, + tag_encoding: Niche { + untagged_variant: 1, + niche_variants: 0..=0, + niche_start: 0, + }, + tag_field: 0, + variants: [ + Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(8 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(8 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 1..=4294967295, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 1..=4294967295, + }, + ), + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/range_patterns.rs:11:1 + | +LL | type A = Option; + | ^^^^^^ + +error: aborting due to 4 previous errors +