diff --git a/src/librustc_infer/infer/canonical/mod.rs b/src/librustc_infer/infer/canonical/mod.rs index b7890cf9e925a..d2a702bd30006 100644 --- a/src/librustc_infer/infer/canonical/mod.rs +++ b/src/librustc_infer/infer/canonical/mod.rs @@ -154,7 +154,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { self.tcx .mk_const(ty::Const { val: ty::ConstKind::Placeholder(placeholder_mapped), - ty: self.tcx.types.err, // FIXME(const_generics) + ty: self.tcx.err(), // FIXME(const_generics) }) .into() } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 54f80e8f38812..6a48d87cb16ac 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -1746,7 +1746,7 @@ impl<'tcx> TypeTrace<'tcx> { pub fn dummy(tcx: TyCtxt<'tcx>) -> TypeTrace<'tcx> { TypeTrace { cause: ObligationCause::dummy(), - values: Types(ExpectedFound { expected: tcx.types.err, found: tcx.types.err }), + values: Types(ExpectedFound { expected: tcx.err(), found: tcx.err() }), } } } diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index bd9d108cfe871..9899137c63912 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -188,15 +188,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { match t.kind { ty::Infer(ty::TyVar(vid)) => { self.err = Some(FixupError::UnresolvedTy(vid)); - self.tcx().types.err + self.tcx().err() } ty::Infer(ty::IntVar(vid)) => { self.err = Some(FixupError::UnresolvedIntTy(vid)); - self.tcx().types.err + self.tcx().err() } ty::Infer(ty::FloatVar(vid)) => { self.err = Some(FixupError::UnresolvedFloatTy(vid)); - self.tcx().types.err + self.tcx().err() } ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); @@ -227,7 +227,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { self.err = Some(FixupError::UnresolvedConst(vid)); - return self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: c.ty }); + return self.tcx().err_const(c.ty); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index 080af37492d89..8a390c08c54ab 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -119,7 +119,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { (&ty::Error, _) | (_, &ty::Error) => { infcx.set_tainted_by_errors(); - Ok(self.tcx().types.err) + Ok(self.tcx().err()) } _ => { diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs index 9b38b43c93ae2..5fa565b482bdc 100644 --- a/src/librustc_middle/lib.rs +++ b/src/librustc_middle/lib.rs @@ -52,6 +52,7 @@ #![feature(rustc_attrs)] #![feature(hash_raw_entry)] #![feature(int_error_matching)] +#![feature(track_caller)] #![recursion_limit = "512"] #[macro_use] diff --git a/src/librustc_middle/ty/_match.rs b/src/librustc_middle/ty/_match.rs index 02abe868f3943..6749e5a80672a 100644 --- a/src/librustc_middle/ty/_match.rs +++ b/src/librustc_middle/ty/_match.rs @@ -79,7 +79,7 @@ impl TypeRelation<'tcx> for Match<'tcx> { Err(TypeError::Sorts(relate::expected_found(self, &a, &b))) } - (&ty::Error, _) | (_, &ty::Error) => Ok(self.tcx().types.err), + (&ty::Error, _) | (_, &ty::Error) => Ok(self.tcx().err()), _ => relate::super_relate_tys(self, a, b), } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index e43eb01ad96f7..f4546f5db9612 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -59,7 +59,7 @@ use rustc_session::lint::{Level, Lint}; use rustc_session::Session; use rustc_span::source_map::MultiSpan; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; @@ -152,7 +152,6 @@ pub struct CommonTypes<'tcx> { pub f64: Ty<'tcx>, pub never: Ty<'tcx>, pub self_param: Ty<'tcx>, - pub err: Ty<'tcx>, /// Dummy type used for the `Self` of a `TraitRef` created for converting /// a trait object, and which gets removed in `ExistentialTraitRef`. @@ -811,7 +810,6 @@ impl<'tcx> CommonTypes<'tcx> { bool: mk(Bool), char: mk(Char), never: mk(Never), - err: mk(Error), isize: mk(Int(ast::IntTy::Isize)), i8: mk(Int(ast::IntTy::I8)), i16: mk(Int(ast::IntTy::I16)), @@ -1180,6 +1178,32 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. + #[track_caller] + pub fn err(self) -> Ty<'tcx> { + self.sess.delay_span_bug( + DUMMY_SP, + &format!( + "TyKind::Error constructed but no error reported. {}", + std::panic::Location::caller() + ), + ); + self.mk_ty(Error) + } + + /// Like `err` but for constants. + #[track_caller] + pub fn err_const(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { + self.sess.delay_span_bug( + DUMMY_SP, + &format!( + "ty::ConstKind::Error constructed but no error reported. {}", + std::panic::Location::caller() + ), + ); + self.mk_const(ty::Const { val: ty::ConstKind::Error, ty }) + } + pub fn consider_optimizing String>(&self, msg: T) -> bool { let cname = self.crate_name(LOCAL_CRATE).as_str(); self.sess.consider_optimizing(&cname, msg) diff --git a/src/librustc_middle/ty/query/values.rs b/src/librustc_middle/ty/query/values.rs index b01d15c29b2db..155d3f9ae6ea9 100644 --- a/src/librustc_middle/ty/query/values.rs +++ b/src/librustc_middle/ty/query/values.rs @@ -15,7 +15,7 @@ impl<'tcx, T> Value<'tcx> for T { impl<'tcx> Value<'tcx> for Ty<'tcx> { fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.types.err + tcx.err() } } @@ -27,6 +27,6 @@ impl<'tcx> Value<'tcx> for ty::SymbolName { impl<'tcx> Value<'tcx> for AdtSizedConstraint<'tcx> { fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self { - AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err])) + AdtSizedConstraint(tcx.intern_type_list(&[tcx.err()])) } } diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index faa74f81e818b..48f8634bf3f5e 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -354,7 +354,7 @@ pub fn super_relate_tys>( bug!("bound types encountered in super_relate_tys") } - (&ty::Error, _) | (_, &ty::Error) => Ok(tcx.types.err), + (&ty::Error, _) | (_, &ty::Error) => Ok(tcx.err()), (&ty::Never, _) | (&ty::Char, _) diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index ac5477edcc3c0..b274f07dd4e5f 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -2378,9 +2378,7 @@ impl<'tcx> Const<'tcx> { // can leak through `val` into the const we return. Ok(val) => Const::from_value(tcx, val, self.ty), Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self, - Err(ErrorHandled::Reported(ErrorReported)) => { - tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: self.ty }) - } + Err(ErrorHandled::Reported(ErrorReported)) => tcx.err_const(self.ty), } } else { self diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 36ccc0aaa8bb4..f7f66699c1876 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -494,7 +494,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { if place_ty.variant_index.is_none() { if place_ty.ty.references_error() { assert!(self.errors_reported); - return PlaceTy::from_ty(self.tcx().types.err); + return PlaceTy::from_ty(self.tcx().err()); } } place_ty = self.sanitize_projection(place_ty, elem, place, location) @@ -721,7 +721,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn error(&mut self) -> Ty<'tcx> { self.errors_reported = true; - self.tcx().types.err + self.tcx().err() } fn field_ty( diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 2ce2627987a01..74b5c7e3578f3 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -687,7 +687,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t let tcx = hir.tcx(); let owner_id = tcx.hir().body_owner(body_id); let span = tcx.hir().span(owner_id); - let ty = tcx.types.err; + let ty = tcx.err(); let num_params = match hir.body_owner_kind { hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len(), hir::BodyOwnerKind::Closure => { diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index de3ae2e961f42..ec44e3d193a19 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -242,7 +242,7 @@ use rustc_hir::{HirId, RangeEnd}; use rustc_middle::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar}; use rustc_middle::mir::Field; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef}; +use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Integer, Size, VariantIdx}; @@ -408,7 +408,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> { PatStack::from_slice(&self.0[1..]) } - fn iter(&self) -> impl Iterator> { + fn iter(&self) -> impl Iterator> + DoubleEndedIterator { self.0.iter().copied() } @@ -441,12 +441,13 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> { &self, cx: &mut MatchCheckCtxt<'p, 'tcx>, constructor: &Constructor<'tcx>, - ctor_wild_subpatterns: &'p [Pat<'tcx>], + ctor_wild_fields: &Fields<'p, 'tcx>, ) -> Option> { - let new_heads = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns); - new_heads.map(|mut new_head| { - new_head.0.extend_from_slice(&self.0[1..]); - new_head + let new_heads = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_fields); + new_heads.map(|fields| { + let mut new_head = fields.filtered_patterns(); + new_head.extend_from_slice(&self.0[1..]); + PatStack::from_vec(new_head) }) } } @@ -503,11 +504,11 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> { &self, cx: &mut MatchCheckCtxt<'p, 'tcx>, constructor: &Constructor<'tcx>, - ctor_wild_subpatterns: &'p [Pat<'tcx>], + ctor_wild_fields: &Fields<'p, 'tcx>, ) -> Matrix<'p, 'tcx> { self.0 .iter() - .filter_map(|r| r.specialize_constructor(cx, constructor, ctor_wild_subpatterns)) + .filter_map(|r| r.specialize_constructor(cx, constructor, ctor_wild_fields)) .collect() } } @@ -604,7 +605,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } } - // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. + /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. crate fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { match ty.kind { ty::Adt(def, ..) => { @@ -613,15 +614,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { _ => false, } } - - // Returns whether the given variant is from another crate and has its fields declared - // `#[non_exhaustive]`. - fn is_foreign_non_exhaustive_variant(&self, ty: Ty<'tcx>, variant: &VariantDef) -> bool { - match ty.kind { - ty::Adt(def, ..) => variant.is_field_list_non_exhaustive() && !def.did.is_local(), - _ => false, - } - } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -733,10 +725,17 @@ impl Slice { } } +/// A value can be decomposed into a constructor applied to some fields. This struct represents +/// the constructor. See also `Fields`. +/// +/// `pat_constructor` retrieves the constructor corresponding to a pattern. +/// `specialize_one_pattern` returns the list of fields corresponding to a pattern, given a +/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and +/// `Fields`. #[derive(Clone, Debug, PartialEq)] enum Constructor<'tcx> { - /// The constructor of all patterns that don't vary by constructor, - /// e.g., struct patterns and fixed-length arrays. + /// The constructor for patterns that have a single constructor, like tuples, struct patterns + /// and fixed-length arrays. Single, /// Enum variants. Variant(DefId), @@ -861,107 +860,10 @@ impl<'tcx> Constructor<'tcx> { } } - /// This returns one wildcard pattern for each argument to this constructor. - /// - /// This must be consistent with `apply`, `specialize_one_pattern`, and `arity`. - fn wildcard_subpatterns<'a>( - &self, - cx: &MatchCheckCtxt<'a, 'tcx>, - ty: Ty<'tcx>, - ) -> Vec> { - debug!("wildcard_subpatterns({:#?}, {:?})", self, ty); - - match self { - Single | Variant(_) => match ty.kind { - ty::Tuple(ref fs) => { - fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect() - } - ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)], - ty::Adt(adt, substs) => { - if adt.is_box() { - // Use T as the sub pattern type of Box. - vec![Pat::wildcard_from_ty(substs.type_at(0))] - } else { - let variant = &adt.variants[self.variant_index_for_adt(cx, adt)]; - let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(ty, variant); - variant - .fields - .iter() - .map(|field| { - let is_visible = adt.is_enum() - || field.vis.is_accessible_from(cx.module, cx.tcx); - let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs)); - match (is_visible, is_non_exhaustive, is_uninhabited) { - // Treat all uninhabited types in non-exhaustive variants as - // `TyErr`. - (_, true, true) => cx.tcx.types.err, - // Treat all non-visible fields as `TyErr`. They can't appear - // in any other pattern from this match (because they are - // private), so their type does not matter - but we don't want - // to know they are uninhabited. - (false, ..) => cx.tcx.types.err, - (true, ..) => { - let ty = field.ty(cx.tcx, substs); - match ty.kind { - // If the field type returned is an array of an unknown - // size return an TyErr. - ty::Array(_, len) - if len - .try_eval_usize(cx.tcx, cx.param_env) - .is_none() => - { - cx.tcx.types.err - } - _ => ty, - } - } - } - }) - .map(Pat::wildcard_from_ty) - .collect() - } - } - _ => vec![], - }, - Slice(_) => match ty.kind { - ty::Slice(ty) | ty::Array(ty, _) => { - let arity = self.arity(cx, ty); - (0..arity).map(|_| Pat::wildcard_from_ty(ty)).collect() - } - _ => bug!("bad slice pattern {:?} {:?}", self, ty), - }, - ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => vec![], - } - } - - /// This computes the arity of a constructor. The arity of a constructor - /// is how many subpattern patterns of that constructor should be expanded to. - /// - /// For instance, a tuple pattern `(_, 42, Some([]))` has the arity of 3. - /// A struct pattern's arity is the number of fields it contains, etc. - /// - /// This must be consistent with `wildcard_subpatterns`, `specialize_one_pattern`, and `apply`. - fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 { - debug!("Constructor::arity({:#?}, {:?})", self, ty); - match self { - Single | Variant(_) => match ty.kind { - ty::Tuple(ref fs) => fs.len() as u64, - ty::Slice(..) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty), - ty::Ref(..) => 1, - ty::Adt(adt, _) => { - adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64 - } - _ => 0, - }, - Slice(slice) => slice.arity(), - ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => 0, - } - } - /// Apply a constructor to a list of patterns, yielding a new pattern. `pats` /// must have as many elements as this constructor's arity. /// - /// This must be consistent with `wildcard_subpatterns`, `specialize_one_pattern`, and `arity`. + /// This is morally the inverse of `specialize_one_pattern`. /// /// Examples: /// `self`: `Constructor::Single` @@ -973,13 +875,13 @@ impl<'tcx> Constructor<'tcx> { /// `ty`: `Option` /// `pats`: `[false]` /// returns `Some(false)` - fn apply<'a>( + fn apply<'p>( &self, - cx: &MatchCheckCtxt<'a, 'tcx>, + cx: &MatchCheckCtxt<'p, 'tcx>, ty: Ty<'tcx>, - pats: impl IntoIterator>, + fields: Fields<'p, 'tcx>, ) -> Pat<'tcx> { - let mut subpatterns = pats.into_iter(); + let mut subpatterns = fields.all_patterns().into_iter(); let pat = match self { Single | Variant(_) => match ty.kind { @@ -1044,8 +946,192 @@ impl<'tcx> Constructor<'tcx> { /// Like `apply`, but where all the subpatterns are wildcards `_`. fn apply_wildcards<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> { - let subpatterns = self.wildcard_subpatterns(cx, ty).into_iter().rev(); - self.apply(cx, ty, subpatterns) + self.apply(cx, ty, Fields::wildcards(cx, self, ty)) + } +} + +#[derive(Debug, Copy, Clone)] +enum StructField<'p, 'tcx> { + Kept(&'p Pat<'tcx>), + Hidden(Ty<'tcx>), +} + +impl<'p, 'tcx> StructField<'p, 'tcx> { + fn wildcard_from_ty(cx: &MatchCheckCtxt<'p, 'tcx>, ty: Ty<'tcx>) -> Self { + let wild = &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty)); + StructField::Kept(wild) + } + + fn kept(self) -> Option<&'p Pat<'tcx>> { + match self { + StructField::Kept(p) => Some(p), + StructField::Hidden(_) => None, + } + } + + fn to_pattern(self) -> Pat<'tcx> { + match self { + StructField::Kept(p) => p.clone(), + StructField::Hidden(ty) => Pat::wildcard_from_ty(ty), + } + } +} + +/// A value can be decomposed into a constructor applied to some fields. This struct represents +/// those fields, generalized to allow patterns in each field. See also `Constructor`. +/// +/// In some special cases of uninhabited types, we filter out those fields in the matrix so that +/// the code can't observe they are uninhabited. But we do need to handle the full list of fields +/// when going to/from a `Pat`, hence the distinction between filtered and unfiltered fields. As a +/// rule, when going to/from the matrix, use the filtered fields; when going to/from `Pat`, use the +/// full fields. +#[derive(Debug, Clone)] +enum Fields<'p, 'tcx> { + /// Fields of a struct/tuple/variant, with special handling of uninhabited types. + Struct(SmallVec<[StructField<'p, 'tcx>; 2]>), + /// Non-struct list of patterns + Other(SmallVec<[&'p Pat<'tcx>; 2]>), + /// Optimization for slices of wildcards + WildcardSlice { arity: usize, wild: &'p Pat<'tcx> }, +} + +impl<'p, 'tcx> Fields<'p, 'tcx> { + fn empty() -> Self { + Fields::Other(smallvec![]) + } + + /// Construct a new `Fields` from the given patterns. Must not be used if the patterns are + /// fields of a struct/tuple/variant. + fn from_patterns_not_struct(pats: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self { + Fields::Other(pats) + } + + /// Creates a new list of wildcard fields for a given constructor. + fn wildcards( + cx: &MatchCheckCtxt<'p, 'tcx>, + constructor: &Constructor<'tcx>, + ty: Ty<'tcx>, + ) -> Self { + debug!("Fields::wildcards({:#?}, {:?})", constructor, ty); + + match constructor { + Single | Variant(_) => Fields::Struct(match ty.kind { + ty::Tuple(ref fs) => fs + .into_iter() + .map(|t| t.expect_ty()) + .map(|ty| StructField::wildcard_from_ty(cx, ty)) + .collect(), + ty::Ref(_, rty, _) => smallvec![StructField::wildcard_from_ty(cx, rty)], + ty::Adt(adt, substs) => { + if adt.is_box() { + // Use T as the sub pattern type of Box. + smallvec![StructField::wildcard_from_ty(cx, substs.type_at(0))] + } else { + let variant = &adt.variants[constructor.variant_index_for_adt(cx, adt)]; + // Whether we must not match the fields of this variant exhaustively. + let is_non_exhaustive = + variant.is_field_list_non_exhaustive() && !adt.did.is_local(); + variant + .fields + .iter() + .map(|field| { + let field_ty = field.ty(cx.tcx, substs); + let is_visible = adt.is_enum() + || field.vis.is_accessible_from(cx.module, cx.tcx); + let is_uninhabited = cx.is_uninhabited(field_ty); + + // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide + // uninhabited fields in order not to reveal the uninhabitedness of the whole variant. + if is_uninhabited && (!is_visible || is_non_exhaustive) { + StructField::Hidden(field_ty) + } else { + StructField::wildcard_from_ty(cx, field_ty) + } + }) + .collect() + } + } + _ => smallvec![], + }), + Slice(slice) => match ty.kind { + ty::Slice(ty) | ty::Array(ty, _) => { + let wild = &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty)); + let arity = slice.arity() as usize; + Fields::WildcardSlice { arity, wild } + } + _ => bug!("bad slice pattern {:?} {:?}", constructor, ty), + }, + ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => Fields::empty(), + } + } + + /// Overrides some of the fields with the provided patterns. Panics if `self` is not `Struct`. + fn replace_fields_indexed(&self, pats: impl IntoIterator>) -> Self { + match self { + Fields::Struct(fields) => { + let mut fields = fields.clone(); + for pat in pats { + if let StructField::Kept(p) = &mut fields[pat.field.index()] { + *p = &pat.pattern + } + } + Fields::Struct(fields) + } + _ => bug!("`replace_fields_indexed` called on the wrong kind of `Fields`"), + } + } + + /// Replaces contained fields with the given filtered list of patterns, e.g. taken from the + /// matrix. + fn replace_fields( + &self, + cx: &MatchCheckCtxt<'p, 'tcx>, + pats: impl IntoIterator>, + ) -> Self { + // There should be `arity()` patterns in there. + let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats); + let mut pats = pats.iter(); + + match self { + Fields::Struct(fields) => { + let mut fields = fields.clone(); + for f in &mut fields { + if let StructField::Kept(p) = f { + // We take one input pattern for each `Kept` field, in order. + *p = pats.next().unwrap(); + } + } + Fields::Struct(fields) + } + _ => Fields::Other(pats.collect()), + } + } + + /// Number of (filtered) patterns contained. + fn arity(&self) -> usize { + match self { + Fields::Struct(fields) => fields.iter().filter(|p| p.kept().is_some()).count(), + Fields::Other(pats) => pats.len(), + &Fields::WildcardSlice { arity, .. } => arity, + } + } + + /// Returns the exhaustive list of patterns. + fn all_patterns(&self) -> SmallVec<[Pat<'tcx>; 2]> { + match self { + Fields::Struct(fields) => fields.iter().map(|p| p.to_pattern()).collect(), + Fields::Other(pats) => pats.iter().copied().cloned().collect(), + &Fields::WildcardSlice { arity, wild } => (0..arity).map(|_| wild).cloned().collect(), + } + } + + /// Returns the filtered list of patterns, to be stored in the matrix. + fn filtered_patterns(self) -> SmallVec<[&'p Pat<'tcx>; 2]> { + match self { + Fields::Struct(fields) => fields.into_iter().filter_map(|p| p.kept()).collect(), + Fields::Other(pats) => pats, + Fields::WildcardSlice { arity, wild } => (0..arity).map(|_| wild).collect(), + } } } @@ -1075,15 +1161,16 @@ impl<'tcx, 'p> Usefulness<'tcx, 'p> { fn apply_constructor( self, - cx: &MatchCheckCtxt<'_, 'tcx>, + cx: &MatchCheckCtxt<'p, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>, + ctor_wild_fields: &Fields<'p, 'tcx>, ) -> Self { match self { UsefulWithWitness(witnesses) => UsefulWithWitness( witnesses .into_iter() - .map(|witness| witness.apply_constructor(cx, &ctor, ty)) + .map(|witness| witness.apply_constructor(cx, &ctor, ty, ctor_wild_fields)) .collect(), ), x => x, @@ -1203,17 +1290,19 @@ impl<'tcx> Witness<'tcx> { /// /// left_ty: struct X { a: (bool, &'static str), b: usize} /// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 } - fn apply_constructor<'a>( + fn apply_constructor<'p>( mut self, - cx: &MatchCheckCtxt<'a, 'tcx>, + cx: &MatchCheckCtxt<'p, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>, + ctor_wild_fields: &Fields<'p, 'tcx>, ) -> Self { - let arity = ctor.arity(cx, ty); let pat = { - let len = self.0.len() as u64; - let pats = self.0.drain((len - arity) as usize..).rev(); - ctor.apply(cx, ty, pats) + let len = self.0.len(); + let arity = ctor_wild_fields.arity(); + let pats = self.0.drain((len - arity)..).rev(); + let fields = ctor_wild_fields.replace_fields(cx, pats); + ctor.apply(cx, ty, fields) }; self.0.push(pat); @@ -1838,19 +1927,19 @@ fn is_useful_specialized<'p, 'tcx>( matrix: &Matrix<'p, 'tcx>, v: &PatStack<'p, 'tcx>, ctor: Constructor<'tcx>, - lty: Ty<'tcx>, + ty: Ty<'tcx>, witness_preference: WitnessPreference, hir_id: HirId, is_under_guard: bool, ) -> Usefulness<'tcx, 'p> { - debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty); + debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, ty); - let ctor_wild_subpatterns = - cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty)); - let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns); - v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns) + // We cache the result of `Fields::wildcards` because it is used a lot. + let ctor_wild_fields = Fields::wildcards(cx, &ctor, ty); + let matrix = matrix.specialize_constructor(cx, &ctor, &ctor_wild_fields); + v.specialize_constructor(cx, &ctor, &ctor_wild_fields) .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false)) - .map(|u| u.apply_constructor(cx, &ctor, lty)) + .map(|u| u.apply_constructor(cx, &ctor, ty, &ctor_wild_fields)) .unwrap_or(NotUseful) } @@ -2314,27 +2403,6 @@ fn constructor_covered_by_range<'tcx>( if intersects { Some(()) } else { None } } -fn patterns_for_variant<'p, 'tcx>( - cx: &mut MatchCheckCtxt<'p, 'tcx>, - subpatterns: &'p [FieldPat<'tcx>], - ctor_wild_subpatterns: &'p [Pat<'tcx>], - is_non_exhaustive: bool, -) -> PatStack<'p, 'tcx> { - let mut result: SmallVec<_> = ctor_wild_subpatterns.iter().collect(); - - for subpat in subpatterns { - if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) { - result[subpat.field.index()] = &subpat.pattern; - } - } - - debug!( - "patterns_for_variant({:#?}, {:#?}) = {:#?}", - subpatterns, ctor_wild_subpatterns, result - ); - PatStack::from_vec(result) -} - /// This is the main specialization step. It expands the pattern /// into `arity` patterns based on the constructor. For most patterns, the step is trivial, /// for instance tuple patterns are flattened and box patterns expand into their inner pattern. @@ -2344,39 +2412,44 @@ fn patterns_for_variant<'p, 'tcx>( /// different patterns. /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing /// fields filled with wild patterns. +/// +/// This is morally the inverse of `Constructor::apply`. fn specialize_one_pattern<'p, 'tcx>( cx: &mut MatchCheckCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>, constructor: &Constructor<'tcx>, - ctor_wild_subpatterns: &'p [Pat<'tcx>], -) -> Option> { + ctor_wild_fields: &Fields<'p, 'tcx>, +) -> Option> { if let NonExhaustive = constructor { // Only a wildcard pattern can match the special extra constructor - return if pat.is_wildcard() { Some(PatStack::default()) } else { None }; + return if pat.is_wildcard() { Some(Fields::empty()) } else { None }; } let result = match *pat.kind { PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern` - PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.iter().collect()), + PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_fields.clone()), PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { - let variant = &adt_def.variants[variant_index]; - let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant); - Some(Variant(variant.def_id)) - .filter(|variant_constructor| variant_constructor == constructor) - .map(|_| { - patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns, is_non_exhaustive) - }) + let pat_ctor = Variant(adt_def.variants[variant_index].def_id); + if constructor == &pat_ctor { + Some(ctor_wild_fields.replace_fields_indexed(subpatterns)) + } else { + None + } } PatKind::Leaf { ref subpatterns } => { - Some(patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns, false)) + Some(ctor_wild_fields.replace_fields_indexed(subpatterns)) } - PatKind::Deref { ref subpattern } => Some(PatStack::from_pattern(subpattern)), + PatKind::Deref { ref subpattern } => { + Some(Fields::from_patterns_not_struct(smallvec![subpattern])) + } PatKind::Constant { value } if constructor.is_slice() => { + let arity = ctor_wild_fields.arity() as u64; + // We extract an `Option` for the pointer because slices of zero // elements don't necessarily point to memory, they are usually // just integers. The only time they should be pointing to memory @@ -2387,8 +2460,8 @@ fn specialize_one_pattern<'p, 'tcx>( // Shortcut for `n == 0` where no matter what `alloc` and `offset` we produce, // the result would be exactly what we early return here. if n == 0 { - if ctor_wild_subpatterns.len() as u64 == 0 { - return Some(PatStack::from_slice(&[])); + if arity == 0 { + return Some(Fields::empty()); } else { return None; } @@ -2425,7 +2498,7 @@ fn specialize_one_pattern<'p, 'tcx>( constructor, ), }; - if ctor_wild_subpatterns.len() as u64 == n { + if arity == n { // convert a constant slice/array pattern to a list of patterns. let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; let ptr = Pointer::new(AllocId(0), offset); @@ -2439,7 +2512,8 @@ fn specialize_one_pattern<'p, 'tcx>( Pat { ty, span: pat.span, kind: box PatKind::Constant { value } }; Some(&*cx.pattern_arena.alloc(pattern)) }) - .collect() + .collect::>() + .map(Fields::from_patterns_not_struct) } else { None } @@ -2455,7 +2529,7 @@ fn specialize_one_pattern<'p, 'tcx>( // Constructor splitting should ensure that all intersections we encounter // are actually inclusions. assert!(ctor.is_subrange(&pat)); - PatStack::default() + Fields::empty() }), _ => None, } @@ -2466,28 +2540,27 @@ fn specialize_one_pattern<'p, 'tcx>( // range so intersection actually devolves into being covered // by the pattern. constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat) - .map(|()| PatStack::default()) + .map(|()| Fields::empty()) } } PatKind::Array { ref prefix, ref slice, ref suffix } | PatKind::Slice { ref prefix, ref slice, ref suffix } => match *constructor { Slice(_) => { + let (arity, wild_pat) = match *ctor_wild_fields { + Fields::WildcardSlice { arity, wild } => (arity, wild), + _ => bug!("bad slice pattern {:?} {:?}", ctor_wild_fields, pat.ty), + }; let pat_len = prefix.len() + suffix.len(); - if let Some(slice_count) = ctor_wild_subpatterns.len().checked_sub(pat_len) { + if let Some(slice_count) = arity.checked_sub(pat_len) { if slice_count == 0 || slice.is_some() { - Some( + Some(Fields::from_patterns_not_struct( prefix .iter() - .chain( - ctor_wild_subpatterns - .iter() - .skip(prefix.len()) - .take(slice_count) - .chain(suffix.iter()), - ) + .chain((0..slice_count).map(|_| wild_pat)) + .chain(suffix.iter()) .collect(), - ) + )) } else { None } @@ -2505,7 +2578,7 @@ fn specialize_one_pattern<'p, 'tcx>( suffix, cx.param_env, ) { - Ok(true) => Some(PatStack::default()), + Ok(true) => Some(Fields::empty()), Ok(false) => None, Err(ErrorReported) => None, } @@ -2515,7 +2588,7 @@ fn specialize_one_pattern<'p, 'tcx>( PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."), }; - debug!("specialize({:#?}, {:#?}) = {:#?}", pat, ctor_wild_subpatterns, result); + debug!("specialize({:#?}) = {:#?}", pat, result); result } diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 4f8075b0171d3..f0cc9806bb4ed 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -939,7 +939,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); - self.tcx().types.err + self.tcx().err() } } } @@ -972,7 +972,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); - self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty }) + self.tcx().err_const(ct.ty) } } } @@ -1000,7 +1000,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { tcx, ty_op: |ty| { if ty.references_error() { - return tcx.types.err; + return tcx.err(); } else if let ty::Opaque(def_id, substs) = ty.kind { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 2b4a0409fd1e2..6e419a5acbf2f 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -773,7 +773,7 @@ struct Progress<'tcx> { impl<'tcx> Progress<'tcx> { fn error(tcx: TyCtxt<'tcx>) -> Self { - Progress { ty: tcx.types.err, obligations: vec![] } + Progress { ty: tcx.err(), obligations: vec![] } } fn with_addl_obligations(mut self, mut obligations: Vec>) -> Self { @@ -1356,7 +1356,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); debug!("confirm_param_env_candidate: {}", msg); infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg); - Progress { ty: infcx.tcx.types.err, obligations: vec![] } + Progress { ty: infcx.tcx.err(), obligations: vec![] } } } } @@ -1375,7 +1375,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let param_env = obligation.param_env; let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) { Ok(assoc_ty) => assoc_ty, - Err(ErrorReported) => return Progress { ty: tcx.types.err, obligations: nested }, + Err(ErrorReported) => return Progress { ty: tcx.err(), obligations: nested }, }; if !assoc_ty.item.defaultness.has_value() { @@ -1387,7 +1387,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( "confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.ident, obligation.predicate ); - return Progress { ty: tcx.types.err, obligations: nested }; + return Progress { ty: tcx.err(), obligations: nested }; } let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs); let substs = @@ -1401,7 +1401,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() { tcx.sess .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts"); - Progress { ty: tcx.types.err, obligations: nested } + Progress { ty: tcx.err(), obligations: nested } } else { Progress { ty: ty.subst(tcx, substs), obligations: nested } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index cd6cd94b14356..6eccb2ab0d275 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -780,7 +780,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) { inferred_params.push(ty.span); - tcx.types.err.into() + tcx.err().into() } else { self.ast_ty_to_ty(&ty).into() } @@ -806,7 +806,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // careful! if default_needs_object_self(param) { missing_type_params.push(param.name.to_string()); - tcx.types.err.into() + tcx.err().into() } else { // This is a default type parameter. self.normalize_ty( @@ -826,7 +826,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ty_infer(param, span).into() } else { // We've already errored above about the mismatch. - tcx.types.err.into() + tcx.err().into() } } GenericParamDefKind::Const => { @@ -837,7 +837,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ct_infer(ty, Some(param), span).into() } else { // We've already errored above about the mismatch. - tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty }).into() + tcx.err_const(ty).into() } } } @@ -1564,7 +1564,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "at least one trait is required for an object type" ) .emit(); - return tcx.types.err; + return tcx.err(); } // Check that there are no gross object safety violations; @@ -1581,7 +1581,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &object_safety_violations[..], ) .emit(); - return tcx.types.err; + return tcx.err(); } } @@ -2391,7 +2391,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &path_str, item_segment.ident.name, ); - return tcx.types.err; + return tcx.err(); }; debug!("qpath_to_ty: self_type={:?}", self_ty); @@ -2708,7 +2708,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Res::Err => { self.set_tainted_by_errors(); - self.tcx().types.err + self.tcx().err() } _ => span_bug!(span, "unexpected resolution: {:?}", path.res), } @@ -2769,7 +2769,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, res, segment, false) .map(|(ty, _, _)| ty) - .unwrap_or(tcx.types.err) + .unwrap_or_else(|_| tcx.err()) } hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.hir_id); @@ -2787,7 +2787,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .span_label(ast_ty.span, "reserved keyword") .emit(); - tcx.types.err + tcx.err() } hir::TyKind::Infer => { // Infer also appears as the type of arguments or return @@ -2796,7 +2796,7 @@ 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::Err => tcx.types.err, + hir::TyKind::Err => tcx.err(), }; debug!("ast_ty_to_ty: result_ty={:?}", result_ty); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 16af168ce1af9..8ddecc1061642 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -105,7 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && i != 0 && self.if_fallback_coercion(expr.span, &arms[0].body, &mut coercion) { - tcx.types.err + tcx.err() } else { // Only call this if this is not an `if` expr with an expected type and no `else` // clause to avoid duplicated type errors. (#60254) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 0d254412203aa..22d298f5337c9 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -363,7 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ( ty::Binder::bind(self.tcx.mk_fn_sig( self.err_args(arg_exprs.len()).into_iter(), - self.tcx.types.err, + self.tcx.err(), false, hir::Unsafety::Normal, abi::Abi::Rust, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 1acbcc038891d..c97d2174a8953 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match expected_ty.kind { ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { - let pb = pb.with_self_ty(self.tcx, self.tcx.types.err); + let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); self.deduce_sig_from_projection(None, &pb) }); let kind = object_type @@ -714,7 +714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let supplied_arguments = decl.inputs.iter().map(|a| { // Convert the types that the user supplied (if any), but ignore them. astconv.ast_ty_to_ty(a); - self.tcx.types.err + self.tcx.err() }); if let hir::FnRetTy::Return(ref output) = decl.output { @@ -723,7 +723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = ty::Binder::bind(self.tcx.mk_fn_sig( supplied_arguments, - self.tcx.types.err, + self.tcx.err(), decl.c_variadic, hir::Unsafety::Normal, Abi::RustCall, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 86cafa0b8ca25..0b65b0ff61aaa 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -162,7 +162,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Just ignore error types. if a.references_error() || b.references_error() { - return success(vec![], self.fcx.tcx.types.err, vec![]); + return success(vec![], self.fcx.tcx.err(), vec![]); } if a.is_never() { @@ -827,7 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (adjustments, _) = self.register_infer_ok_obligations(ok); self.apply_adjustments(expr, adjustments); - Ok(if expr_ty.references_error() { self.tcx.types.err } else { target }) + Ok(if expr_ty.references_error() { self.tcx.err() } else { target }) } /// Same as `try_coerce()`, but without side-effects. @@ -1156,7 +1156,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // If we see any error types, just propagate that error // upwards. if expression_ty.references_error() || self.merged_ty().references_error() { - self.final_ty = Some(fcx.tcx.types.err); + self.final_ty = Some(fcx.tcx.err()); return; } @@ -1313,7 +1313,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { err.emit_unless(assign_to_bool || unsized_return); - self.final_ty = Some(fcx.tcx.types.err); + self.final_ty = Some(fcx.tcx.err()); } } } diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 92ddfbff824cd..e4fa990e16d27 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.types.never } else { // There was an error; make type-check fail. - tcx.types.err + tcx.err() } } ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), @@ -282,7 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Field(ref base, field) => self.check_field(expr, needs, &base, field), ExprKind::Index(ref base, ref idx) => self.check_expr_index(base, idx, needs, expr), ExprKind::Yield(ref value, ref src) => self.check_expr_yield(value, expr, src), - hir::ExprKind::Err => tcx.types.err, + hir::ExprKind::Err => tcx.err(), } } @@ -358,7 +358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp, None); } err.emit(); - oprnd_t = tcx.types.err; + oprnd_t = tcx.err(); } } hir::UnOp::UnNot => { @@ -408,7 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tm = ty::TypeAndMut { ty, mutbl }; match kind { - _ if tm.ty.references_error() => self.tcx.types.err, + _ if tm.ty.references_error() => self.tcx.err(), hir::BorrowKind::Raw => { self.check_named_place_expr(oprnd); self.tcx.mk_ptr(tm) @@ -474,11 +474,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = match res { Res::Err => { self.set_tainted_by_errors(); - tcx.types.err + tcx.err() } Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => { report_unexpected_variant_res(tcx, res, expr.span); - tcx.types.err + tcx.err() } _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, }; @@ -562,7 +562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, "break was outside loop, but no error was emitted", ); - return tcx.types.err; + return tcx.err(); } } }; @@ -570,7 +570,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the loop context is not a `loop { }`, then break with // a value is illegal, and `opt_coerce_to` will be `None`. // Just set expectation to error in that case. - let coerce_to = opt_coerce_to.unwrap_or(tcx.types.err); + let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.err()); // Recurse without `enclosing_breakables` borrowed. e_ty = self.check_expr_with_hint(e, coerce_to); @@ -594,7 +594,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, "break was outside loop, but no error was emitted", ); - return tcx.types.err; + return tcx.err(); } }; @@ -654,7 +654,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We still need to assign a type to the inner expression to // prevent the ICE in #43162. if let Some(ref e) = expr_opt { - self.check_expr_with_hint(e, tcx.types.err); + self.check_expr_with_hint(e, tcx.err()); // ... except when we try to 'break rust;'. // ICE this expression in particular (see #43162). @@ -665,7 +665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } // There was an error; make type-check fail. - tcx.types.err + tcx.err() } } @@ -801,7 +801,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); if lhs_ty.references_error() || rhs_ty.references_error() { - self.tcx.types.err + self.tcx.err() } else { self.tcx.mk_unit() } @@ -955,7 +955,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Eagerly check for some obvious errors. if t_expr.references_error() || t_cast.references_error() { - self.tcx.types.err + self.tcx.err() } else { // Defer other checks until we're done type checking. let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); @@ -964,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { deferred_cast_checks.push(cast_check); t_cast } - Err(ErrorReported) => self.tcx.types.err, + Err(ErrorReported) => self.tcx.err(), } } } @@ -1039,7 +1039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if element_ty.references_error() { - return tcx.types.err; + return tcx.err(); } tcx.mk_ty(ty::Array(t, count)) @@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let tuple = self.tcx.mk_tup(elt_ts_iter); if tuple.references_error() { - self.tcx.types.err + self.tcx.err() } else { self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); tuple @@ -1090,7 +1090,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant_ty } else { self.check_struct_fields_on_error(fields, base_expr); - return self.tcx.types.err; + return self.tcx.err(); }; let path_span = match *qpath { @@ -1231,7 +1231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span); } - tcx.types.err + tcx.err() }; // Make sure to give a type to the field even if there's @@ -1517,7 +1517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } - self.tcx().types.err + self.tcx().err() } fn ban_nonexisting_field( @@ -1773,7 +1773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } err.emit(); - self.tcx.types.err + self.tcx.err() } } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 64dc34ab3b0a7..a52d8ad020b94 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { rustc_span::DUMMY_SP, &format!("failed autoderef {}", pick.autoderefs), ); - return self.tcx.types.err; + return self.tcx.err(); } }; assert_eq!(n, pick.autoderefs); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 03e32c21a54ac..fdd1ed6fa2e00 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -400,7 +400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .probe_instantiate_query_response(span, &orig_values, ty) .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty)); let ty = self.structurally_resolved_type(span, ty.value); - assert_eq!(ty, self.tcx.types.err); + assert_eq!(ty, self.tcx.err()); return Err(MethodError::NoMatch(NoMatchData::new( Vec::new(), Vec::new(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bff1ca2433a83..c6d941c9bde21 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -982,7 +982,7 @@ fn diagnostic_only_typeck_tables_of<'tcx>( let fallback = move || { let span = tcx.hir().span(tcx.hir().as_local_hir_id(def_id)); tcx.sess.delay_span_bug(span, "diagnostic only typeck table used"); - tcx.types.err + tcx.err() }; typeck_tables_of_with_fallback(tcx, def_id, fallback) } @@ -3400,7 +3400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> { match self.tables.borrow().node_types().get(id) { Some(&t) => t, - None if self.is_tainted_by_errors() => self.tcx.types.err, + None if self.is_tainted_by_errors() => self.tcx.err(), None => { bug!( "no type for node {}: {} in fcx {}", @@ -3515,7 +3515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(ty.is_ty_infer()); let fallback = match self.type_is_unconstrained_numeric(ty) { - _ if self.is_tainted_by_errors() => self.tcx().types.err, + _ if self.is_tainted_by_errors() => self.tcx().err(), UnconstrainedInt => self.tcx.types.i32, UnconstrainedFloat => self.tcx.types.f64, Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(), @@ -3788,7 +3788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tuple_arguments, None, ); - return self.tcx.types.err; + return self.tcx.err(); } let method = method.unwrap(); @@ -4172,7 +4172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn err_args(&self, len: usize) -> Vec> { - vec![self.tcx.types.err; len] + vec![self.tcx.err(); len] } /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk @@ -4314,7 +4314,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_ty.unwrap_or_else(|| self.next_float_var()) } ast::LitKind::Bool(_) => tcx.types.bool, - ast::LitKind::Err(_) => tcx.types.err, + ast::LitKind::Err(_) => tcx.err(), } } @@ -4451,7 +4451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let result = AstConv::associated_path_to_ty(self, hir_id, path_span, ty, res, segment, true); - let ty = result.map(|(ty, _, _)| ty).unwrap_or(self.tcx().types.err); + let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().err()); let result = result.map(|(_, kind, def_id)| (kind, def_id)); // Write back the new resolution. @@ -4579,7 +4579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) { if ty.references_error() { - // Override the types everywhere with `types.err` to avoid knock on errors. + // Override the types everywhere with `err()` to avoid knock on errors. self.write_ty(local.hir_id, ty); self.write_ty(local.pat.hir_id, ty); let local_ty = LocalTy { decl_ty, revealed_ty: ty }; @@ -4799,7 +4799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut ty = ctxt.coerce.unwrap().complete(self); if self.has_errors.get() || ty.references_error() { - ty = self.tcx.types.err + ty = self.tcx.err() } self.write_ty(blk.hir_id, ty); @@ -5546,7 +5546,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } err.emit(); - return (tcx.types.err, res); + return (tcx.err(), res); } } } else { @@ -5730,8 +5730,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .note("type must be known at this point") .emit(); } - self.demand_suptype(sp, self.tcx.types.err, ty); - self.tcx.types.err + self.demand_suptype(sp, self.tcx.err(), ty); + self.tcx.err() } } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 23004cf364725..9d0bab70fef41 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -473,7 +473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.tcx.types.err + self.tcx.err() } }; @@ -685,7 +685,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } err.emit(); } - self.tcx.types.err + self.tcx.err() } } } diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 8e109efbcb576..5cb557ad97182 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -441,7 +441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // There exists a side that didn't meet our criteria that the end-point // be of a numeric or char type, as checked in `calc_side` above. self.emit_err_pat_range(span, lhs, rhs); - return self.tcx.types.err; + return self.tcx.err(); } // Now that we know the types can be unified we find the unified type @@ -674,9 +674,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { for field in fields { let ti = TopInfo { parent_pat: Some(&pat), ..ti }; - self.check_pat(&field.pat, self.tcx.types.err, def_bm, ti); + self.check_pat(&field.pat, self.tcx.err(), def_bm, ti); } - return self.tcx.types.err; + return self.tcx.err(); }; // Type-check the path. @@ -686,7 +686,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, etc, def_bm, ti) { pat_ty } else { - self.tcx.types.err + self.tcx.err() } } @@ -704,11 +704,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match res { Res::Err => { self.set_tainted_by_errors(); - return tcx.types.err; + return tcx.err(); } Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => { report_unexpected_variant_res(tcx, res, pat.span); - return tcx.types.err; + return tcx.err(); } Res::SelfCtor(..) | Res::Def( @@ -787,7 +787,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let on_error = || { let parent_pat = Some(pat); for pat in subpats { - self.check_pat(&pat, tcx.types.err, def_bm, TopInfo { parent_pat, ..ti }); + self.check_pat(&pat, tcx.err(), def_bm, TopInfo { parent_pat, ..ti }); } }; let report_unexpected_res = |res: Res| { @@ -823,7 +823,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if res == Res::Err { self.set_tainted_by_errors(); on_error(); - return self.tcx.types.err; + return self.tcx.err(); } // Type-check the path. @@ -831,18 +831,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id); if !pat_ty.is_fn() { report_unexpected_res(res); - return tcx.types.err; + return tcx.err(); } let variant = match res { Res::Err => { self.set_tainted_by_errors(); on_error(); - return tcx.types.err; + return tcx.err(); } Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { report_unexpected_res(res); - return tcx.types.err; + return tcx.err(); } Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res), _ => bug!("unexpected pattern resolution: {:?}", res), @@ -879,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Pattern has wrong number of fields. self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err); on_error(); - return tcx.types.err; + return tcx.err(); } pat_ty } @@ -1000,9 +1000,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); // Walk subpatterns with an expected type of `err` in this case to silence // further errors being emitted when using the bindings. #50333 - let element_tys_iter = (0..max_len).map(|_| tcx.types.err); + let element_tys_iter = (0..max_len).map(|_| tcx.err()); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, &tcx.types.err, def_bm, ti); + self.check_pat(elem, &tcx.err(), def_bm, ti); } tcx.mk_tup(element_tys_iter) } else { @@ -1051,7 +1051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Occupied(occupied) => { self.error_field_already_bound(span, field.ident, *occupied.get()); no_field_errors = false; - tcx.types.err + tcx.err() } Vacant(vacant) => { vacant.insert(span); @@ -1065,7 +1065,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or_else(|| { inexistent_fields.push(field.ident); no_field_errors = false; - tcx.types.err + tcx.err() }) } }; @@ -1280,7 +1280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_pat(span, expected, box_ty, ti); (box_ty, inner_ty) } else { - (tcx.types.err, tcx.types.err) + (tcx.err(), tcx.err()) }; self.check_pat(&inner, inner_ty, def_bm, ti); box_ty @@ -1326,7 +1326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } else { - (tcx.types.err, tcx.types.err) + (tcx.err(), tcx.err()) }; self.check_pat(&inner, inner_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); rptr_ty @@ -1377,7 +1377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !expected.references_error() { self.error_expected_array_or_slice(span, expected); } - let err = self.tcx.types.err; + let err = self.tcx.err(); (err, Some(err), err) } }; @@ -1444,7 +1444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // If we get here, we must have emitted an error. - (Some(self.tcx.types.err), arr_ty) + (Some(self.tcx.err()), arr_ty) } fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index c5bf151bc1e11..fa89dbe60b3d9 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -212,7 +212,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { e.span, &format!("bad index {:?} for base: `{:?}`", index, base), ); - self.fcx.tcx.types.err + self.fcx.tcx.err() }); let index_ty = self.fcx.resolve_vars_if_possible(&index_ty); @@ -668,7 +668,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); self.report_error(t); self.replaced_with_error = true; - self.tcx().types.err + self.tcx().err() } } } @@ -686,7 +686,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { // FIXME: we'd like to use `self.report_error`, but it doesn't yet // accept a &'tcx ty::Const. self.replaced_with_error = true; - self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty }) + self.tcx().err_const(ct.ty) } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0fad328459890..a71501ea18a42 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -308,7 +308,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { self.tcx().sess.delay_span_bug(span, "bad placeholder type"); - self.tcx().types.err + self.tcx().err() } fn ct_infer( @@ -318,8 +318,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { span: Span, ) -> &'tcx Const<'tcx> { bad_placeholder_type(self.tcx(), vec![span]).emit(); - - self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty }) + self.tcx().err_const(ty) } fn projected_ty_from_poly_trait_ref( @@ -419,7 +418,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { _ => {} } err.emit(); - self.tcx().types.err + self.tcx().err() } } @@ -1473,7 +1472,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { visitor.visit_ty(ty); let mut diag = bad_placeholder_type(tcx, visitor.0); let ret_ty = fn_sig.output(); - if ret_ty != tcx.types.err { + if ret_ty != tcx.err() { diag.span_suggestion( ty.span, "replace with the correct return type", @@ -2032,12 +2031,11 @@ fn associated_item_predicates( // once they are handled by the trait system. ty::GenericParamDefKind::Type { .. } => { unimplemented_error("type"); - tcx.types.err.into() + tcx.err().into() } ty::GenericParamDefKind::Const => { unimplemented_error("const"); - tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: tcx.type_of(param.def_id) }) - .into() + tcx.err_const(tcx.type_of(param.def_id)).into() } } }; diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index cf0e3f9cdf592..03ce83afa8250 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -143,7 +143,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { // Some error in the // owner fn prevented us from populating // the `concrete_opaque_types` table. - tcx.types.err + tcx.err() } else { // We failed to resolve the opaque type or it // resolves to itself. Return the non-revealed @@ -244,7 +244,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { DUMMY_SP, &format!("unexpected const parent path {:?}", parent_node), ); - return tcx.types.err; + return tcx.err(); } }; @@ -284,7 +284,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { res, path, ), ); - return tcx.types.err; + return tcx.err(); } }; @@ -313,7 +313,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { parent_node, res ), ); - tcx.types.err + tcx.err() } } @@ -322,7 +322,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { DUMMY_SP, &format!("unexpected const parent in type_of_def_id(): {:?}", x), ); - tcx.types.err + tcx.err() } } } @@ -591,7 +591,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { None => { let span = tcx.def_span(def_id); tcx.sess.span_err(span, "could not find defining uses"); - tcx.types.err + tcx.err() } } } @@ -624,7 +624,7 @@ fn infer_placeholder_type( } None => { let mut diag = bad_placeholder_type(tcx, vec![span]); - if ty != tcx.types.err { + if ty != tcx.err() { diag.span_suggestion( span, "replace `_` with the correct type",