diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index d0e0203bf8c44..ea3602e8a056a 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -495,8 +495,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Existential { .. } => { + NllRegionVariableOrigin::Existential { .. } => { // For existential, regions, nothing to do. } } @@ -1410,8 +1409,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_bound_universal_region(fr, placeholder, errors_buffer); } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Existential { .. } => { + NllRegionVariableOrigin::Existential { .. } => { // nothing to check here } } @@ -1513,8 +1511,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_bound_universal_region(fr, placeholder, errors_buffer); } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Existential { .. } => { + NllRegionVariableOrigin::Existential { .. } => { // nothing to check here } } @@ -1788,9 +1785,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { universe1.cannot_name(placeholder.universe) } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::FreeRegion - | NllRegionVariableOrigin::Existential { .. } => false, + NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { .. } => { + false + } } } @@ -2152,8 +2149,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let blame_source = match from_region_origin { NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { from_forall: false } => true, - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Placeholder(_) + NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::Existential { from_forall: true } => false, }; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index d129e8454265b..7c1fa28b8dfcc 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,11 +1,20 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::DefId; use rustc_hir::OpaqueTyOrigin; +use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::TyCtxtInferExt as _; +use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; +use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ - self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable, TypeVisitable, + self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable, }; -use rustc_trait_selection::opaque_types::InferCtxtExt; +use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::TraitEngineExt as _; use super::RegionInferenceContext; @@ -173,3 +182,474 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) } } + +pub trait InferCtxtExt<'tcx> { + fn infer_opaque_definition_from_instantiation( + &self, + opaque_type_key: OpaqueTypeKey<'tcx>, + instantiated_ty: OpaqueHiddenType<'tcx>, + origin: OpaqueTyOrigin, + ) -> Ty<'tcx>; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { + /// Given the fully resolved, instantiated type for an opaque + /// type, i.e., the value of an inference variable like C1 or C2 + /// (*), computes the "definition type" for an opaque type + /// definition -- that is, the inferred value of `Foo1<'x>` or + /// `Foo2<'x>` that we would conceptually use in its definition: + /// ```ignore (illustrative) + /// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA + /// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB + /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } + /// ``` + /// Note that these values are defined in terms of a distinct set of + /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main + /// purpose of this function is to do that translation. + /// + /// (*) C1 and C2 were introduced in the comments on + /// `register_member_constraints`. Read that comment for more context. + /// + /// # Parameters + /// + /// - `def_id`, the `impl Trait` type + /// - `substs`, the substs used to instantiate this opaque type + /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of + /// `opaque_defn.concrete_ty` + #[instrument(level = "debug", skip(self))] + fn infer_opaque_definition_from_instantiation( + &self, + opaque_type_key: OpaqueTypeKey<'tcx>, + instantiated_ty: OpaqueHiddenType<'tcx>, + origin: OpaqueTyOrigin, + ) -> Ty<'tcx> { + if self.is_tainted_by_errors() { + return self.tcx.ty_error(); + } + + let OpaqueTypeKey { def_id, substs } = opaque_type_key; + + // Use substs to build up a reverse map from regions to their + // identity mappings. This is necessary because of `impl + // Trait` lifetimes are computed by replacing existing + // lifetimes with 'static and remapping only those used in the + // `impl Trait` return type, resulting in the parameters + // shifting. + let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); + debug!(?id_substs); + let map: FxHashMap, GenericArg<'tcx>> = + substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect(); + debug!("map = {:#?}", map); + + // Convert the type from the function into a type valid outside + // the function, by replacing invalid regions with 'static, + // after producing an error for each of them. + let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new( + self.tcx, + def_id, + map, + instantiated_ty.ty, + instantiated_ty.span, + )); + debug!(?definition_ty); + + if !check_opaque_type_parameter_valid( + self.tcx, + opaque_type_key, + origin, + instantiated_ty.span, + ) { + return self.tcx.ty_error(); + } + + // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` + // on stable and we'd break that. + if let OpaqueTyOrigin::TyAlias = origin { + // This logic duplicates most of `check_opaque_meets_bounds`. + // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. + let param_env = self.tcx.param_env(def_id); + let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()); + self.tcx.infer_ctxt().enter(move |infcx| { + // Require the hidden type to be well-formed with only the generics of the opaque type. + // Defining use functions may have more bounds than the opaque type, which is ok, as long as the + // hidden type is well formed even without those bounds. + let predicate = + ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) + .to_predicate(infcx.tcx); + let mut fulfillment_cx = >::new(infcx.tcx); + + // Require that the hidden type actually fulfills all the bounds of the opaque type, even without + // the bounds that the function supplies. + match infcx.register_hidden_type( + OpaqueTypeKey { def_id, substs: id_substs }, + ObligationCause::misc(instantiated_ty.span, body_id), + param_env, + definition_ty, + origin, + ) { + Ok(infer_ok) => { + for obligation in infer_ok.obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + } + } + Err(err) => { + infcx + .report_mismatched_types( + &ObligationCause::misc(instantiated_ty.span, body_id), + self.tcx.mk_opaque(def_id, id_substs), + definition_ty, + err, + ) + .emit(); + } + } + + fulfillment_cx.register_predicate_obligation( + &infcx, + Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), + ); + + // Check that all obligations are satisfied by the implementation's + // version. + let errors = fulfillment_cx.select_all_or_error(&infcx); + + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + + if errors.is_empty() { + definition_ty + } else { + infcx.report_fulfillment_errors(&errors, None, false); + self.tcx.ty_error() + } + }) + } else { + definition_ty + } + } +} + +fn check_opaque_type_parameter_valid( + tcx: TyCtxt<'_>, + opaque_type_key: OpaqueTypeKey<'_>, + origin: OpaqueTyOrigin, + span: Span, +) -> bool { + match origin { + // No need to check return position impl trait (RPIT) + // because for type and const parameters they are correct + // by construction: we convert + // + // fn foo() -> impl Trait + // + // into + // + // type Foo + // fn foo() -> Foo. + // + // For lifetime parameters we convert + // + // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> + // + // into + // + // type foo::<'p0..'pn>::Foo<'q0..'qm> + // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. + // + // which would error here on all of the `'static` args. + OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, + // Check these + OpaqueTyOrigin::TyAlias => {} + } + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); + let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); + for (i, arg) in opaque_type_key.substs.iter().enumerate() { + let arg_is_param = match arg.unpack() { + GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), + GenericArgKind::Lifetime(lt) if lt.is_static() => { + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_label( + tcx.def_span(opaque_generics.param_at(i, tcx).def_id), + "cannot use static lifetime; use a bound lifetime \ + instead or remove the lifetime parameter from the \ + opaque type", + ) + .emit(); + return false; + } + GenericArgKind::Lifetime(lt) => { + matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) + } + GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), + }; + + if arg_is_param { + seen_params.entry(arg).or_default().push(i); + } else { + // Prevent `fn foo() -> Foo` from being defining. + let opaque_param = opaque_generics.param_at(i, tcx); + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_note( + tcx.def_span(opaque_param.def_id), + &format!( + "used non-generic {} `{}` for generic parameter", + opaque_param.kind.descr(), + arg, + ), + ) + .emit(); + return false; + } + } + + for (_, indices) in seen_params { + if indices.len() > 1 { + let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); + let spans: Vec<_> = indices + .into_iter() + .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) + .collect(); + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_note(spans, &format!("{} used multiple times", descr)) + .emit(); + return false; + } + } + true +} + +struct ReverseMapper<'tcx> { + tcx: TyCtxt<'tcx>, + + opaque_type_def_id: DefId, + map: FxHashMap, GenericArg<'tcx>>, + map_missing_regions_to_empty: bool, + + /// initially `Some`, set to `None` once error has been reported + hidden_ty: Option>, + + /// Span of function being checked. + span: Span, +} + +impl<'tcx> ReverseMapper<'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + opaque_type_def_id: DefId, + map: FxHashMap, GenericArg<'tcx>>, + hidden_ty: Ty<'tcx>, + span: Span, + ) -> Self { + Self { + tcx, + opaque_type_def_id, + map, + map_missing_regions_to_empty: false, + hidden_ty: Some(hidden_ty), + span, + } + } + + fn fold_kind_mapping_missing_regions_to_empty( + &mut self, + kind: GenericArg<'tcx>, + ) -> GenericArg<'tcx> { + assert!(!self.map_missing_regions_to_empty); + self.map_missing_regions_to_empty = true; + let kind = kind.fold_with(self); + self.map_missing_regions_to_empty = false; + kind + } + + fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { + assert!(!self.map_missing_regions_to_empty); + kind.fold_with(self) + } +} + +impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + #[instrument(skip(self), level = "debug")] + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + // Ignore bound regions and `'static` regions that appear in the + // type, we only need to remap regions that reference lifetimes + // from the function declaration. + // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReLateBound(..) | ty::ReStatic => return r, + + // If regions have been erased (by writeback), don't try to unerase + // them. + ty::ReErased => return r, + + // The regions that we expect from borrow checking. + ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} + + ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => { + // All of the regions in the type should either have been + // erased by writeback, or mapped back to named regions by + // borrow checking. + bug!("unexpected region kind in opaque type: {:?}", r); + } + } + + let generics = self.tcx().generics_of(self.opaque_type_def_id); + match self.map.get(&r.into()).map(|k| k.unpack()) { + Some(GenericArgKind::Lifetime(r1)) => r1, + Some(u) => panic!("region mapped to unexpected kind: {:?}", u), + None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty, + None if generics.parent.is_some() => { + if let Some(hidden_ty) = self.hidden_ty.take() { + unexpected_hidden_region_diagnostic( + self.tcx, + self.tcx.def_span(self.opaque_type_def_id), + hidden_ty, + r, + ) + .emit(); + } + self.tcx.lifetimes.re_root_empty + } + None => { + self.tcx + .sess + .struct_span_err(self.span, "non-defining opaque type use in defining scope") + .span_label( + self.span, + format!( + "lifetime `{}` is part of concrete type but not used in \ + parameter list of the `impl Trait` type alias", + r + ), + ) + .emit(); + + self.tcx().lifetimes.re_static + } + } + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match *ty.kind() { + ty::Closure(def_id, substs) => { + // I am a horrible monster and I pray for death. When + // we encounter a closure here, it is always a closure + // from within the function that we are currently + // type-checking -- one that is now being encapsulated + // in an opaque type. Ideally, we would + // go through the types/lifetimes that it references + // and treat them just like we would any other type, + // which means we would error out if we find any + // reference to a type/region that is not in the + // "reverse map". + // + // **However,** in the case of closures, there is a + // somewhat subtle (read: hacky) consideration. The + // problem is that our closure types currently include + // all the lifetime parameters declared on the + // enclosing function, even if they are unused by the + // closure itself. We can't readily filter them out, + // so here we replace those values with `'empty`. This + // can't really make a difference to the rest of the + // compiler; those regions are ignored for the + // outlives relation, and hence don't affect trait + // selection or auto traits, and they are erased + // during codegen. + + let generics = self.tcx.generics_of(def_id); + let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + })); + + self.tcx.mk_closure(def_id, substs) + } + + ty::Generator(def_id, substs, movability) => { + let generics = self.tcx.generics_of(def_id); + let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + })); + + self.tcx.mk_generator(def_id, substs, movability) + } + + ty::Param(param) => { + // Look it up in the substitution list. + match self.map.get(&ty.into()).map(|k| k.unpack()) { + // Found it in the substitution list; replace with the parameter from the + // opaque type. + Some(GenericArgKind::Type(t1)) => t1, + Some(u) => panic!("type mapped to unexpected kind: {:?}", u), + None => { + debug!(?param, ?self.map); + self.tcx + .sess + .struct_span_err( + self.span, + &format!( + "type parameter `{}` is part of concrete type but not \ + used in parameter list for the `impl Trait` type alias", + ty + ), + ) + .emit(); + + self.tcx().ty_error() + } + } + } + + _ => ty.super_fold_with(self), + } + } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + trace!("checking const {:?}", ct); + // Find a const parameter + match ct.kind() { + ty::ConstKind::Param(..) => { + // Look it up in the substitution list. + match self.map.get(&ct.into()).map(|k| k.unpack()) { + // Found it in the substitution list, replace with the parameter from the + // opaque type. + Some(GenericArgKind::Const(c1)) => c1, + Some(u) => panic!("const mapped to unexpected kind: {:?}", u), + None => { + self.tcx + .sess + .struct_span_err( + self.span, + &format!( + "const parameter `{}` is part of concrete type but not \ + used in parameter list for the `impl Trait` type alias", + ct + ), + ) + .emit(); + + self.tcx().const_error(ct.ty()) + } + } + } + + _ => ct, + } + } +} diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 89d84fcf09cfe..2a7713bc4df3b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -503,7 +503,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let root_empty = self .infcx - .next_nll_region_var(NllRegionVariableOrigin::RootEmptyRegion) + .next_nll_region_var(NllRegionVariableOrigin::Existential { from_forall: true }) .to_region_vid(); UniversalRegions { diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6d74e9a9f2b9e..85ea8eb393782 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -63,7 +63,7 @@ impl HumanReadableErrorType { bundle: Option>, fallback_bundle: LazyFallbackBundle, teach: bool, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> EmitterWriter { let (short, color_config) = self.unzip(); @@ -76,7 +76,7 @@ impl HumanReadableErrorType { short, teach, color, - terminal_width, + diagnostic_width, macro_backtrace, ) } @@ -710,7 +710,7 @@ pub struct EmitterWriter { short_message: bool, teach: bool, ui_testing: bool, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, } @@ -730,7 +730,7 @@ impl EmitterWriter { fallback_bundle: LazyFallbackBundle, short_message: bool, teach: bool, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> EmitterWriter { let dst = Destination::from_stderr(color_config); @@ -742,7 +742,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, - terminal_width, + diagnostic_width, macro_backtrace, } } @@ -755,7 +755,7 @@ impl EmitterWriter { short_message: bool, teach: bool, colored: bool, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> EmitterWriter { EmitterWriter { @@ -766,7 +766,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, - terminal_width, + diagnostic_width, macro_backtrace, } } @@ -1615,7 +1615,7 @@ impl EmitterWriter { width_offset + annotated_file.multiline_depth + 1 }; - let column_width = if let Some(width) = self.terminal_width { + let column_width = if let Some(width) = self.diagnostic_width { width.saturating_sub(code_offset) } else if self.ui_testing { DEFAULT_COLUMN_WIDTH diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index d4d1491c16945..b8cd334b4c6c6 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -42,7 +42,7 @@ pub struct JsonEmitter { pretty: bool, ui_testing: bool, json_rendered: HumanReadableErrorType, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, } @@ -54,7 +54,7 @@ impl JsonEmitter { fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { @@ -66,7 +66,7 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, - terminal_width, + diagnostic_width, macro_backtrace, } } @@ -76,7 +76,7 @@ impl JsonEmitter { json_rendered: HumanReadableErrorType, fluent_bundle: Option>, fallback_bundle: LazyFallbackBundle, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> JsonEmitter { let file_path_mapping = FilePathMapping::empty(); @@ -87,7 +87,7 @@ impl JsonEmitter { fallback_bundle, pretty, json_rendered, - terminal_width, + diagnostic_width, macro_backtrace, ) } @@ -100,7 +100,7 @@ impl JsonEmitter { fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, - terminal_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { @@ -112,7 +112,7 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, - terminal_width, + diagnostic_width, macro_backtrace, } } @@ -345,7 +345,7 @@ impl Diagnostic { je.fluent_bundle.clone(), je.fallback_bundle.clone(), false, - je.terminal_width, + je.diagnostic_width, je.macro_backtrace, ) .ui_testing(je.ui_testing) diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index fad949a3bc6a1..d566634a49203 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -4,7 +4,7 @@ //! and use that to decide when one free region outlives another, and so forth. use rustc_data_structures::transitive_relation::TransitiveRelation; -use rustc_middle::ty::{self, Lift, Region, TyCtxt}; +use rustc_middle::ty::{Lift, Region, TyCtxt}; /// Combines a `FreeRegionMap` and a `TyCtxt`. /// @@ -49,7 +49,7 @@ impl<'tcx> FreeRegionMap<'tcx> { // (with the exception that `'static: 'x` is not notable) pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) { debug!("relate_regions(sub={:?}, sup={:?})", sub, sup); - if self.is_free_or_static(sub) && self.is_free(sup) { + if sub.is_free_or_static() && sup.is_free() { self.relation.add(sub, sup) } } @@ -68,7 +68,7 @@ impl<'tcx> FreeRegionMap<'tcx> { r_a: Region<'tcx>, r_b: Region<'tcx>, ) -> bool { - assert!(self.is_free_or_static(r_a) && self.is_free_or_static(r_b)); + assert!(r_a.is_free_or_static() && r_b.is_free_or_static()); let re_static = tcx.lifetimes.re_static; if self.check_relation(re_static, r_b) { // `'a <= 'static` is always true, and not stored in the @@ -85,20 +85,6 @@ impl<'tcx> FreeRegionMap<'tcx> { r_a == r_b || self.relation.contains(r_a, r_b) } - /// True for free regions other than `'static`. - pub fn is_free(&self, r: Region<'_>) -> bool { - matches!(*r, ty::ReEarlyBound(_) | ty::ReFree(_)) - } - - /// True if `r` is a free region or static of the sort that this - /// free region map can be used with. - pub fn is_free_or_static(&self, r: Region<'_>) -> bool { - match *r { - ty::ReStatic => true, - _ => self.is_free(r), - } - } - /// Computes the least-upper-bound of two free regions. In some /// cases, this is more conservative than necessary, in order to /// avoid making arbitrary choices. See @@ -110,8 +96,8 @@ impl<'tcx> FreeRegionMap<'tcx> { r_b: Region<'tcx>, ) -> Region<'tcx> { debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b); - assert!(self.is_free(r_a)); - assert!(self.is_free(r_b)); + assert!(r_a.is_free()); + assert!(r_b.is_free()); let result = if r_a == r_b { r_a } else { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 87fa22b3835ef..3783cfb4cc5c8 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -47,7 +47,6 @@ pub(crate) fn resolve<'tcx>( #[derive(Clone)] pub struct LexicalRegionResolutions<'tcx> { pub(crate) values: IndexVec>, - pub(crate) error_region: ty::Region<'tcx>, } #[derive(Copy, Clone, Debug)] @@ -140,7 +139,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// empty region. The `expansion` phase will grow this larger. fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> { LexicalRegionResolutions { - error_region: tcx.lifetimes.re_static, values: IndexVec::from_fn_n( |vid| { let vid_universe = self.var_infos[vid].universe; @@ -310,7 +308,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // Check for the case where we know that `'b: 'static` -- in that case, // `a <= b` for all `a`. - let b_free_or_static = self.region_rels.free_regions.is_free_or_static(b); + let b_free_or_static = b.is_free_or_static(); if b_free_or_static && sub_free_regions(tcx.lifetimes.re_static, b) { return true; } @@ -320,7 +318,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // `lub` relationship defined below, since sometimes the "lub" // is actually the `postdom_upper_bound` (see // `TransitiveRelation` for more details). - let a_free_or_static = self.region_rels.free_regions.is_free_or_static(a); + let a_free_or_static = a.is_free_or_static(); if a_free_or_static && b_free_or_static { return sub_free_regions(a, b); } @@ -864,10 +862,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { where T: TypeFoldable<'tcx>, { - tcx.fold_regions(value, |r, _db| match *r { - ty::ReVar(rid) => self.resolve_var(rid), - _ => r, - }) + tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r)) } fn value(&self, rid: RegionVid) -> &VarValue<'tcx> { @@ -878,12 +873,19 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { &mut self.values[rid] } - pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> { - let result = match self.values[rid] { - VarValue::Value(r) => r, - VarValue::ErrorValue => self.error_region, + pub(crate) fn resolve_region( + &self, + tcx: TyCtxt<'tcx>, + r: ty::Region<'tcx>, + ) -> ty::Region<'tcx> { + let result = match *r { + ty::ReVar(rid) => match self.values[rid] { + VarValue::Value(r) => r, + VarValue::ErrorValue => tcx.lifetimes.re_static, + }, + _ => r, }; - debug!("resolve_var({:?}) = {:?}", rid, result); + debug!("resolve_region({:?}) = {:?}", r, result); result } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 991fd23ab4344..6e0f2d687437b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -466,9 +466,6 @@ pub enum NllRegionVariableOrigin { /// from a `for<'a> T` binder). Meant to represent "any region". Placeholder(ty::PlaceholderRegion), - /// The variable we create to represent `'empty(U0)`. - RootEmptyRegion, - Existential { /// If this is true, then this variable was created to represent a lifetime /// bound in a `for` binder. For example, it might have been created to @@ -1250,7 +1247,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let lexical_region_resolutions = LexicalRegionResolutions { - error_region: self.tcx.lifetimes.re_static, values: rustc_index::vec::IndexVec::from_elem_n( crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), var_infos.len(), diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index a614568742920..3d99f0958f7f9 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -206,13 +206,13 @@ impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { match *r { - ty::ReVar(rid) => Ok(self + ty::ReVar(_) => Ok(self .infcx .lexical_region_resolutions .borrow() .as_ref() .expect("region resolution not performed") - .resolve_var(rid)), + .resolve_region(self.infcx.tcx, r)), _ => Ok(r), } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 30a29ed6ed38f..81145416437b7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -689,7 +689,6 @@ fn test_debugging_options_tracking_hash() { untracked!(span_debug, true); untracked!(span_free_formats, true); untracked!(temps_dir, Some(String::from("abc"))); - untracked!(terminal_width, Some(80)); untracked!(threads, 99); untracked!(time, true); untracked!(time_llvm_passes, true); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9368612810198..f136b8e236824 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1048,6 +1048,8 @@ impl BasicBlock { /////////////////////////////////////////////////////////////////////////// // BasicBlockData +/// Data for a basic block, including a list of its statements. +/// /// See [`BasicBlock`] for documentation on what basic blocks are at a high level. #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct BasicBlockData<'tcx> { @@ -1079,7 +1081,7 @@ impl<'tcx> BasicBlockData<'tcx> { /// Accessor for terminator. /// /// Terminator may not be None after construction of the basic block is complete. This accessor - /// provides a convenience way to reach the terminator. + /// provides a convenient way to reach the terminator. #[inline] pub fn terminator(&self) -> &Terminator<'tcx> { self.terminator.as_ref().expect("invalid terminator state") @@ -1286,6 +1288,7 @@ impl fmt::Debug for AssertKind { /////////////////////////////////////////////////////////////////////////// // Statements +/// A statement in a basic block, including information about its source code. #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Statement<'tcx> { pub source_info: SourceInfo, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 815e39aab5715..03e4319bbf1a8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1570,6 +1570,19 @@ impl<'tcx> Region<'tcx> { _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), } } + + /// True for free regions other than `'static`. + pub fn is_free(self) -> bool { + matches!(*self, ty::ReEarlyBound(_) | ty::ReFree(_)) + } + + /// True if `self` is a free region or static. + pub fn is_free_or_static(self) -> bool { + match *self { + ty::ReStatic => true, + _ => self.is_free(), + } + } } /// Type utilities diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 2c43563b10474..f9387e29262ae 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1393,7 +1393,9 @@ impl<'a> Parser<'a> { self.parse_yield_expr(attrs) } else if self.is_do_yeet() { self.parse_yeet_expr(attrs) - } else if self.eat_keyword(kw::Let) { + } else if self.check_keyword(kw::Let) { + self.manage_let_chains_context(); + self.bump(); self.parse_let_expr(attrs) } else if self.eat_keyword(kw::Underscore) { Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) @@ -2355,16 +2357,30 @@ impl<'a> Parser<'a> { Ok(cond) } + // Checks if `let` is in an invalid position like `let x = let y = 1;` or + // if the current `let` is in a let_chains context but nested in another + // expression like `if let Some(_) = _opt && [1, 2, 3][let _ = ()] = 1`. + // + // This method expects that the current token is `let`. + fn manage_let_chains_context(&mut self) { + debug_assert!(matches!(self.token.kind, TokenKind::Ident(kw::Let, _))); + let is_in_a_let_chains_context_but_nested_in_other_expr = self.let_expr_allowed + && !matches!( + self.prev_token.kind, + TokenKind::AndAnd + | TokenKind::CloseDelim(Delimiter::Brace) + | TokenKind::Ident(kw::If, _) + | TokenKind::Ident(kw::While, _) + ); + if !self.let_expr_allowed || is_in_a_let_chains_context_but_nested_in_other_expr { + self.struct_span_err(self.token.span, "expected expression, found `let` statement") + .emit(); + } + } + /// Parses a `let $pat = $expr` pseudo-expression. /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { - if !self.let_expr_allowed { - self.struct_span_err( - self.prev_token.span, - "expected expression, found `let` statement", - ) - .emit(); - } let lo = self.prev_token.span; let pat = self.parse_pat_allow_top_alt( None, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e7717f1367cb0..b7da0f229420b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -726,6 +726,7 @@ impl Default for Options { prints: Vec::new(), cg: Default::default(), error_format: ErrorOutputType::default(), + diagnostic_width: None, externs: Externs(BTreeMap::new()), crate_name: None, libs: Vec::new(), @@ -1427,6 +1428,12 @@ pub fn rustc_optgroups() -> Vec { never = never colorize output", "auto|always|never", ), + opt::opt_s( + "", + "diagnostic-width", + "Inform rustc of the width of the output so that diagnostics can be truncated to fit", + "WIDTH", + ), opt::multi_s( "", "remap-path-prefix", @@ -2202,6 +2209,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let error_format = parse_error_format(matches, color, json_rendered); + let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { + early_error(error_format, "`--diagnostic-width` must be an positive integer"); + }); + let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) .unwrap_or_else(|e| early_error(error_format, &e)); @@ -2474,6 +2485,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { prints, cg, error_format, + diagnostic_width, externs, unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), crate_name, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index be70ea5d5e480..b0c74ffb6dcc1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -170,6 +170,7 @@ top_level_options!( test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], + diagnostic_width: Option [UNTRACKED], /// If `Some`, enable incremental compilation, using the given /// directory to store intermediate results. @@ -1388,6 +1389,8 @@ options! { "panic strategy for out-of-memory handling"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], "pass `-install_name @rpath/...` to the macOS linker (default: no)"), + diagnostic_width: Option = (None, parse_opt_number, [UNTRACKED], + "set the current output width for diagnostic truncation"), panic_abort_tests: bool = (false, parse_bool, [TRACKED], "support compiling tests with panic=abort (default: no)"), panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED], @@ -1514,8 +1517,6 @@ options! { "show extended diagnostic help (default: no)"), temps_dir: Option = (None, parse_opt_string, [UNTRACKED], "the directory the intermediate files are written to"), - terminal_width: Option = (None, parse_opt_number, [UNTRACKED], - "set the current terminal width"), // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved // alongside query results and changes to translation options can affect diagnostics - so // translation options should be tracked. diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 2a5ddd4e9e420..52b9ee9471802 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1162,7 +1162,7 @@ fn default_emitter( fallback_bundle, short, sopts.debugging_opts.teach, - sopts.debugging_opts.terminal_width, + sopts.diagnostic_width, macro_backtrace, ), Some(dst) => EmitterWriter::new( @@ -1173,7 +1173,7 @@ fn default_emitter( short, false, // no teach messages when writing to a buffer false, // no colors when writing to a buffer - None, // no terminal width + None, // no diagnostic width macro_backtrace, ), }; @@ -1188,7 +1188,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.debugging_opts.terminal_width, + sopts.diagnostic_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), @@ -1202,7 +1202,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.debugging_opts.terminal_width, + sopts.diagnostic_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 44ff3fd73061e..282ee632ce581 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -37,5 +37,4 @@ extern crate smallvec; pub mod autoderef; pub mod infer; -pub mod opaque_types; pub mod traits; diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs deleted file mode 100644 index d290f7b074cb5..0000000000000 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ /dev/null @@ -1,545 +0,0 @@ -use crate::traits; -use crate::traits::error_reporting::InferCtxtExt as _; -use crate::traits::TraitEngineExt as _; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::DefId; -use rustc_hir::OpaqueTyOrigin; -use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt as _}; -use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; -use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt}; -use rustc_span::Span; - -pub trait InferCtxtExt<'tcx> { - fn infer_opaque_definition_from_instantiation( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - instantiated_ty: OpaqueHiddenType<'tcx>, - origin: OpaqueTyOrigin, - ) -> Ty<'tcx>; -} - -impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { - /// Given the fully resolved, instantiated type for an opaque - /// type, i.e., the value of an inference variable like C1 or C2 - /// (*), computes the "definition type" for an opaque type - /// definition -- that is, the inferred value of `Foo1<'x>` or - /// `Foo2<'x>` that we would conceptually use in its definition: - /// ```ignore (illustrative) - /// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA - /// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB - /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } - /// ``` - /// Note that these values are defined in terms of a distinct set of - /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main - /// purpose of this function is to do that translation. - /// - /// (*) C1 and C2 were introduced in the comments on - /// `register_member_constraints`. Read that comment for more context. - /// - /// # Parameters - /// - /// - `def_id`, the `impl Trait` type - /// - `substs`, the substs used to instantiate this opaque type - /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of - /// `opaque_defn.concrete_ty` - #[instrument(level = "debug", skip(self))] - fn infer_opaque_definition_from_instantiation( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - instantiated_ty: OpaqueHiddenType<'tcx>, - origin: OpaqueTyOrigin, - ) -> Ty<'tcx> { - if self.is_tainted_by_errors() { - return self.tcx.ty_error(); - } - - let OpaqueTypeKey { def_id, substs } = opaque_type_key; - - // Use substs to build up a reverse map from regions to their - // identity mappings. This is necessary because of `impl - // Trait` lifetimes are computed by replacing existing - // lifetimes with 'static and remapping only those used in the - // `impl Trait` return type, resulting in the parameters - // shifting. - let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); - debug!(?id_substs); - let map: FxHashMap, GenericArg<'tcx>> = - substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect(); - debug!("map = {:#?}", map); - - // Convert the type from the function into a type valid outside - // the function, by replacing invalid regions with 'static, - // after producing an error for each of them. - let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new( - self.tcx, - def_id, - map, - instantiated_ty.ty, - instantiated_ty.span, - )); - debug!(?definition_ty); - - if !check_opaque_type_parameter_valid( - self.tcx, - opaque_type_key, - origin, - instantiated_ty.span, - ) { - return self.tcx.ty_error(); - } - - // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` - // on stable and we'd break that. - if let OpaqueTyOrigin::TyAlias = origin { - // This logic duplicates most of `check_opaque_meets_bounds`. - // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. - let param_env = self.tcx.param_env(def_id); - let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()); - self.tcx.infer_ctxt().enter(move |infcx| { - // Require the hidden type to be well-formed with only the generics of the opaque type. - // Defining use functions may have more bounds than the opaque type, which is ok, as long as the - // hidden type is well formed even without those bounds. - let predicate = - ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) - .to_predicate(infcx.tcx); - let mut fulfillment_cx = >::new(infcx.tcx); - - // Require that the hidden type actually fulfills all the bounds of the opaque type, even without - // the bounds that the function supplies. - match infcx.register_hidden_type( - OpaqueTypeKey { def_id, substs: id_substs }, - ObligationCause::misc(instantiated_ty.span, body_id), - param_env, - definition_ty, - origin, - ) { - Ok(infer_ok) => { - for obligation in infer_ok.obligations { - fulfillment_cx.register_predicate_obligation(&infcx, obligation); - } - } - Err(err) => { - infcx - .report_mismatched_types( - &ObligationCause::misc(instantiated_ty.span, body_id), - self.tcx.mk_opaque(def_id, id_substs), - definition_ty, - err, - ) - .emit(); - } - } - - fulfillment_cx.register_predicate_obligation( - &infcx, - Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), - ); - - // Check that all obligations are satisfied by the implementation's - // version. - let errors = fulfillment_cx.select_all_or_error(&infcx); - - let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - - if errors.is_empty() { - definition_ty - } else { - infcx.report_fulfillment_errors(&errors, None, false); - self.tcx.ty_error() - } - }) - } else { - definition_ty - } - } -} - -fn check_opaque_type_parameter_valid( - tcx: TyCtxt<'_>, - opaque_type_key: OpaqueTypeKey<'_>, - origin: OpaqueTyOrigin, - span: Span, -) -> bool { - match origin { - // No need to check return position impl trait (RPIT) - // because for type and const parameters they are correct - // by construction: we convert - // - // fn foo() -> impl Trait - // - // into - // - // type Foo - // fn foo() -> Foo. - // - // For lifetime parameters we convert - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. - // - // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, - // Check these - OpaqueTyOrigin::TyAlias => {} - } - let opaque_generics = tcx.generics_of(opaque_type_key.def_id); - let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); - for (i, arg) in opaque_type_key.substs.iter().enumerate() { - let arg_is_param = match arg.unpack() { - GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - GenericArgKind::Lifetime(lt) if lt.is_static() => { - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_label( - tcx.def_span(opaque_generics.param_at(i, tcx).def_id), - "cannot use static lifetime; use a bound lifetime \ - instead or remove the lifetime parameter from the \ - opaque type", - ) - .emit(); - return false; - } - GenericArgKind::Lifetime(lt) => { - matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) - } - GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), - }; - - if arg_is_param { - seen_params.entry(arg).or_default().push(i); - } else { - // Prevent `fn foo() -> Foo` from being defining. - let opaque_param = opaque_generics.param_at(i, tcx); - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note( - tcx.def_span(opaque_param.def_id), - &format!( - "used non-generic {} `{}` for generic parameter", - opaque_param.kind.descr(), - arg, - ), - ) - .emit(); - return false; - } - } - - for (_, indices) in seen_params { - if indices.len() > 1 { - let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); - let spans: Vec<_> = indices - .into_iter() - .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) - .collect(); - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note(spans, &format!("{} used multiple times", descr)) - .emit(); - return false; - } - } - true -} - -struct ReverseMapper<'tcx> { - tcx: TyCtxt<'tcx>, - - opaque_type_def_id: DefId, - map: FxHashMap, GenericArg<'tcx>>, - map_missing_regions_to_empty: bool, - - /// initially `Some`, set to `None` once error has been reported - hidden_ty: Option>, - - /// Span of function being checked. - span: Span, -} - -impl<'tcx> ReverseMapper<'tcx> { - fn new( - tcx: TyCtxt<'tcx>, - opaque_type_def_id: DefId, - map: FxHashMap, GenericArg<'tcx>>, - hidden_ty: Ty<'tcx>, - span: Span, - ) -> Self { - Self { - tcx, - opaque_type_def_id, - map, - map_missing_regions_to_empty: false, - hidden_ty: Some(hidden_ty), - span, - } - } - - fn fold_kind_mapping_missing_regions_to_empty( - &mut self, - kind: GenericArg<'tcx>, - ) -> GenericArg<'tcx> { - assert!(!self.map_missing_regions_to_empty); - self.map_missing_regions_to_empty = true; - let kind = kind.fold_with(self); - self.map_missing_regions_to_empty = false; - kind - } - - fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { - assert!(!self.map_missing_regions_to_empty); - kind.fold_with(self) - } -} - -impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - #[instrument(skip(self), level = "debug")] - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - // Ignore bound regions and `'static` regions that appear in the - // type, we only need to remap regions that reference lifetimes - // from the function declaration. - // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | ty::ReStatic => return r, - - // If regions have been erased (by writeback), don't try to unerase - // them. - ty::ReErased => return r, - - // The regions that we expect from borrow checking. - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} - - ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => { - // All of the regions in the type should either have been - // erased by writeback, or mapped back to named regions by - // borrow checking. - bug!("unexpected region kind in opaque type: {:?}", r); - } - } - - let generics = self.tcx().generics_of(self.opaque_type_def_id); - match self.map.get(&r.into()).map(|k| k.unpack()) { - Some(GenericArgKind::Lifetime(r1)) => r1, - Some(u) => panic!("region mapped to unexpected kind: {:?}", u), - None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty, - None if generics.parent.is_some() => { - if let Some(hidden_ty) = self.hidden_ty.take() { - unexpected_hidden_region_diagnostic( - self.tcx, - self.tcx.def_span(self.opaque_type_def_id), - hidden_ty, - r, - ) - .emit(); - } - self.tcx.lifetimes.re_root_empty - } - None => { - self.tcx - .sess - .struct_span_err(self.span, "non-defining opaque type use in defining scope") - .span_label( - self.span, - format!( - "lifetime `{}` is part of concrete type but not used in \ - parameter list of the `impl Trait` type alias", - r - ), - ) - .emit(); - - self.tcx().lifetimes.re_static - } - } - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Closure(def_id, substs) => { - // I am a horrible monster and I pray for death. When - // we encounter a closure here, it is always a closure - // from within the function that we are currently - // type-checking -- one that is now being encapsulated - // in an opaque type. Ideally, we would - // go through the types/lifetimes that it references - // and treat them just like we would any other type, - // which means we would error out if we find any - // reference to a type/region that is not in the - // "reverse map". - // - // **However,** in the case of closures, there is a - // somewhat subtle (read: hacky) consideration. The - // problem is that our closure types currently include - // all the lifetime parameters declared on the - // enclosing function, even if they are unused by the - // closure itself. We can't readily filter them out, - // so here we replace those values with `'empty`. This - // can't really make a difference to the rest of the - // compiler; those regions are ignored for the - // outlives relation, and hence don't affect trait - // selection or auto traits, and they are erased - // during codegen. - - let generics = self.tcx.generics_of(def_id); - let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { - if index < generics.parent_count { - // Accommodate missing regions in the parent kinds... - self.fold_kind_mapping_missing_regions_to_empty(kind) - } else { - // ...but not elsewhere. - self.fold_kind_normally(kind) - } - })); - - self.tcx.mk_closure(def_id, substs) - } - - ty::Generator(def_id, substs, movability) => { - let generics = self.tcx.generics_of(def_id); - let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { - if index < generics.parent_count { - // Accommodate missing regions in the parent kinds... - self.fold_kind_mapping_missing_regions_to_empty(kind) - } else { - // ...but not elsewhere. - self.fold_kind_normally(kind) - } - })); - - self.tcx.mk_generator(def_id, substs, movability) - } - - ty::Param(param) => { - // Look it up in the substitution list. - match self.map.get(&ty.into()).map(|k| k.unpack()) { - // Found it in the substitution list; replace with the parameter from the - // opaque type. - Some(GenericArgKind::Type(t1)) => t1, - Some(u) => panic!("type mapped to unexpected kind: {:?}", u), - None => { - debug!(?param, ?self.map); - self.tcx - .sess - .struct_span_err( - self.span, - &format!( - "type parameter `{}` is part of concrete type but not \ - used in parameter list for the `impl Trait` type alias", - ty - ), - ) - .emit(); - - self.tcx().ty_error() - } - } - } - - _ => ty.super_fold_with(self), - } - } - - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - trace!("checking const {:?}", ct); - // Find a const parameter - match ct.kind() { - ty::ConstKind::Param(..) => { - // Look it up in the substitution list. - match self.map.get(&ct.into()).map(|k| k.unpack()) { - // Found it in the substitution list, replace with the parameter from the - // opaque type. - Some(GenericArgKind::Const(c1)) => c1, - Some(u) => panic!("const mapped to unexpected kind: {:?}", u), - None => { - self.tcx - .sess - .struct_span_err( - self.span, - &format!( - "const parameter `{}` is part of concrete type but not \ - used in parameter list for the `impl Trait` type alias", - ct - ), - ) - .emit(); - - self.tcx().const_error(ct.ty()) - } - } - } - - _ => ct, - } - } -} - -/// Given a set of predicates that apply to an object type, returns -/// the region bounds that the (erased) `Self` type must -/// outlive. Precisely *because* the `Self` type is erased, the -/// parameter `erased_self_ty` must be supplied to indicate what type -/// has been used to represent `Self` in the predicates -/// themselves. This should really be a unique type; `FreshTy(0)` is a -/// popular choice. -/// -/// N.B., in some cases, particularly around higher-ranked bounds, -/// this function returns a kind of conservative approximation. -/// That is, all regions returned by this function are definitely -/// required, but there may be other region bounds that are not -/// returned, as well as requirements like `for<'a> T: 'a`. -/// -/// Requires that trait definitions have been processed so that we can -/// elaborate predicates and walk supertraits. -#[instrument(skip(tcx, predicates), level = "debug")] -pub(crate) fn required_region_bounds<'tcx>( - tcx: TyCtxt<'tcx>, - erased_self_ty: Ty<'tcx>, - predicates: impl Iterator>, -) -> Vec> { - assert!(!erased_self_ty.has_escaping_bound_vars()); - - traits::elaborate_predicates(tcx, predicates) - .filter_map(|obligation| { - debug!(?obligation); - match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Projection(..) - | ty::PredicateKind::Trait(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::WellFormed(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::RegionOutlives(..) - | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { - // Search for a bound of the form `erased_self_ty - // : 'a`, but be wary of something like `for<'a> - // erased_self_ty : 'a` (we interpret a - // higher-ranked bound like that as 'static, - // though at present the code in `fulfill.rs` - // considers such bounds to be unsatisfiable, so - // it's kind of a moot point since you could never - // construct such an object, but this seems - // correct even if that code changes). - if t == &erased_self_ty && !r.has_escaping_bound_vars() { - Some(*r) - } else { - None - } - } - } - }) - .collect() -} diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d43b3c9091fc6..3dfc7a9cacd97 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1,5 +1,4 @@ use crate::infer::InferCtxt; -use crate::opaque_types::required_region_bounds; use crate::traits; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -810,3 +809,63 @@ pub fn object_region_bounds<'tcx>( required_region_bounds(tcx, open_ty, predicates) } + +/// Given a set of predicates that apply to an object type, returns +/// the region bounds that the (erased) `Self` type must +/// outlive. Precisely *because* the `Self` type is erased, the +/// parameter `erased_self_ty` must be supplied to indicate what type +/// has been used to represent `Self` in the predicates +/// themselves. This should really be a unique type; `FreshTy(0)` is a +/// popular choice. +/// +/// N.B., in some cases, particularly around higher-ranked bounds, +/// this function returns a kind of conservative approximation. +/// That is, all regions returned by this function are definitely +/// required, but there may be other region bounds that are not +/// returned, as well as requirements like `for<'a> T: 'a`. +/// +/// Requires that trait definitions have been processed so that we can +/// elaborate predicates and walk supertraits. +#[instrument(skip(tcx, predicates), level = "debug")] +pub(crate) fn required_region_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + erased_self_ty: Ty<'tcx>, + predicates: impl Iterator>, +) -> Vec> { + assert!(!erased_self_ty.has_escaping_bound_vars()); + + traits::elaborate_predicates(tcx, predicates) + .filter_map(|obligation| { + debug!(?obligation); + match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Projection(..) + | ty::PredicateKind::Trait(..) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::RegionOutlives(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { + // Search for a bound of the form `erased_self_ty + // : 'a`, but be wary of something like `for<'a> + // erased_self_ty : 'a` (we interpret a + // higher-ranked bound like that as 'static, + // though at present the code in `fulfill.rs` + // considers such bounds to be unsatisfiable, so + // it's kind of a moot point since you could never + // construct such an object, but this seems + // correct even if that code changes). + if t == &erased_self_ty && !r.has_escaping_bound_vars() { + Some(*r) + } else { + None + } + } + } + }) + .collect() +} diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs index ad9e80e117f1e..649b433877222 100644 --- a/library/core/src/future/into_future.rs +++ b/library/core/src/future/into_future.rs @@ -13,8 +13,6 @@ use crate::future::Future; /// on all futures. /// /// ```no_run -/// #![feature(into_future)] -/// /// use std::future::IntoFuture; /// /// # async fn foo() { @@ -33,8 +31,6 @@ use crate::future::Future; /// multiple times before being `.await`ed. /// /// ```rust -/// #![feature(into_future)] -/// /// use std::future::{ready, Ready, IntoFuture}; /// /// /// Eventually multiply two numbers @@ -91,8 +87,6 @@ use crate::future::Future; /// `IntoFuture::into_future` to obtain an instance of `Future`: /// /// ```rust -/// #![feature(into_future)] -/// /// use std::future::IntoFuture; /// /// /// Convert the output of a future to a string. @@ -104,14 +98,14 @@ use crate::future::Future; /// format!("{:?}", fut.await) /// } /// ``` -#[unstable(feature = "into_future", issue = "67644")] +#[stable(feature = "into_future", since = "1.64.0")] pub trait IntoFuture { /// The output that the future will produce on completion. - #[unstable(feature = "into_future", issue = "67644")] + #[stable(feature = "into_future", since = "1.64.0")] type Output; /// Which kind of future are we turning this into? - #[unstable(feature = "into_future", issue = "67644")] + #[stable(feature = "into_future", since = "1.64.0")] type IntoFuture: Future; /// Creates a future from a value. @@ -121,8 +115,6 @@ pub trait IntoFuture { /// Basic usage: /// /// ```no_run - /// #![feature(into_future)] - /// /// use std::future::IntoFuture; /// /// # async fn foo() { @@ -131,12 +123,12 @@ pub trait IntoFuture { /// assert_eq!("meow", fut.await); /// # } /// ``` - #[unstable(feature = "into_future", issue = "67644")] + #[stable(feature = "into_future", since = "1.64.0")] #[lang = "into_future"] fn into_future(self) -> Self::IntoFuture; } -#[unstable(feature = "into_future", issue = "67644")] +#[stable(feature = "into_future", since = "1.64.0")] impl IntoFuture for F { type Output = F::Output; type IntoFuture = F; diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 9b89f766c67bf..90eecb9d4a000 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -29,7 +29,7 @@ pub use self::future::Future; #[unstable(feature = "future_join", issue = "91642")] pub use self::join::join; -#[unstable(feature = "into_future", issue = "67644")] +#[stable(feature = "into_future", since = "1.64.0")] pub use into_future::IntoFuture; #[stable(feature = "future_readiness_fns", since = "1.48.0")] diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 7ec6eb0be6527..272188f82994c 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -73,6 +73,8 @@ pub(crate) struct Options { pub(crate) proc_macro_crate: bool, /// How to format errors and warnings. pub(crate) error_format: ErrorOutputType, + /// Width of output buffer to truncate errors appropriately. + pub(crate) diagnostic_width: Option, /// Library search paths to hand to the compiler. pub(crate) libs: Vec, /// Library search paths strings to hand to the compiler. @@ -331,11 +333,12 @@ impl Options { let config::JsonConfig { json_rendered, json_unused_externs, .. } = config::parse_json(matches); let error_format = config::parse_error_format(matches, color, json_rendered); + let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default(); let codegen_options = CodegenOptions::build(matches, error_format); let debugging_opts = DebuggingOptions::build(matches, error_format); - let diag = new_handler(error_format, None, &debugging_opts); + let diag = new_handler(error_format, None, diagnostic_width, &debugging_opts); // check for deprecated options check_deprecated_options(matches, &diag); @@ -699,6 +702,7 @@ impl Options { input, proc_macro_crate, error_format, + diagnostic_width, libs, lib_strs, externs, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 51b245e36ba3b..8c494ee28cc1f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -154,6 +154,7 @@ impl<'tcx> DocContext<'tcx> { pub(crate) fn new_handler( error_format: ErrorOutputType, source_map: Option>, + diagnostic_width: Option, debugging_opts: &DebuggingOptions, ) -> rustc_errors::Handler { let fallback_bundle = @@ -169,7 +170,7 @@ pub(crate) fn new_handler( fallback_bundle, short, debugging_opts.teach, - debugging_opts.terminal_width, + diagnostic_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -187,7 +188,7 @@ pub(crate) fn new_handler( fallback_bundle, pretty, json_rendered, - debugging_opts.terminal_width, + diagnostic_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -208,6 +209,7 @@ pub(crate) fn create_config( crate_name, proc_macro_crate, error_format, + diagnostic_width, libs, externs, mut cfgs, @@ -266,6 +268,7 @@ pub(crate) fn create_config( actually_rustdoc: true, debugging_opts, error_format, + diagnostic_width, edition, describe_lints, crate_name, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ded3d9951bd35..0d3ec7ecb6448 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -462,6 +462,14 @@ fn opts() -> Vec { "human|json|short", ) }), + unstable("diagnostic-width", |o| { + o.optopt( + "", + "diagnostic-width", + "Provide width of the output for truncated error messages", + "WIDTH", + ) + }), stable("json", |o| { o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") }), @@ -733,7 +741,12 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } fn main_options(options: config::Options) -> MainResult { - let diag = core::new_handler(options.error_format, None, &options.debugging_opts); + let diag = core::new_handler( + options.error_format, + None, + options.diagnostic_width, + &options.debugging_opts, + ); match (options.should_test, options.markdown_input()) { (true, true) => return wrap_return(&diag, markdown::test(options)), diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout index 6d16fe5673bc1..08877af928657 100644 --- a/src/test/run-make/issue-88756-default-output/output-default.stdout +++ b/src/test/run-make/issue-88756-default-output/output-default.stdout @@ -110,6 +110,9 @@ Options: never = never colorize output --error-format human|json|short How errors and other messages are produced + --diagnostic-width WIDTH + Provide width of the output for truncated error + messages --json CONFIG Configure the structure of JSON diagnostics --disable-minification Disable minification applied on JS files diff --git a/src/test/rustdoc-ui/diagnostic-width.rs b/src/test/rustdoc-ui/diagnostic-width.rs new file mode 100644 index 0000000000000..61961d5ec710e --- /dev/null +++ b/src/test/rustdoc-ui/diagnostic-width.rs @@ -0,0 +1,5 @@ +// compile-flags: -Zunstable-options --diagnostic-width=10 +#![deny(rustdoc::bare_urls)] + +/// This is a long line that contains a http://link.com +pub struct Foo; //~^ ERROR diff --git a/src/test/rustdoc-ui/diagnostic-width.stderr b/src/test/rustdoc-ui/diagnostic-width.stderr new file mode 100644 index 0000000000000..fed049d2b37bc --- /dev/null +++ b/src/test/rustdoc-ui/diagnostic-width.stderr @@ -0,0 +1,15 @@ +error: this URL is not a hyperlink + --> $DIR/diagnostic-width.rs:4:41 + | +LL | ... a http://link.com + | ^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | +note: the lint level is defined here + --> $DIR/diagnostic-width.rs:2:9 + | +LL | ...ny(rustdoc::bare_url... + | ^^^^^^^^^^^^^^^^^^ + = note: bare URLs are not automatically turned into clickable links + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/await-into-future.rs b/src/test/ui/async-await/await-into-future.rs index 6e1b155e181ee..8bf1385b3c5cd 100644 --- a/src/test/ui/async-await/await-into-future.rs +++ b/src/test/ui/async-await/await-into-future.rs @@ -1,8 +1,6 @@ // run-pass // aux-build: issue-72470-lib.rs // edition:2021 -#![feature(into_future)] - extern crate issue_72470_lib; use std::{future::{Future, IntoFuture}, pin::Pin}; diff --git a/src/test/ui/diagnostic-width/flag-human.rs b/src/test/ui/diagnostic-width/flag-human.rs new file mode 100644 index 0000000000000..289bfbabd949b --- /dev/null +++ b/src/test/ui/diagnostic-width/flag-human.rs @@ -0,0 +1,9 @@ +// compile-flags: --diagnostic-width=20 + +// This test checks that `-Z output-width` effects the human error output by restricting it to an +// arbitrarily low value so that the effect is visible. + +fn main() { + let _: () = 42; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/flag-human.stderr b/src/test/ui/diagnostic-width/flag-human.stderr similarity index 100% rename from src/test/ui/terminal-width/flag-human.stderr rename to src/test/ui/diagnostic-width/flag-human.stderr diff --git a/src/test/ui/diagnostic-width/flag-json.rs b/src/test/ui/diagnostic-width/flag-json.rs new file mode 100644 index 0000000000000..51a1fb447c7d2 --- /dev/null +++ b/src/test/ui/diagnostic-width/flag-json.rs @@ -0,0 +1,9 @@ +// compile-flags: --diagnostic-width=20 --error-format=json + +// This test checks that `-Z output-width` effects the JSON error output by restricting it to an +// arbitrarily low value so that the effect is visible. + +fn main() { + let _: () = 42; + //~^ ERROR arguments to this function are incorrect +} diff --git a/src/test/ui/terminal-width/flag-json.stderr b/src/test/ui/diagnostic-width/flag-json.stderr similarity index 93% rename from src/test/ui/terminal-width/flag-json.stderr rename to src/test/ui/diagnostic-width/flag-json.stderr index 93c246cb3f501..b21391d1640ef 100644 --- a/src/test/ui/terminal-width/flag-json.stderr +++ b/src/test/ui/diagnostic-width/flag-json.stderr @@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":244,"byte_end":246,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":239,"byte_end":241,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":243,"byte_end":245,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":238,"byte_end":240,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types --> $DIR/flag-json.rs:7:17 | LL | ..._: () = 42; diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs b/src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs similarity index 100% rename from src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs rename to src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr similarity index 100% rename from src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr rename to src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs b/src/test/ui/diagnostic-width/non-whitespace-trimming-2.rs similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-2.rs rename to src/test/ui/diagnostic-width/non-whitespace-trimming-2.rs diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr b/src/test/ui/diagnostic-width/non-whitespace-trimming-2.stderr similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-2.stderr rename to src/test/ui/diagnostic-width/non-whitespace-trimming-2.stderr diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs b/src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.rs similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs rename to src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.rs diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr b/src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr rename to src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.rs b/src/test/ui/diagnostic-width/non-whitespace-trimming.rs similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming.rs rename to src/test/ui/diagnostic-width/non-whitespace-trimming.rs diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.stderr b/src/test/ui/diagnostic-width/non-whitespace-trimming.stderr similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming.stderr rename to src/test/ui/diagnostic-width/non-whitespace-trimming.stderr diff --git a/src/test/ui/terminal-width/tabs-trimming.rs b/src/test/ui/diagnostic-width/tabs-trimming.rs similarity index 100% rename from src/test/ui/terminal-width/tabs-trimming.rs rename to src/test/ui/diagnostic-width/tabs-trimming.rs diff --git a/src/test/ui/terminal-width/tabs-trimming.stderr b/src/test/ui/diagnostic-width/tabs-trimming.stderr similarity index 100% rename from src/test/ui/terminal-width/tabs-trimming.stderr rename to src/test/ui/diagnostic-width/tabs-trimming.stderr diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.rs b/src/test/ui/diagnostic-width/whitespace-trimming-2.rs similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming-2.rs rename to src/test/ui/diagnostic-width/whitespace-trimming-2.rs diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.stderr b/src/test/ui/diagnostic-width/whitespace-trimming-2.stderr similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming-2.stderr rename to src/test/ui/diagnostic-width/whitespace-trimming-2.stderr diff --git a/src/test/ui/terminal-width/whitespace-trimming.rs b/src/test/ui/diagnostic-width/whitespace-trimming.rs similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming.rs rename to src/test/ui/diagnostic-width/whitespace-trimming.rs diff --git a/src/test/ui/terminal-width/whitespace-trimming.stderr b/src/test/ui/diagnostic-width/whitespace-trimming.stderr similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming.stderr rename to src/test/ui/diagnostic-width/whitespace-trimming.stderr diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs index bb1aff70d8995..d8febd273c96e 100644 --- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs +++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs @@ -9,9 +9,11 @@ fn _if_let_guard() { () if (let 0 = 1) => {} //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if (((let 0 = 1))) => {} //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if true && let 0 = 1 => {} //~^ ERROR `if let` guards are experimental @@ -23,13 +25,17 @@ fn _if_let_guard() { () if (let 0 = 1) && true => {} //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if true && (let 0 = 1) => {} //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if (let 0 = 1) && (let 0 = 1) => {} //~^ ERROR `let` expressions in this position are unstable //~| ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} //~^ ERROR `if let` guards are experimental @@ -38,6 +44,7 @@ fn _if_let_guard() { //~| ERROR `let` expressions in this position are unstable //~| ERROR `let` expressions in this position are unstable //~| ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if let Range { start: _, end: _ } = (true..true) && false => {} //~^ ERROR `if let` guards are experimental diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr index 370a57318fdd0..52b5bca628ac7 100644 --- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr +++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr @@ -1,17 +1,59 @@ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:59:16 + --> $DIR/feature-gate.rs:10:16 + | +LL | () if (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:14:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:26:16 + | +LL | () if (let 0 = 1) && true => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:30:24 + | +LL | () if true && (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:34:16 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:34:31 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:40:42 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:66:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:62:16 + --> $DIR/feature-gate.rs:69:16 | LL | use_expr!((let 0 = 1)); | ^^^ error: no rules expected the token `let` - --> $DIR/feature-gate.rs:71:15 + --> $DIR/feature-gate.rs:78:15 | LL | macro_rules! use_expr { | --------------------- when calling this macro @@ -30,7 +72,7 @@ LL | () if let 0 = 1 => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:16:12 + --> $DIR/feature-gate.rs:18:12 | LL | () if true && let 0 = 1 => {} | ^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +82,7 @@ LL | () if true && let 0 = 1 => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:20:12 + --> $DIR/feature-gate.rs:22:12 | LL | () if let 0 = 1 && true => {} | ^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +92,7 @@ LL | () if let 0 = 1 && true => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:34:12 + --> $DIR/feature-gate.rs:40:12 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +102,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:42:12 + --> $DIR/feature-gate.rs:49:12 | LL | () if let Range { start: _, end: _ } = (true..true) && false => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +112,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:67:12 + --> $DIR/feature-gate.rs:74:12 | LL | () if let 0 = 1 => {} | ^^^^^^^^^^^^ @@ -89,7 +131,7 @@ LL | () if (let 0 = 1) => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:13:18 + --> $DIR/feature-gate.rs:14:18 | LL | () if (((let 0 = 1))) => {} | ^^^^^^^^^ @@ -98,7 +140,7 @@ LL | () if (((let 0 = 1))) => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:16:23 + --> $DIR/feature-gate.rs:18:23 | LL | () if true && let 0 = 1 => {} | ^^^^^^^^^ @@ -107,7 +149,7 @@ LL | () if true && let 0 = 1 => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:20:15 + --> $DIR/feature-gate.rs:22:15 | LL | () if let 0 = 1 && true => {} | ^^^^^^^^^ @@ -116,7 +158,7 @@ LL | () if let 0 = 1 && true => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:24:16 + --> $DIR/feature-gate.rs:26:16 | LL | () if (let 0 = 1) && true => {} | ^^^^^^^^^ @@ -125,7 +167,7 @@ LL | () if (let 0 = 1) && true => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:27:24 + --> $DIR/feature-gate.rs:30:24 | LL | () if true && (let 0 = 1) => {} | ^^^^^^^^^ @@ -134,7 +176,7 @@ LL | () if true && (let 0 = 1) => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:30:16 + --> $DIR/feature-gate.rs:34:16 | LL | () if (let 0 = 1) && (let 0 = 1) => {} | ^^^^^^^^^ @@ -143,7 +185,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:30:31 + --> $DIR/feature-gate.rs:34:31 | LL | () if (let 0 = 1) && (let 0 = 1) => {} | ^^^^^^^^^ @@ -152,7 +194,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:34:15 + --> $DIR/feature-gate.rs:40:15 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^^^^^^^ @@ -161,7 +203,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:34:28 + --> $DIR/feature-gate.rs:40:28 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^^^^^^^ @@ -170,7 +212,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:34:42 + --> $DIR/feature-gate.rs:40:42 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^^^^^^^ @@ -179,7 +221,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:34:55 + --> $DIR/feature-gate.rs:40:55 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^^^^^^^ @@ -188,7 +230,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:34:68 + --> $DIR/feature-gate.rs:40:68 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^^^^^^^ @@ -197,7 +239,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:42:15 + --> $DIR/feature-gate.rs:49:15 | LL | () if let Range { start: _, end: _ } = (true..true) && false => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -206,7 +248,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:59:16 + --> $DIR/feature-gate.rs:66:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^ @@ -215,7 +257,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:62:16 + --> $DIR/feature-gate.rs:69:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ @@ -223,6 +265,6 @@ LL | use_expr!((let 0 = 1)); = note: see issue #53667 for more information = help: add `#![feature(let_chains)]` to the crate attributes to enable -error: aborting due to 25 previous errors +error: aborting due to 32 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs index 36b730505c29e..069d2dc414dea 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -28,47 +28,61 @@ fn main() {} fn _if() { if (let 0 = 1) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement if (((let 0 = 1))) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement if (let 0 = 1) && true {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement if true && (let 0 = 1) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement if (let 0 = 1) && (let 0 = 1) {} //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement } fn _while() { while (let 0 = 1) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement while (((let 0 = 1))) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement while (let 0 = 1) && true {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement while true && (let 0 = 1) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement while (let 0 = 1) && (let 0 = 1) {} //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement } fn _macros() { @@ -89,39 +103,64 @@ fn _macros() { } fn nested_within_if_expr() { - if &let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types + if &let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement - if !let 0 = 0 {} //~ ERROR `let` expressions are not supported here - if *let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR type `bool` cannot be dereferenced - if -let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR cannot apply unary operator `-` to type `bool` + if !let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if *let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR type `bool` cannot be dereferenced + //~| ERROR expected expression, found `let` statement + if -let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR cannot apply unary operator `-` to type `bool` + //~| ERROR expected expression, found `let` statement fn _check_try_binds_tighter() -> Result<(), ()> { if let 0 = 0? {} //~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } - if (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + if (let 0 = 0)? {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR the `?` operator can only be applied to values that implement `Try` //~| ERROR the `?` operator can only be used in a function that returns `Result` + //~| ERROR expected expression, found `let` statement - if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here - if (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here - if true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here - if true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here + if true || let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if true && (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if true || (true && let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here let mut x = true; - if x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types + if x = let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement - if true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types - if ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types - if (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types + if true..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + if ..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + if (let 0 = 0).. {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement // Binds as `(let ... = true)..true &&/|| false`. if let Range { start: _, end: _ } = true..true && false {} @@ -151,42 +190,68 @@ fn nested_within_if_expr() { if let true = let true = true {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement } fn nested_within_while_expr() { - while &let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types + while &let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement - while !let 0 = 0 {} //~ ERROR `let` expressions are not supported here - while *let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR type `bool` cannot be dereferenced - while -let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR cannot apply unary operator `-` to type `bool` + while !let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while *let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR type `bool` cannot be dereferenced + //~| ERROR expected expression, found `let` statement + while -let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR cannot apply unary operator `-` to type `bool` + //~| ERROR expected expression, found `let` statement fn _check_try_binds_tighter() -> Result<(), ()> { while let 0 = 0? {} //~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } - while (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + while (let 0 = 0)? {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR the `?` operator can only be applied to values that implement `Try` //~| ERROR the `?` operator can only be used in a function that returns `Result` + //~| ERROR expected expression, found `let` statement - while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here - while (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here - while true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here - while true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here + while true || let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while true && (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while true || (true && let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here let mut x = true; - while x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types + while x = let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement - while true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types - while ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types - while (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here - //~^ ERROR mismatched types + while true..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + while ..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + while (let 0 = 0).. {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement // Binds as `(let ... = true)..true &&/|| false`. while let Range { start: _, end: _ } = true..true && false {} @@ -216,6 +281,7 @@ fn nested_within_while_expr() { while let true = let true = true {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement } fn not_error_because_clarified_intent() { @@ -316,15 +382,18 @@ fn inside_const_generic_arguments() { impl A<{B}> { const O: u32 = 5; } if let A::<{ - true && let 1 = 1 //~ ERROR `let` expressions are not supported here + true && let 1 = 1 + //~^ ERROR `let` expressions are not supported here }>::O = 5 {} while let A::<{ - true && let 1 = 1 //~ ERROR `let` expressions are not supported here + true && let 1 = 1 + //~^ ERROR `let` expressions are not supported here }>::O = 5 {} if A::<{ - true && let 1 = 1 //~ ERROR `let` expressions are not supported here + true && let 1 = 1 + //~^ ERROR `let` expressions are not supported here }>::O == 5 {} // In the cases above we have `ExprKind::Block` to help us out. @@ -345,14 +414,18 @@ fn with_parenthesis() { if (let Some(a) = opt && true) { //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement } if (let Some(a) = opt) && true { //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement } if (let Some(a) = opt) && (let Some(b) = a) { //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement } if let Some(a) = opt && (true && true) { } @@ -360,13 +433,18 @@ fn with_parenthesis() { if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement } if (let Some(a) = opt && (let Some(b) = a)) && true { //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement } if (let Some(a) = opt && (true)) && true { //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement } if (true && (true)) && let Some(a) = opt { diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 5cf06cf4b27cd..20512e8ee31aa 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -1,113 +1,353 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:232:6 + --> $DIR/disallowed-positions.rs:29:9 + | +LL | if (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:33:11 + | +LL | if (((let 0 = 1))) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:37:9 + | +LL | if (let 0 = 1) && true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:45:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:45:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:51:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:59:12 + | +LL | while (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:63:14 + | +LL | while (((let 0 = 1))) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:67:12 + | +LL | while (let 0 = 1) && true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:71:20 + | +LL | while true && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:75:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:75:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:81:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:106:9 + | +LL | if &let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:111:9 + | +LL | if !let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:114:9 + | +LL | if *let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:118:9 + | +LL | if -let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:128:9 + | +LL | if (let 0 = 0)? {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:134:16 + | +LL | if true || let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:137:17 + | +LL | if (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:140:25 + | +LL | if true && (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:147:12 + | +LL | if x = let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:152:15 + | +LL | if true..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:156:11 + | +LL | if ..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:160:9 + | +LL | if (let 0 = 0).. {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:191:19 + | +LL | if let true = let true = true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:197:12 + | +LL | while &let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:202:12 + | +LL | while !let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:205:12 + | +LL | while *let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:209:12 + | +LL | while -let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:219:12 + | +LL | while (let 0 = 0)? {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:225:19 + | +LL | while true || let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:228:20 + | +LL | while (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:231:28 + | +LL | while true && (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:238:15 + | +LL | while x = let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:243:18 + | +LL | while true..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:247:14 + | +LL | while ..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:251:12 + | +LL | while (let 0 = 0).. {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:282:22 + | +LL | while let true = let true = true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:298:6 | LL | &let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:236:6 + --> $DIR/disallowed-positions.rs:302:6 | LL | !let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:6 + --> $DIR/disallowed-positions.rs:305:6 | LL | *let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:243:6 + --> $DIR/disallowed-positions.rs:309:6 | LL | -let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:253:6 + --> $DIR/disallowed-positions.rs:319:6 | LL | (let 0 = 0)?; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:13 + --> $DIR/disallowed-positions.rs:325:13 | LL | true || let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:262:14 + --> $DIR/disallowed-positions.rs:328:14 | LL | (true || let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:265:22 + --> $DIR/disallowed-positions.rs:331:22 | LL | true && (true || let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:270:9 + --> $DIR/disallowed-positions.rs:336:9 | LL | x = let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:274:12 + --> $DIR/disallowed-positions.rs:340:12 | LL | true..(let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:277:8 + --> $DIR/disallowed-positions.rs:343:8 | LL | ..(let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:280:6 + --> $DIR/disallowed-positions.rs:346:6 | LL | (let 0 = 0)..; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:284:6 + --> $DIR/disallowed-positions.rs:350:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:289:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | (let true = let true = true); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:289:17 + --> $DIR/disallowed-positions.rs:355:17 | LL | (let true = let true = true); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:296:25 + --> $DIR/disallowed-positions.rs:362:25 | LL | let x = true && let y = 1; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:302:19 + --> $DIR/disallowed-positions.rs:368:19 | LL | [1, 2, 3][let _ = ()] | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:307:6 + --> $DIR/disallowed-positions.rs:373:6 | LL | &let 0 = 0 | ^^^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:337:9 + --> $DIR/disallowed-positions.rs:406:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -118,25 +358,79 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:384:22 + --> $DIR/disallowed-positions.rs:415:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:420:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:424:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:424:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:433:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:433:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:439:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:439:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:445:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:462:22 | LL | let x = (true && let y = 1); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:389:20 + --> $DIR/disallowed-positions.rs:467:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:81:16 + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:85:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -155,280 +449,280 @@ LL | if (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:32:11 + --> $DIR/disallowed-positions.rs:33:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:32:11 + --> $DIR/disallowed-positions.rs:33:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:35:9 + --> $DIR/disallowed-positions.rs:37:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:35:9 + --> $DIR/disallowed-positions.rs:37:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:38:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:38:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:41:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:41:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:41:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:41:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:51:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:51:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:45:48 + --> $DIR/disallowed-positions.rs:51:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:51:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:45:61 + --> $DIR/disallowed-positions.rs:51:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:51:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:52:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:52:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:55:14 + --> $DIR/disallowed-positions.rs:63:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:55:14 + --> $DIR/disallowed-positions.rs:63:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:67:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:67:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:61:20 + --> $DIR/disallowed-positions.rs:71:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:61:20 + --> $DIR/disallowed-positions.rs:71:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:75:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:75:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:64:27 + --> $DIR/disallowed-positions.rs:75:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:64:27 + --> $DIR/disallowed-positions.rs:75:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:68:51 + --> $DIR/disallowed-positions.rs:81:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:68:64 + --> $DIR/disallowed-positions.rs:81:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:81:16 + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:81:16 + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:81:16 + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:81:16 + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:85:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:85:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:85:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:85:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:92:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -436,7 +730,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:95:9 + --> $DIR/disallowed-positions.rs:111:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -444,7 +738,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:96:9 + --> $DIR/disallowed-positions.rs:114:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -452,7 +746,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:98:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -460,72 +754,72 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:128:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:128:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:110:16 + --> $DIR/disallowed-positions.rs:134:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:110:13 + --> $DIR/disallowed-positions.rs:134:13 | LL | if true || let 0 = 0 {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:111:17 + --> $DIR/disallowed-positions.rs:137:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:111:14 + --> $DIR/disallowed-positions.rs:137:14 | LL | if (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:112:25 + --> $DIR/disallowed-positions.rs:140:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:112:22 + --> $DIR/disallowed-positions.rs:140:22 | LL | if true && (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:113:25 + --> $DIR/disallowed-positions.rs:143:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:113:17 + --> $DIR/disallowed-positions.rs:143:17 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:116:12 + --> $DIR/disallowed-positions.rs:147:12 | LL | if x = let 0 = 0 {} | ^^^^^^^^^ @@ -533,46 +827,46 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:119:15 + --> $DIR/disallowed-positions.rs:152:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:119:15 + --> $DIR/disallowed-positions.rs:152:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:121:11 + --> $DIR/disallowed-positions.rs:156:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:121:11 + --> $DIR/disallowed-positions.rs:156:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:123:9 + --> $DIR/disallowed-positions.rs:160:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:123:9 + --> $DIR/disallowed-positions.rs:160:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:127:8 + --> $DIR/disallowed-positions.rs:166:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -580,7 +874,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:131:8 + --> $DIR/disallowed-positions.rs:170:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -588,7 +882,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:138:8 + --> $DIR/disallowed-positions.rs:177:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -596,7 +890,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:146:8 + --> $DIR/disallowed-positions.rs:185:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -604,7 +898,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:152:19 + --> $DIR/disallowed-positions.rs:191:19 | LL | if let true = let true = true {} | ^^^^^^^^^^^^^^^ @@ -612,7 +906,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:157:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -620,7 +914,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:160:12 + --> $DIR/disallowed-positions.rs:202:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -628,7 +922,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:161:12 + --> $DIR/disallowed-positions.rs:205:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -636,7 +930,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:163:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -644,72 +938,72 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:171:12 + --> $DIR/disallowed-positions.rs:219:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:171:12 + --> $DIR/disallowed-positions.rs:219:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:175:19 + --> $DIR/disallowed-positions.rs:225:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:175:16 + --> $DIR/disallowed-positions.rs:225:16 | LL | while true || let 0 = 0 {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:176:20 + --> $DIR/disallowed-positions.rs:228:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:176:17 + --> $DIR/disallowed-positions.rs:228:17 | LL | while (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:177:28 + --> $DIR/disallowed-positions.rs:231:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:177:25 + --> $DIR/disallowed-positions.rs:231:25 | LL | while true && (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:178:28 + --> $DIR/disallowed-positions.rs:234:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:178:20 + --> $DIR/disallowed-positions.rs:234:20 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:181:15 + --> $DIR/disallowed-positions.rs:238:15 | LL | while x = let 0 = 0 {} | ^^^^^^^^^ @@ -717,46 +1011,46 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:184:18 + --> $DIR/disallowed-positions.rs:243:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:184:18 + --> $DIR/disallowed-positions.rs:243:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:186:14 + --> $DIR/disallowed-positions.rs:247:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:186:14 + --> $DIR/disallowed-positions.rs:247:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:188:12 + --> $DIR/disallowed-positions.rs:251:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:188:12 + --> $DIR/disallowed-positions.rs:251:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:192:11 + --> $DIR/disallowed-positions.rs:257:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -764,7 +1058,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:196:11 + --> $DIR/disallowed-positions.rs:261:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -772,7 +1066,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:203:11 + --> $DIR/disallowed-positions.rs:268:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -780,7 +1074,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:211:11 + --> $DIR/disallowed-positions.rs:276:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -788,7 +1082,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:217:22 + --> $DIR/disallowed-positions.rs:282:22 | LL | while let true = let true = true {} | ^^^^^^^^^^^^^^^ @@ -796,7 +1090,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:232:6 + --> $DIR/disallowed-positions.rs:298:6 | LL | &let 0 = 0; | ^^^^^^^^^ @@ -804,7 +1098,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:236:6 + --> $DIR/disallowed-positions.rs:302:6 | LL | !let 0 = 0; | ^^^^^^^^^ @@ -812,7 +1106,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:239:6 + --> $DIR/disallowed-positions.rs:305:6 | LL | *let 0 = 0; | ^^^^^^^^^ @@ -820,7 +1114,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:243:6 + --> $DIR/disallowed-positions.rs:309:6 | LL | -let 0 = 0; | ^^^^^^^^^ @@ -828,59 +1122,59 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:253:6 + --> $DIR/disallowed-positions.rs:319:6 | LL | (let 0 = 0)?; | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:253:6 + --> $DIR/disallowed-positions.rs:319:6 | LL | (let 0 = 0)?; | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:259:13 + --> $DIR/disallowed-positions.rs:325:13 | LL | true || let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:259:10 + --> $DIR/disallowed-positions.rs:325:10 | LL | true || let 0 = 0; | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:262:14 + --> $DIR/disallowed-positions.rs:328:14 | LL | (true || let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:262:11 + --> $DIR/disallowed-positions.rs:328:11 | LL | (true || let 0 = 0); | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:265:22 + --> $DIR/disallowed-positions.rs:331:22 | LL | true && (true || let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:265:19 + --> $DIR/disallowed-positions.rs:331:19 | LL | true && (true || let 0 = 0); | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:270:9 + --> $DIR/disallowed-positions.rs:336:9 | LL | x = let 0 = 0; | ^^^^^^^^^ @@ -888,46 +1182,46 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:274:12 + --> $DIR/disallowed-positions.rs:340:12 | LL | true..(let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:274:12 + --> $DIR/disallowed-positions.rs:340:12 | LL | true..(let 0 = 0); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:277:8 + --> $DIR/disallowed-positions.rs:343:8 | LL | ..(let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:277:8 + --> $DIR/disallowed-positions.rs:343:8 | LL | ..(let 0 = 0); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:280:6 + --> $DIR/disallowed-positions.rs:346:6 | LL | (let 0 = 0)..; | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:280:6 + --> $DIR/disallowed-positions.rs:346:6 | LL | (let 0 = 0)..; | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:284:6 + --> $DIR/disallowed-positions.rs:350:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -935,20 +1229,20 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:289:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:289:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:307:6 + --> $DIR/disallowed-positions.rs:373:6 | LL | &let 0 = 0 | ^^^^^^^^^ @@ -956,7 +1250,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:319:17 + --> $DIR/disallowed-positions.rs:385:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -964,7 +1258,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:323:17 + --> $DIR/disallowed-positions.rs:390:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -972,7 +1266,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:327:17 + --> $DIR/disallowed-positions.rs:395:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -980,7 +1274,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:337:17 + --> $DIR/disallowed-positions.rs:406:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -988,124 +1282,124 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:346:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:346:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:350:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:350:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:353:9 + --> $DIR/disallowed-positions.rs:424:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:353:9 + --> $DIR/disallowed-positions.rs:424:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:353:32 + --> $DIR/disallowed-positions.rs:424:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:353:32 + --> $DIR/disallowed-positions.rs:424:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:360:9 + --> $DIR/disallowed-positions.rs:433:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:360:9 + --> $DIR/disallowed-positions.rs:433:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:360:31 + --> $DIR/disallowed-positions.rs:433:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:360:31 + --> $DIR/disallowed-positions.rs:433:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:364:9 + --> $DIR/disallowed-positions.rs:439:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:364:9 + --> $DIR/disallowed-positions.rs:439:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:364:31 + --> $DIR/disallowed-positions.rs:439:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:364:31 + --> $DIR/disallowed-positions.rs:439:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:368:9 + --> $DIR/disallowed-positions.rs:445:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:368:9 + --> $DIR/disallowed-positions.rs:445:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:92:8 + --> $DIR/disallowed-positions.rs:106:8 | LL | if &let 0 = 0 {} | ^^^^^^^^^^ expected `bool`, found `&bool` @@ -1117,19 +1411,19 @@ LL + if let 0 = 0 {} | error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:96:8 + --> $DIR/disallowed-positions.rs:114:8 | LL | if *let 0 = 0 {} | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:98:8 + --> $DIR/disallowed-positions.rs:118:8 | LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:106:8 + --> $DIR/disallowed-positions.rs:128:8 | LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1137,7 +1431,7 @@ LL | if (let 0 = 0)? {} = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:106:19 + --> $DIR/disallowed-positions.rs:128:19 | LL | / fn nested_within_if_expr() { LL | | if &let 0 = 0 {} @@ -1154,7 +1448,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:116:8 + --> $DIR/disallowed-positions.rs:147:8 | LL | if x = let 0 = 0 {} | ^^^^^^^^^^^^^ expected `bool`, found `()` @@ -1165,7 +1459,7 @@ LL | if x == let 0 = 0 {} | ~~ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:119:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1174,7 +1468,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:121:8 + --> $DIR/disallowed-positions.rs:156:8 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` @@ -1183,7 +1477,7 @@ LL | if ..(let 0 = 0) {} found struct `RangeTo` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:123:8 + --> $DIR/disallowed-positions.rs:160:8 | LL | if (let 0 = 0).. {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` @@ -1192,7 +1486,7 @@ LL | if (let 0 = 0).. {} found struct `RangeFrom` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:166:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1203,7 +1497,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:127:8 + --> $DIR/disallowed-positions.rs:166:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1212,7 +1506,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:131:12 + --> $DIR/disallowed-positions.rs:170:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1223,7 +1517,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:131:8 + --> $DIR/disallowed-positions.rs:170:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1232,7 +1526,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:138:12 + --> $DIR/disallowed-positions.rs:177:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1243,20 +1537,20 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:138:41 + --> $DIR/disallowed-positions.rs:177:41 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:138:41: 138:48]` + found closure `[closure@$DIR/disallowed-positions.rs:177:41: 177:48]` help: use parentheses to call this closure | LL | if let Range { start: F, end } = F..(|| true)() {} | + +++ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:138:8 + --> $DIR/disallowed-positions.rs:177:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1265,7 +1559,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:146:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1276,7 +1570,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:146:44 + --> $DIR/disallowed-positions.rs:185:44 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^ expected `bool`, found `&&bool` @@ -1288,7 +1582,7 @@ LL + if let Range { start: true, end } = t..false {} | error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:146:8 + --> $DIR/disallowed-positions.rs:185:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1297,7 +1591,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:102:20 + --> $DIR/disallowed-positions.rs:124:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1305,7 +1599,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:157:11 + --> $DIR/disallowed-positions.rs:197:11 | LL | while &let 0 = 0 {} | ^^^^^^^^^^ expected `bool`, found `&bool` @@ -1317,19 +1611,19 @@ LL + while let 0 = 0 {} | error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:161:11 + --> $DIR/disallowed-positions.rs:205:11 | LL | while *let 0 = 0 {} | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:163:11 + --> $DIR/disallowed-positions.rs:209:11 | LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:171:11 + --> $DIR/disallowed-positions.rs:219:11 | LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1337,7 +1631,7 @@ LL | while (let 0 = 0)? {} = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:171:22 + --> $DIR/disallowed-positions.rs:219:22 | LL | / fn nested_within_while_expr() { LL | | while &let 0 = 0 {} @@ -1354,7 +1648,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:181:11 + --> $DIR/disallowed-positions.rs:238:11 | LL | while x = let 0 = 0 {} | ^^^^^^^^^^^^^ expected `bool`, found `()` @@ -1365,7 +1659,7 @@ LL | while x == let 0 = 0 {} | ~~ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:184:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1374,7 +1668,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:186:11 + --> $DIR/disallowed-positions.rs:247:11 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` @@ -1383,7 +1677,7 @@ LL | while ..(let 0 = 0) {} found struct `RangeTo` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:188:11 + --> $DIR/disallowed-positions.rs:251:11 | LL | while (let 0 = 0).. {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` @@ -1392,7 +1686,7 @@ LL | while (let 0 = 0).. {} found struct `RangeFrom` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:192:15 + --> $DIR/disallowed-positions.rs:257:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1403,7 +1697,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:192:11 + --> $DIR/disallowed-positions.rs:257:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1412,7 +1706,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:196:15 + --> $DIR/disallowed-positions.rs:261:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1423,7 +1717,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:196:11 + --> $DIR/disallowed-positions.rs:261:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1432,7 +1726,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:203:15 + --> $DIR/disallowed-positions.rs:268:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1443,20 +1737,20 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:203:44 + --> $DIR/disallowed-positions.rs:268:44 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:203:44: 203:51]` + found closure `[closure@$DIR/disallowed-positions.rs:268:44: 268:51]` help: use parentheses to call this closure | LL | while let Range { start: F, end } = F..(|| true)() {} | + +++ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:203:11 + --> $DIR/disallowed-positions.rs:268:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1465,7 +1759,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:211:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1476,7 +1770,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:211:47 + --> $DIR/disallowed-positions.rs:276:47 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^ expected `bool`, found `&&bool` @@ -1488,7 +1782,7 @@ LL + while let Range { start: true, end } = t..false {} | error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:211:11 + --> $DIR/disallowed-positions.rs:276:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1497,7 +1791,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:167:23 + --> $DIR/disallowed-positions.rs:215:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1505,19 +1799,19 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:239:5 + --> $DIR/disallowed-positions.rs:305:5 | LL | *let 0 = 0; | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:243:5 + --> $DIR/disallowed-positions.rs:309:5 | LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:253:5 + --> $DIR/disallowed-positions.rs:319:5 | LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1525,7 +1819,7 @@ LL | (let 0 = 0)?; = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:253:16 + --> $DIR/disallowed-positions.rs:319:16 | LL | / fn outside_if_and_while_expr() { LL | | &let 0 = 0; @@ -1542,7 +1836,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:284:10 + --> $DIR/disallowed-positions.rs:350:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1553,7 +1847,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:307:5 + --> $DIR/disallowed-positions.rs:373:5 | LL | fn outside_if_and_while_expr() { | - help: try adding a return type: `-> &bool` @@ -1562,14 +1856,14 @@ LL | &let 0 = 0 | ^^^^^^^^^^ expected `()`, found `&bool` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:249:17 + --> $DIR/disallowed-positions.rs:315:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 156 previous errors +error: aborting due to 205 previous errors Some errors have detailed explanations: E0277, E0308, E0600, E0614. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs index 8771821130848..2b407ef510c52 100644 --- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs +++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs @@ -19,6 +19,11 @@ fn _if() { if let Range { start: _, end: _ } = (true..true) && false {} //~^ ERROR `let` expressions in this position are unstable [E0658] + + if let 1 = 1 && let true = { true } && false { + //~^ ERROR `let` expressions in this position are unstable [E0658] + //~| ERROR `let` expressions in this position are unstable [E0658] + } } fn _while() { diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr index bcea8bbaa730b..feea1c254d8da 100644 --- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr @@ -1,17 +1,17 @@ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:50:20 + --> $DIR/feature-gate.rs:55:20 | LL | #[cfg(FALSE)] (let 0 = 1); | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:40:17 + --> $DIR/feature-gate.rs:45:17 | LL | noop_expr!((let 0 = 1)); | ^^^ error: no rules expected the token `let` - --> $DIR/feature-gate.rs:53:15 + --> $DIR/feature-gate.rs:58:15 | LL | macro_rules! use_expr { | --------------------- when calling this macro @@ -47,7 +47,25 @@ LL | if let Range { start: _, end: _ } = (true..true) && false {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:27:19 + --> $DIR/feature-gate.rs:23:8 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:23:21 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:32:19 | LL | while true && let 0 = 1 {} | ^^^^^^^^^ @@ -56,7 +74,7 @@ LL | while true && let 0 = 1 {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:30:11 + --> $DIR/feature-gate.rs:35:11 | LL | while let 0 = 1 && true {} | ^^^^^^^^^ @@ -65,7 +83,7 @@ LL | while let 0 = 1 && true {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:33:11 + --> $DIR/feature-gate.rs:38:11 | LL | while let Range { start: _, end: _ } = (true..true) && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,7 +92,7 @@ LL | while let Range { start: _, end: _ } = (true..true) && false {} = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:50:20 + --> $DIR/feature-gate.rs:55:20 | LL | #[cfg(FALSE)] (let 0 = 1); | ^^^^^^^^^ @@ -83,7 +101,7 @@ LL | #[cfg(FALSE)] (let 0 = 1); = help: add `#![feature(let_chains)]` to the crate attributes to enable error[E0658]: `let` expressions in this position are unstable - --> $DIR/feature-gate.rs:40:17 + --> $DIR/feature-gate.rs:45:17 | LL | noop_expr!((let 0 = 1)); | ^^^^^^^^^ @@ -91,6 +109,6 @@ LL | noop_expr!((let 0 = 1)); = note: see issue #53667 for more information = help: add `#![feature(let_chains)]` to the crate attributes to enable -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs index 6cc53a1935b95..a942d1f4cafbf 100644 --- a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs +++ b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs @@ -1,17 +1,45 @@ -// check-pass -// known-bug - #![feature(let_chains)] fn main() { let _opt = Some(1i32); + #[cfg(FALSE)] + { + let _ = &&let Some(x) = Some(42); + //~^ ERROR expected expression, found `let` statement + } + #[cfg(FALSE)] + { + if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { + //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + true + } + } + #[cfg(FALSE)] { if let Some(elem) = _opt && { [1, 2, 3][let _ = ()]; + //~^ ERROR expected expression, found `let` statement true } { } } + + #[cfg(FALSE)] + { + if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 { + //~^ ERROR expected expression, found `let` statement + true + } + } + #[cfg(FALSE)] + { + if let a = 1 && { + let x = let y = 1; + //~^ ERROR expected expression, found `let` statement + } { + } + } } diff --git a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr new file mode 100644 index 0000000000000..d1ce83c723329 --- /dev/null +++ b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr @@ -0,0 +1,38 @@ +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:8:19 + | +LL | let _ = &&let Some(x) = Some(42); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:13:47 + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:13:57 + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:23:23 + | +LL | [1, 2, 3][let _ = ()]; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:32:47 + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:40:21 + | +LL | let x = let y = 1; + | ^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/terminal-width/flag-human.rs b/src/test/ui/terminal-width/flag-human.rs deleted file mode 100644 index e445a84fd012e..0000000000000 --- a/src/test/ui/terminal-width/flag-human.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: -Z terminal-width=20 - -// This test checks that `-Z terminal-width` effects the human error output by restricting it to an -// arbitrarily low value so that the effect is visible. - -fn main() { - let _: () = 42; - //~^ ERROR mismatched types -} diff --git a/src/test/ui/terminal-width/flag-json.rs b/src/test/ui/terminal-width/flag-json.rs deleted file mode 100644 index 3d2530e204b33..0000000000000 --- a/src/test/ui/terminal-width/flag-json.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: -Z terminal-width=20 --error-format=json - -// This test checks that `-Z terminal-width` effects the JSON error output by restricting it to an -// arbitrarily low value so that the effect is visible. - -fn main() { - let _: () = 42; - //~^ ERROR arguments to this function are incorrect -} diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index df2430ced6b62..be7df08d89f05 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -301,7 +301,7 @@ fn in_attributes_expansion(expr: &Expr<'_>) -> bool { use rustc_span::hygiene::MacroKind; if expr.span.from_expansion() { let data = expr.span.ctxt().outer_expn_data(); - matches!(data.kind, ExpnKind::Macro(MacroKind::Attr, _)) + matches!(data.kind, ExpnKind::Macro(MacroKind::Attr|MacroKind::Derive, _)) } else { false } diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs index 21d66d5df79ec..d20977d55d29d 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.rs +++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs @@ -44,6 +44,12 @@ fn in_struct_field() { s._underscore_field += 1; } +/// Tests that we do not lint if the struct field is used in code created with derive. +#[derive(Clone, Debug)] +pub struct UnderscoreInStruct { + _foo: u32, +} + /// Tests that we do not lint if the underscore is not a prefix fn non_prefix_underscore(some_foo: u32) -> u32 { some_foo + 1 diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr index 790b849210c9b..61a9161d212da 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr +++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr @@ -31,7 +31,7 @@ LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:99:16 + --> $DIR/used_underscore_binding.rs:105:16 | LL | uses_i(_i); | ^^