diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 969d16d11e81b..82a755c7892b1 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -893,15 +893,18 @@ def bootstrap(help_triggered): build.verbose = args.verbose build.clean = args.clean - try: - toml_path = os.getenv('RUST_BOOTSTRAP_CONFIG') or args.config or 'config.toml' + # Read from `RUST_BOOTSTRAP_CONFIG`, then `--config`, then fallback to `config.toml` (if it + # exists). + toml_path = os.getenv('RUST_BOOTSTRAP_CONFIG') or args.config + if not toml_path and os.path.exists('config.toml'): + toml_path = 'config.toml' + + if toml_path: if not os.path.exists(toml_path): toml_path = os.path.join(build.rust_root, toml_path) with open(toml_path) as config: build.config_toml = config.read() - except (OSError, IOError): - pass config_verbose = build.get_toml('verbose', 'build') if config_verbose is not None: @@ -947,11 +950,12 @@ def bootstrap(help_triggered): env["SRC"] = build.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) env["BOOTSTRAP_PYTHON"] = sys.executable - env["BOOTSTRAP_CONFIG"] = toml_path env["BUILD_DIR"] = build.build_dir env["RUSTC_BOOTSTRAP"] = '1' env["CARGO"] = build.cargo() env["RUSTC"] = build.rustc() + if toml_path: + env["BOOTSTRAP_CONFIG"] = toml_path if build.rustfmt(): env["RUSTFMT"] = build.rustfmt() run(args, env=env, verbose=build.verbose) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 7a7838d965bc7..30b18eb56a125 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -273,10 +273,18 @@ This flag, when combined with other flags, makes them produce extra output. This flag allows you to pass the name and location for an external crate of a direct dependency. Indirect dependencies (dependencies of dependencies) are located using the [`-L` flag](#option-l-search-path). The given crate name is -added to the [extern prelude], which is the same as specifying `extern crate` -within the root module. The given crate name does not need to match the name +added to the [extern prelude], similar to specifying `extern crate` within the +root module. The given crate name does not need to match the name the library was built with. +Specifying `--extern` has one behavior difference from `extern crate`: +`--extern` merely makes the crate a _candidate_ for being linked; it does not +actually link it unless it's actively used. In rare occasions you may wish +to ensure a crate is linked even if you don't actively use it from your +code: for example, if it changes the global allocator or if it contains +`#[no_mangle]` symbols for use by other programming languages. In such +cases you'll need to use `extern crate`. + This flag may be specified multiple times. This flag takes an argument with either of the following formats: diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 15e81f9288722..67ebdcc9f33b1 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -60,7 +60,7 @@ impl RawVec { /// `#[rustc_force_min_const_fn]` attribute which requires conformance /// with `min_const_fn` but does not necessarily allow calling it in /// `stable(...) const fn` / user code not enabling `foo` when - /// `#[rustc_const_unstable(feature = "foo", ..)]` is present. + /// `#[rustc_const_unstable(feature = "foo", issue = "01234")]` is present. pub const NEW: Self = Self::new(); /// Creates the biggest possible `RawVec` (on the system heap) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 9061145a695f8..50e321f9c7158 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1012,7 +1012,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::any::type_name`](../../std/any/fn.type_name.html) - #[rustc_const_unstable(feature = "const_type_name", issue = "none")] + #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This @@ -1021,7 +1021,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of) - #[rustc_const_unstable(feature = "const_type_id", issue = "none")] + #[rustc_const_unstable(feature = "const_type_id", issue = "41875")] pub fn type_id() -> u64; /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: @@ -1931,7 +1931,7 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "none")] + #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")] pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// Internal hook used by Miri to implement unwinding. @@ -1948,6 +1948,16 @@ extern "rust-intrinsic" { #[cfg(not(bootstrap))] #[lang = "count_code_region"] pub fn count_code_region(index: u32); + + /// See documentation of `<*const T>::guaranteed_eq` for details. + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[cfg(not(bootstrap))] + pub fn ptr_guaranteed_eq(ptr: *const T, other: *const T) -> bool; + + /// See documentation of `<*const T>::guaranteed_ne` for details. + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[cfg(not(bootstrap))] + pub fn ptr_guaranteed_ne(ptr: *const T, other: *const T) -> bool; } // Some functions are defined here because they accidentally got made diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 0115c4df2fd3e..4eb2fdbd07868 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -87,6 +87,7 @@ #![feature(const_generics)] #![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] +#![cfg_attr(not(bootstrap), feature(const_raw_ptr_comparison))] #![feature(const_result)] #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index acc09ddc014e6..395b3879cfd0c 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -295,6 +295,72 @@ impl *const T { intrinsics::ptr_offset_from(self, origin) } + /// Returns whether two pointers are guaranteed to be equal. + /// + /// At runtime this function behaves like `self == other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be equal. + /// But when it returns `true`, the pointers are guaranteed to be equal. + /// + /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_ne`]: #method.guaranteed_ne + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_eq(self, other: *const T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_eq(self, other) + } + + /// Returns whether two pointers are guaranteed to be inequal. + /// + /// At runtime this function behaves like `self != other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine the inequality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be inequal. + /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// + /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_eq`]: #method.guaranteed_eq + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_ne(self, other: *const T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_ne(self, other) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 2bbeb95965e7e..b86ef5b13b353 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -273,6 +273,72 @@ impl *mut T { if self.is_null() { None } else { Some(&mut *self) } } + /// Returns whether two pointers are guaranteed to be equal. + /// + /// At runtime this function behaves like `self == other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be equal. + /// But when it returns `true`, the pointers are guaranteed to be equal. + /// + /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_ne`]: #method.guaranteed_ne + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_eq(self, other: *mut T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _) + } + + /// Returns whether two pointers are guaranteed to be inequal. + /// + /// At runtime this function behaves like `self != other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine the inequality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be inequal. + /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// + /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_eq`]: #method.guaranteed_eq + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 21ba2b5abcfb6..c69aafe687cf8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -5956,10 +5956,18 @@ where return false; } + #[cfg(bootstrap)] if self.as_ptr() == other.as_ptr() { return true; } + // While performance would suffer if `guaranteed_eq` just returned `false` + // for all arguments, correctness and return value of this function are not affected. + #[cfg(not(bootstrap))] + if self.as_ptr().guaranteed_eq(other.as_ptr()) { + return true; + } + self.iter().zip(other.iter()).all(|(x, y)| x == y) } } @@ -5973,9 +5981,18 @@ where if self.len() != other.len() { return false; } + + #[cfg(bootstrap)] if self.as_ptr() == other.as_ptr() { return true; } + + // While performance would suffer if `guaranteed_eq` just returned `false` + // for all arguments, correctness and return value of this function are not affected. + #[cfg(not(bootstrap))] + if self.as_ptr().guaranteed_eq(other.as_ptr()) { + return true; + } unsafe { let size = mem::size_of_val(self); memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0 diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 95465939070a0..0a8525f06fa3d 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -12,7 +12,7 @@ use log::debug; use rustc_ast::ast; use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; -use rustc_codegen_ssa::common::TypeKind; +use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::glue; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; @@ -731,6 +731,16 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } + "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { + let a = args[0].immediate(); + let b = args[1].immediate(); + if name == "ptr_guaranteed_eq" { + self.icmp(IntPredicate::IntEQ, a, b) + } else { + self.icmp(IntPredicate::IntNE, a, b) + } + } + "ptr_offset_from" => { let ty = substs.type_at(0); let pointee_size = self.size_of(ty); diff --git a/src/librustc_error_codes/error_codes/E0689.md b/src/librustc_error_codes/error_codes/E0689.md index 26c2c15ccfaac..a680a20421127 100644 --- a/src/librustc_error_codes/error_codes/E0689.md +++ b/src/librustc_error_codes/error_codes/E0689.md @@ -1,13 +1,16 @@ -This error indicates that the numeric value for the method being passed exists -but the type of the numeric value or binding could not be identified. +A method was called on an ambiguous numeric type. -The error happens on numeric literals: +Erroneous code example: ```compile_fail,E0689 -2.0.neg(); +2.0.neg(); // error! ``` -and on numeric bindings without an identified concrete type: +This error indicates that the numeric value for the method being passed exists +but the type of the numeric value or binding could not be identified. + +The error happens on numeric literals and on numeric bindings without an +identified concrete type: ```compile_fail,E0689 let x = 2.0; @@ -19,8 +22,8 @@ Because of this, you must give the numeric literal or binding a type: ``` use std::ops::Neg; -let _ = 2.0_f32.neg(); +let _ = 2.0_f32.neg(); // ok! let x: f32 = 2.0; -let _ = x.neg(); -let _ = (2.0 as f32).neg(); +let _ = x.neg(); // ok! +let _ = (2.0 as f32).neg(); // ok! ``` diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 7aadf58243f31..e2d497a3adab3 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -401,9 +401,6 @@ declare_features! ( /// Allows dereferencing raw pointers during const eval. (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - /// Allows comparing raw pointers during const eval. - (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - /// Allows `#[doc(alias = "...")]`. (active, doc_alias, "1.27.0", Some(50146), None), diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs index 4e348054fbd4b..8d410894e8b19 100644 --- a/src/librustc_feature/removed.rs +++ b/src/librustc_feature/removed.rs @@ -113,6 +113,11 @@ declare_features! ( Some("removed in favor of `#![feature(marker_trait_attr)]`")), /// Allows `#[no_debug]`. (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), + + /// Allows comparing raw pointers during const eval. + (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None, + Some("cannot be allowed in const eval in any meaningful way")), + // ------------------------------------------------------------------------- // feature-group-end: removed features // ------------------------------------------------------------------------- diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs index de71363cbde5c..6677c0e59f63a 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -26,7 +26,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { &self, region: Region<'tcx>, br: &ty::BoundRegion, - ) -> Option<(&hir::Ty<'_>, &hir::FnDecl<'_>)> { + ) -> Option<(&hir::Ty<'tcx>, &hir::FnDecl<'tcx>)> { if let Some(anon_reg) = self.tcx().is_suitable_region(region) { let def_id = anon_reg.def_id; if let Some(def_id) = def_id.as_local() { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs index a56401ebb90f0..3012928a09854 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -2,7 +2,8 @@ //! where one region is named and the other is anonymous. use crate::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; -use rustc_hir::{FnRetTy, TyKind}; +use rustc_hir::intravisit::Visitor; +use rustc_hir::FnRetTy; use rustc_middle::ty; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -80,16 +81,21 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let FnRetTy::Return(ty) = &fndecl.output { - let mut v = ty::TraitObjectVisitor(vec![]); - rustc_hir::intravisit::walk_ty(&mut v, ty); + let mut v = ty::TraitObjectVisitor(vec![], self.tcx().hir()); + v.visit_ty(ty); debug!("try_report_named_anon_conflict: ret ty {:?}", ty); if sub == &ty::ReStatic - && (matches!(ty.kind, TyKind::OpaqueDef(_, _)) || v.0.len() == 1) + && v.0 + .into_iter() + .filter(|t| t.span.desugaring_kind().is_none()) + .next() + .is_some() { + // If the failure is due to a `'static` requirement coming from a `dyn` or + // `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case + // better in `static_impl_trait`. debug!("try_report_named_anon_conflict: impl Trait + 'static"); - // This is an `impl Trait` or `dyn Trait` return that evaluates de need of - // `'static`. We handle this case better in `static_impl_trait`. return None; } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 82feebc80292a..46dad81a099bb 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -26,8 +26,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); - let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; - debug!("try_report_static_impl_trait: fn_return={:?}", fn_return); + let fn_returns = self.tcx().return_type_impl_or_dyn_traits(anon_reg_sup.def_id); + if fn_returns.is_empty() { + return None; + } + debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); if **sub_r == RegionKind::ReStatic { let sp = var_origin.span(); let return_sp = sub_origin.span(); @@ -98,25 +101,26 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } - // only apply this suggestion onto functions with - // explicit non-desugar'able return. - if fn_return.span.desugaring_kind().is_none() { - // FIXME: account for the need of parens in `&(dyn Trait + '_)` - - let consider = "consider changing the"; - let declare = "to declare that the"; - let arg = match param_info.param.pat.simple_ident() { - Some(simple_ident) => format!("argument `{}`", simple_ident), - None => "the argument".to_string(), - }; - let explicit = - format!("you can add an explicit `{}` lifetime bound", lifetime_name); - let explicit_static = - format!("explicit `'static` bound to the lifetime of {}", arg); - let captures = format!("captures data from {}", arg); - let add_static_bound = - "alternatively, add an explicit `'static` bound to this reference"; - let plus_lt = format!(" + {}", lifetime_name); + // FIXME: account for the need of parens in `&(dyn Trait + '_)` + let consider = "consider changing the"; + let declare = "to declare that the"; + let arg = match param_info.param.pat.simple_ident() { + Some(simple_ident) => format!("argument `{}`", simple_ident), + None => "the argument".to_string(), + }; + let explicit = + format!("you can add an explicit `{}` lifetime bound", lifetime_name); + let explicit_static = + format!("explicit `'static` bound to the lifetime of {}", arg); + let captures = format!("captures data from {}", arg); + let add_static_bound = + "alternatively, add an explicit `'static` bound to this reference"; + let plus_lt = format!(" + {}", lifetime_name); + for fn_return in fn_returns { + if fn_return.span.desugaring_kind().is_some() { + // Skip `async` desugaring `impl Future`. + continue; + } match fn_return.kind { TyKind::OpaqueDef(item_id, _) => { let item = self.tcx().hir().item(item_id.id); @@ -143,7 +147,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_suggestion_verbose( span, &format!("{} `impl Trait`'s {}", consider, explicit_static), - lifetime_name, + lifetime_name.clone(), Applicability::MaybeIncorrect, ); err.span_suggestion_verbose( @@ -152,6 +156,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { param_info.param_ty.to_string(), Applicability::MaybeIncorrect, ); + } else if let Some(_) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { name, span, .. }) + if name.ident().to_string() == lifetime_name => + { + Some(*span) + } + _ => None, + }) + .next() + { } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), @@ -161,10 +178,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { captures = captures, explicit = explicit, ), - plus_lt, + plus_lt.clone(), Applicability::MaybeIncorrect, ); - }; + } } TyKind::TraitObject(_, lt) => match lt.name { LifetimeName::ImplicitObjectLifetimeDefault => { @@ -176,15 +193,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { captures = captures, explicit = explicit, ), - plus_lt, + plus_lt.clone(), Applicability::MaybeIncorrect, ); } - _ => { + name if name.ident().to_string() != lifetime_name => { + // With this check we avoid suggesting redundant bounds. This + // would happen if there are nested impl/dyn traits and only + // one of them has the bound we'd suggest already there, like + // in `impl Foo + '_`. err.span_suggestion_verbose( lt.span, &format!("{} trait object's {}", consider, explicit_static), - lifetime_name, + lifetime_name.clone(), Applicability::MaybeIncorrect, ); err.span_suggestion_verbose( @@ -194,6 +215,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Applicability::MaybeIncorrect, ); } + _ => {} }, _ => {} } diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index 0499dc9ed2232..b6251e34008a3 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -30,10 +30,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { let span = self.trace.cause.span; - self.infcx.commit_if_ok(|snapshot| { + self.infcx.commit_if_ok(|_| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b); + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- @@ -48,8 +48,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // Compare types now that bound regions have been replaced. let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - self.infcx.leak_check(!a_is_expected, &placeholder_map, snapshot)?; - debug!("higher_ranked_sub: OK result={:?}", result); Ok(ty::Binder::bind(result)) @@ -75,7 +73,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { where T: TypeFoldable<'tcx>, { - let next_universe = self.create_next_universe(); + // Figure out what the next universe will be, but don't actually create + // it until after we've done the substitution (in particular there may + // be no bound variables). This is a performance optimization, since the + // leak check for example can be skipped if no new universes are created + // (i.e., if there are no placeholders). + let next_universe = self.universe().next_universe(); let fld_r = |br| { self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion { @@ -103,6 +106,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t, fld_c); + // If there were higher-ranked regions to replace, then actually create + // the next universe (this avoids needlessly creating universes). + if !map.is_empty() { + let n_u = self.create_next_universe(); + assert_eq!(n_u, next_universe); + } + debug!( "replace_bound_vars_with_placeholders(\ next_universe={:?}, \ @@ -119,7 +129,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn leak_check( &self, overly_polymorphic: bool, - placeholder_map: &PlaceholderMap<'tcx>, snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> RelateResult<'tcx, ()> { // If the user gave `-Zno-leak-check`, or we have been @@ -135,7 +144,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.inner.borrow_mut().unwrap_region_constraints().leak_check( self.tcx, overly_polymorphic, - placeholder_map, + self.universe(), snapshot, ) } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 91f4b3323f30e..8f8ce03d638c0 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -991,14 +991,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return None; } - Some(self.commit_if_ok(|snapshot| { - let (ty::SubtypePredicate { a_is_expected, a, b }, placeholder_map) = + Some(self.commit_if_ok(|_snapshot| { + let (ty::SubtypePredicate { a_is_expected, a, b }, _) = self.replace_bound_vars_with_placeholders(&predicate); let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; - self.leak_check(false, &placeholder_map, snapshot)?; - Ok(ok.unit()) })) } @@ -1008,14 +1006,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause: &traits::ObligationCause<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) -> UnitResult<'tcx> { - self.commit_if_ok(|snapshot| { - let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = + self.commit_if_ok(|_snapshot| { + let (ty::OutlivesPredicate(r_a, r_b), _) = self.replace_bound_vars_with_placeholders(&predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) }); self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` - self.leak_check(false, &placeholder_map, snapshot)?; Ok(()) }) } diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 8de8925100608..2350c28dfaaff 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -522,7 +522,13 @@ where } if a == b { - return Ok(a); + // Subtle: if a or b has a bound variable that we are lazilly + // substituting, then even if a == b, it could be that the values we + // will substitute for those bound variables are *not* the same, and + // hence returning `Ok(a)` is incorrect. + if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { + return Ok(a); + } } match (&a.kind, &b.kind) { diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 91c39a0e78ffb..32e708bf52b32 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -1,158 +1,446 @@ use super::*; -use crate::infer::{CombinedSnapshot, PlaceholderMap}; -use rustc_data_structures::undo_log::UndoLogs; +use crate::infer::CombinedSnapshot; +use rustc_data_structures::{ + graph::{scc::Sccs, vec_graph::VecGraph}, + undo_log::UndoLogs, +}; +use rustc_index::vec::Idx; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::RelateResult; impl<'tcx> RegionConstraintCollector<'_, 'tcx> { - /// Searches region constraints created since `snapshot` that - /// affect one of the placeholders in `placeholder_map`, returning - /// an error if any of the placeholders are related to another - /// placeholder or would have to escape into some parent universe - /// that cannot name them. + /// Searches new universes created during `snapshot`, looking for + /// placeholders that may "leak" out from the universes they are contained + /// in. If any leaking placeholders are found, then an `Err` is returned + /// (typically leading to the snapshot being reversed). /// - /// This is a temporary backwards compatibility measure to try and - /// retain the older (arguably incorrect) behavior of the - /// compiler. + /// The leak check *used* to be the only way we had to handle higher-ranked + /// obligations. Now that we have integrated universes into the region + /// solvers, this is no longer the case, but we retain the leak check for + /// backwards compatibility purposes. In particular, it lets us make "early" + /// decisions about whether a region error will be reported that are used in + /// coherence and elsewhere -- see #56105 and #59490 for more details. The + /// eventual fate of the leak checker is not yet settled. /// - /// NB. Although `_snapshot` isn't used, it's passed in to prove - /// that we are in a snapshot, which guarantees that we can just - /// search the "undo log" for edges. This is mostly an efficiency - /// thing -- we could search *all* region constraints, but that'd be - /// a bigger set and the data structures are not setup for that. If - /// we wind up keeping some form of this check long term, it would - /// probably be better to remove the snapshot parameter and to - /// refactor the constraint set. + /// The leak checker works by searching for the following error patterns: + /// + /// * P1: P2, where P1 != P2 + /// * P1: R, where R is in some universe that cannot name P1 + /// + /// The idea here is that each of these patterns represents something that + /// the region solver would eventually report as an error, so we can detect + /// the error early. There is a fly in the ointment, though, in that this is + /// not entirely true. In particular, in the future, we may extend the + /// environment with implied bounds or other info about how placeholders + /// relate to regions in outer universes. In that case, `P1: R` for example + /// might become solveable. + /// + /// # Summary of the implementation + /// + /// The leak checks as follows. First, we construct a graph where `R2: R1` + /// implies `R2 -> R1`, and we compute the SCCs. + /// + /// For each SCC S, we compute: + /// + /// * what placeholder P it must be equal to, if any + /// * if there are multiple placeholders that must be equal, report an error because `P1: P2` + /// * the minimum universe of its constituents + /// + /// Then we walk the SCCs in dependency order and compute + /// + /// * what placeholder they must outlive transitively + /// * if they must also be equal to a placeholder, report an error because `P1: P2` + /// * minimum universe U of all SCCs they must outlive + /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that + /// indicates `P: R` and `R` is in an incompatible universe + /// + /// # Historical note + /// + /// Older variants of the leak check used to report errors for these + /// patterns, but we no longer do: + /// + /// * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n + /// * R: P1, R: P2, as above pub fn leak_check( &mut self, tcx: TyCtxt<'tcx>, overly_polymorphic: bool, - placeholder_map: &PlaceholderMap<'tcx>, - _snapshot: &CombinedSnapshot<'_, 'tcx>, + max_universe: ty::UniverseIndex, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> RelateResult<'tcx, ()> { - debug!("leak_check(placeholders={:?})", placeholder_map); + debug!( + "leak_check(max_universe={:?}, snapshot.universe={:?}, overly_polymorphic={:?})", + max_universe, snapshot.universe, overly_polymorphic + ); assert!(UndoLogs::>::in_snapshot(&self.undo_log)); - // Go through each placeholder that we created. - for &placeholder_region in placeholder_map.values() { - // Find the universe this placeholder inhabits. - let placeholder = match placeholder_region { - ty::RePlaceholder(p) => p, - _ => bug!("leak_check: expected placeholder found {:?}", placeholder_region,), - }; - - // Find all regions that are related to this placeholder - // in some way. This means any region that either outlives - // or is outlived by a placeholder. - let mut taint_set = TaintSet::new(TaintDirections::both(), placeholder_region); - taint_set.fixed_point( - tcx, - self.undo_log.region_constraints(), - &self.storage.data.verifys, - ); - let tainted_regions = taint_set.into_set(); - - // Report an error if two placeholders in the same universe - // are related to one another, or if a placeholder is related - // to something from a parent universe. - for &tainted_region in &tainted_regions { - if let ty::RePlaceholder(_) = tainted_region { - // Two placeholders cannot be related: - if tainted_region == placeholder_region { - continue; - } - } else if self.universe(tainted_region).can_name(placeholder.universe) { - continue; - } - - return Err(if overly_polymorphic { - debug!("overly polymorphic!"); - TypeError::RegionsOverlyPolymorphic(placeholder.name, tainted_region) - } else { - debug!("not as polymorphic!"); - TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, tainted_region) - }); - } + let universe_at_start_of_snapshot = snapshot.universe; + if universe_at_start_of_snapshot == max_universe { + return Ok(()); } + let mini_graph = + &MiniGraph::new(tcx, self.undo_log.region_constraints(), &self.storage.data.verifys); + + let mut leak_check = LeakCheck::new( + tcx, + universe_at_start_of_snapshot, + max_universe, + overly_polymorphic, + mini_graph, + self, + ); + leak_check.assign_placeholder_values()?; + leak_check.propagate_scc_value()?; Ok(()) } } -#[derive(Debug)] -struct TaintSet<'tcx> { - directions: TaintDirections, - regions: FxHashSet>, +struct LeakCheck<'me, 'tcx> { + tcx: TyCtxt<'tcx>, + universe_at_start_of_snapshot: ty::UniverseIndex, + overly_polymorphic: bool, + mini_graph: &'me MiniGraph<'tcx>, + rcc: &'me RegionConstraintCollector<'me, 'tcx>, + + // Initially, for each SCC S, stores a placeholder `P` such that `S = P` + // must hold. + // + // Later, during the [`LeakCheck::propagate_scc_value`] function, this array + // is repurposed to store some placeholder `P` such that the weaker + // condition `S: P` must hold. (This is true if `S: S1` transitively and `S1 + // = P`.) + scc_placeholders: IndexVec>, + + // For each SCC S, track the minimum universe that flows into it. Note that + // this is both the minimum of the universes for every region that is a + // member of the SCC, but also if you have `R1: R2`, then the universe of + // `R2` must be less than the universe of `R1` (i.e., `R1` flows `R2`). To + // see that, imagine that you have `P1: R` -- in that case, `R` must be + // either the placeholder `P1` or the empty region in that same universe. + // + // To detect errors, we look for an SCC S where the values in + // `scc_values[S]` (if any) cannot be stored into `scc_universes[S]`. + scc_universes: IndexVec>, } -impl<'tcx> TaintSet<'tcx> { - fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { - let mut regions = FxHashSet::default(); - regions.insert(initial_region); - TaintSet { directions, regions } +impl<'me, 'tcx> LeakCheck<'me, 'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + universe_at_start_of_snapshot: ty::UniverseIndex, + max_universe: ty::UniverseIndex, + overly_polymorphic: bool, + mini_graph: &'me MiniGraph<'tcx>, + rcc: &'me RegionConstraintCollector<'me, 'tcx>, + ) -> Self { + let dummy_scc_universe = SccUniverse { universe: max_universe, region: None }; + Self { + tcx, + universe_at_start_of_snapshot, + overly_polymorphic, + mini_graph, + rcc, + scc_placeholders: IndexVec::from_elem_n(None, mini_graph.sccs.num_sccs()), + scc_universes: IndexVec::from_elem_n(dummy_scc_universe, mini_graph.sccs.num_sccs()), + } + } + + /// Compute what placeholders (if any) each SCC must be equal to. + /// Also compute the minimum universe of all the regions in each SCC. + fn assign_placeholder_values(&mut self) -> RelateResult<'tcx, ()> { + // First walk: find each placeholder that is from a newly created universe. + for (region, leak_check_node) in &self.mini_graph.nodes { + let scc = self.mini_graph.sccs.scc(*leak_check_node); + + // Set the universe of each SCC to be the minimum of its constituent universes + let universe = self.rcc.universe(region); + debug!( + "assign_placeholder_values: scc={:?} universe={:?} region={:?}", + scc, universe, region + ); + self.scc_universes[scc].take_min(universe, region); + + // Detect those SCCs that directly contain a placeholder + if let ty::RePlaceholder(placeholder) = region { + if self.universe_at_start_of_snapshot.cannot_name(placeholder.universe) { + self.assign_scc_value(scc, *placeholder)?; + } + } + } + + Ok(()) } - fn fixed_point<'a>( + // assign_scc_value(S, P): Update `scc_values` to account for the fact that `P: S` must hold. + // This may create an error. + fn assign_scc_value( &mut self, - tcx: TyCtxt<'tcx>, - undo_log: impl IntoIterator> + Clone, - verifys: &[Verify<'tcx>], - ) where - 'tcx: 'a, - { - let mut prev_len = 0; - while prev_len < self.len() { - debug!("tainted: prev_len = {:?} new_len = {:?}", prev_len, self.len()); - - prev_len = self.len(); - - for undo_entry in undo_log.clone() { - match undo_entry { - &AddConstraint(Constraint::VarSubVar(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::RegSubVar(a, b)) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::VarSubReg(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), b); - } - &AddConstraint(Constraint::RegSubReg(a, b)) => { - self.add_edge(a, b); - } - &AddGiven(a, b) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddVerify(i) => span_bug!( - verifys[i].origin.span(), - "we never add verifications while doing higher-ranked things", - ), - &AddCombination(..) | &AddVar(..) => {} + scc: LeakCheckScc, + placeholder: ty::PlaceholderRegion, + ) -> RelateResult<'tcx, ()> { + match self.scc_placeholders[scc] { + Some(p) => { + assert_ne!(p, placeholder); + return Err(self.placeholder_error(p, placeholder)); + } + None => { + self.scc_placeholders[scc] = Some(placeholder); + } + }; + + Ok(()) + } + + /// For each SCC S, iterate over each successor S1 where `S: S1`: + /// + /// * Compute + /// Iterate over each SCC `S` and ensure that, for each `S1` where `S1: S`, + /// `universe(S) <= universe(S1)`. This executes after + /// `assign_placeholder_values`, so `universe(S)` is already the minimum + /// universe of any of its direct constituents. + fn propagate_scc_value(&mut self) -> RelateResult<'tcx, ()> { + // Loop invariants: + // + // On start of the loop iteration for `scc1`: + // + // * `scc_universes[scc1]` contains the minimum universe of the + // constituents of `scc1` + // * `scc_placeholder[scc1]` stores the placeholder that `scc1` must + // be equal to (if any) + // + // For each succssor `scc2` where `scc1: scc2`: + // + // * `scc_placeholder[scc2]` stores some placeholder `P` where + // `scc2: P` (if any) + // * `scc_universes[scc2]` contains the minimum universe of the + // constituents of `scc2` and any of its successors + for scc1 in self.mini_graph.sccs.all_sccs() { + debug!( + "propagate_scc_value: scc={:?} with universe {:?}", + scc1, self.scc_universes[scc1] + ); + + // Walk over each `scc2` such that `scc1: scc2` and compute: + // + // * `scc1_universe`: the minimum universe of `scc2` and the constituents of `scc1` + // * `succ_bound`: placeholder `P` that the successors must outlive, if any (if there are multiple, + // we pick one arbitrarily) + let mut scc1_universe = self.scc_universes[scc1]; + let mut succ_bound = None; + for &scc2 in self.mini_graph.sccs.successors(scc1) { + let SccUniverse { universe: scc2_universe, region: scc2_region } = + self.scc_universes[scc2]; + + scc1_universe.take_min(scc2_universe, scc2_region.unwrap()); + + if let Some(b) = self.scc_placeholders[scc2] { + succ_bound = Some(b); } } + + // Update minimum universe of scc1. + self.scc_universes[scc1] = scc1_universe; + + // At this point, `scc_placholder[scc1]` stores the placeholder that + // `scc1` must be equal to, if any. + if let Some(scc1_placeholder) = self.scc_placeholders[scc1] { + debug!( + "propagate_scc_value: scc1={:?} placeholder={:?} scc1_universe={:?}", + scc1, scc1_placeholder, scc1_universe + ); + + // Check if `P1: R` for some `R` in a universe that cannot name + // P1. That's an error. + if scc1_universe.universe.cannot_name(scc1_placeholder.universe) { + return Err(self.error(scc1_placeholder, scc1_universe.region.unwrap())); + } + + // Check if we have some placeholder where `S: P2` + // (transitively). In that case, since `S = P1`, that implies + // `P1: P2`, which is an error condition. + if let Some(scc2_placeholder) = succ_bound { + assert_ne!(scc1_placeholder, scc2_placeholder); + return Err(self.placeholder_error(scc1_placeholder, scc2_placeholder)); + } + } else { + // Otherwise, we can reach a placeholder if some successor can. + self.scc_placeholders[scc1] = succ_bound; + } + + // At this point, `scc_placeholder[scc1]` stores some placeholder that `scc1` must outlive (if any). } + Ok(()) } - fn into_set(self) -> FxHashSet> { - self.regions + fn placeholder_error( + &self, + placeholder1: ty::PlaceholderRegion, + placeholder2: ty::PlaceholderRegion, + ) -> TypeError<'tcx> { + self.error(placeholder1, self.tcx.mk_region(ty::RePlaceholder(placeholder2))) } - fn len(&self) -> usize { - self.regions.len() + fn error( + &self, + placeholder: ty::PlaceholderRegion, + other_region: ty::Region<'tcx>, + ) -> TypeError<'tcx> { + debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region); + if self.overly_polymorphic { + return TypeError::RegionsOverlyPolymorphic(placeholder.name, other_region); + } else { + return TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, other_region); + } } +} - fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) { - if self.directions.incoming { - if self.regions.contains(&target) { - self.regions.insert(source); - } +// States we need to distinguish: +// +// * must be equal to a placeholder (i.e., a placeholder is in the SCC) +// * it could conflict with some other regions in the SCC in different universes +// * or a different placeholder +// * `P1: S` and `S` must be equal to a placeholder +// * `P1: S` and `S` is in an incompatible universe +// +// So if we +// +// (a) compute which placeholder (if any) each SCC must be equal to +// (b) compute its minimum universe +// (c) compute *some* placeholder where `S: P1` (any one will do) +// +// then we get an error if: +// +// - it must be equal to a placeholder `P1` and minimum universe cannot name `P1` +// - `S: P1` and minimum universe cannot name `P1` +// - `S: P1` and we must be equal to `P2` +// +// So we want to track: +// +// * Equal placeholder (if any) +// * Some bounding placeholder (if any) +// * Minimum universe +// +// * We compute equal placeholder + minimum universe of constituents in first pass +// * Then we walk in order and compute from our dependencies `S1` where `S: S1` (`S -> S1`) +// * bounding placeholder (if any) +// * minimum universe +// * And if we must be equal to a placeholder then we check it against +// * minimum universe +// * no bounding placeholder + +/// Tracks the "minimum universe" for each SCC, along with some region that +/// caused it to change. +#[derive(Copy, Clone, Debug)] +struct SccUniverse<'tcx> { + /// For some SCC S, the minimum universe of: + /// + /// * each region R in S + /// * each SCC S1 such that S: S1 + universe: ty::UniverseIndex, + + /// Some region that caused `universe` to be what it is. + region: Option>, +} + +impl<'tcx> SccUniverse<'tcx> { + /// If `universe` is less than our current universe, then update + /// `self.universe` and `self.region`. + fn take_min(&mut self, universe: ty::UniverseIndex, region: ty::Region<'tcx>) { + if universe < self.universe || self.region.is_none() { + self.universe = universe; + self.region = Some(region); } + } +} + +rustc_index::newtype_index! { + struct LeakCheckNode { + DEBUG_FORMAT = "LeakCheckNode({})" + } +} - if self.directions.outgoing { - if self.regions.contains(&source) { - self.regions.insert(target); +rustc_index::newtype_index! { + struct LeakCheckScc { + DEBUG_FORMAT = "LeakCheckScc({})" + } +} + +/// Represents the graph of constraints. For each `R1: R2` constraint we create +/// an edge `R1 -> R2` in the graph. +struct MiniGraph<'tcx> { + /// Map from a region to the index of the node in the graph. + nodes: FxHashMap, LeakCheckNode>, + + /// Map from node index to SCC, and stores the successors of each SCC. All + /// the regions in the same SCC are equal to one another, and if `S1 -> S2`, + /// then `S1: S2`. + sccs: Sccs, +} + +impl<'tcx> MiniGraph<'tcx> { + fn new<'a>( + tcx: TyCtxt<'tcx>, + undo_log: impl Iterator>, + verifys: &[Verify<'tcx>], + ) -> Self + where + 'tcx: 'a, + { + let mut nodes = FxHashMap::default(); + let mut edges = Vec::new(); + + // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter. + Self::iterate_undo_log(tcx, undo_log, verifys, |target, source| { + let source_node = Self::add_node(&mut nodes, source); + let target_node = Self::add_node(&mut nodes, target); + edges.push((source_node, target_node)); + }); + let graph = VecGraph::new(nodes.len(), edges); + let sccs = Sccs::new(&graph); + Self { nodes, sccs } + } + + /// Invokes `each_edge(R1, R2)` for each edge where `R2: R1` + fn iterate_undo_log<'a>( + tcx: TyCtxt<'tcx>, + undo_log: impl Iterator>, + verifys: &[Verify<'tcx>], + mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>), + ) where + 'tcx: 'a, + { + for undo_entry in undo_log { + match undo_entry { + &AddConstraint(Constraint::VarSubVar(a, b)) => { + each_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::RegSubVar(a, b)) => { + each_edge(a, tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::VarSubReg(a, b)) => { + each_edge(tcx.mk_region(ReVar(a)), b); + } + &AddConstraint(Constraint::RegSubReg(a, b)) => { + each_edge(a, b); + } + &AddGiven(a, b) => { + each_edge(a, tcx.mk_region(ReVar(b))); + } + &AddVerify(i) => span_bug!( + verifys[i].origin.span(), + "we never add verifications while doing higher-ranked things", + ), + &AddCombination(..) | &AddVar(..) => {} } } } + + fn add_node( + nodes: &mut FxHashMap, LeakCheckNode>, + r: ty::Region<'tcx>, + ) -> LeakCheckNode { + let l = nodes.len(); + *nodes.entry(r).or_insert(LeakCheckNode::new(l)) + } } diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index ed04ee02b7203..0f3f3db867959 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -16,6 +16,9 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_fn)] +#![feature(const_if_match)] +#![feature(const_panic)] #![feature(extend_one)] #![feature(never_type)] #![feature(or_patterns)] diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 56f4ae9e9848b..fb9565e4b9825 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -38,6 +38,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathHash, Definitions}; +use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::{self, PanicLocationLangItem}; use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; @@ -1427,10 +1428,8 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn return_type_impl_or_dyn_trait( - &self, - scope_def_id: DefId, - ) -> Option<&'tcx hir::Ty<'tcx>> { + /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type. + pub fn return_type_impl_or_dyn_traits(&self, scope_def_id: DefId) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local()); let hir_output = match self.hir().get(hir_id) { Node::Item(hir::Item { @@ -1466,30 +1465,12 @@ impl<'tcx> TyCtxt<'tcx> { ), .. }) => ty, - _ => return None, + _ => return vec![], }; - let ret_ty = self.type_of(scope_def_id); - match ret_ty.kind { - ty::FnDef(_, _) => { - let sig = ret_ty.fn_sig(*self); - let output = self.erase_late_bound_regions(&sig.output()); - if output.is_impl_trait() { - let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); - if let hir::FnRetTy::Return(ty) = fn_decl.output { - return Some(ty); - } - } else { - let mut v = TraitObjectVisitor(vec![]); - rustc_hir::intravisit::walk_ty(&mut v, hir_output); - if v.0.len() == 1 { - return Some(v.0[0]); - } - } - None - } - _ => None, - } + let mut v = TraitObjectVisitor(vec![], self.hir()); + v.visit_ty(hir_output); + v.0 } pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> { diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index a2812e117ed39..b22727bdd7587 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -236,7 +236,9 @@ pub fn suggest_constraining_type_param( } } -pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>); +/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. +pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>); + impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { type Map = rustc_hir::intravisit::ErasedMap<'v>; @@ -245,15 +247,24 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { } fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { - if let hir::TyKind::TraitObject( - _, - hir::Lifetime { - name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, - .. - }, - ) = ty.kind - { - self.0.push(ty); + match ty.kind { + hir::TyKind::TraitObject( + _, + hir::Lifetime { + name: + hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, + .. + }, + ) => { + self.0.push(ty); + } + hir::TyKind::OpaqueDef(item_id, _) => { + self.0.push(ty); + let item = self.1.expect_item(item_id.id); + hir::intravisit::walk_item(self, item); + } + _ => {} } + hir::intravisit::walk_ty(self, ty); } } diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index 7ff12820db815..285d9ed64691a 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -25,7 +25,7 @@ pub(super) fn relate_types<'tcx>( category: ConstraintCategory, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, ) -> Fallible<()> { - debug!("eq_types(a={:?}, b={:?}, locations={:?})", a, b, locations); + debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations); TypeRelating::new( infcx, NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 31bdc45a2eab9..6ac1e6be03674 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -296,6 +296,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self); self.write_scalar(offset_ptr, dest)?; } + sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => { + // FIXME: return `true` for at least some comparisons where we can reliably + // determine the result of runtime (in)equality tests at compile-time. + self.write_scalar(Scalar::from_bool(false), dest)?; + } sym::ptr_offset_from => { let a = self.read_immediate(args[0])?.to_scalar()?; let b = self.read_immediate(args[1])?.to_scalar()?; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 36f3947d83017..e51d9ba9c021d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1,7 +1,7 @@ //! Mono Item Collection //! ==================== //! -//! This module is responsible for discovering all items that will contribute to +//! This module is responsible for discovering all items that will contribute //! to code generation of the crate. The important part here is that it not only //! needs to find syntax-level items (functions, structs, etc) but also all //! their monomorphized instantiations. Every non-generic, non-const function @@ -79,7 +79,7 @@ //! function or method call (represented by a CALL terminator in MIR). But //! calls are not the only thing that might introduce a reference between two //! function mono items, and as we will see below, they are just a -//! specialized of the form described next, and consequently will don't get any +//! specialization of the form described next, and consequently will not get any //! special treatment in the algorithm. //! //! #### Taking a reference to a function or method @@ -158,7 +158,7 @@ //! - Eager mode is meant to be used in conjunction with incremental compilation //! where a stable set of mono items is more important than a minimal //! one. Thus, eager mode will instantiate drop-glue for every drop-able type -//! in the crate, even of no drop call for that type exists (yet). It will +//! in the crate, even if no drop call for that type exists (yet). It will //! also instantiate default implementations of trait methods, something that //! otherwise is only done on demand. //! diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 733ae9084511c..676688daf1c6d 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -160,17 +160,20 @@ pub struct InlineAsm; impl NonConstOp for InlineAsm {} #[derive(Debug)] -pub struct LiveDrop; +pub struct LiveDrop(pub Option); impl NonConstOp for LiveDrop { fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - struct_span_err!( + let mut diagnostic = struct_span_err!( ccx.tcx.sess, span, E0493, "destructors cannot be evaluated at compile-time" - ) - .span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind())) - .emit(); + ); + diagnostic.span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind())); + if let Some(span) = self.0 { + diagnostic.span_label(span, "value is dropped here"); + } + diagnostic.emit(); } } @@ -296,18 +299,16 @@ impl NonConstOp for Panic { #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { - fn feature_gate() -> Option { - Some(sym::const_compare_raw_pointers) - } - fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_compare_raw_pointers, - span, - &format!("comparing raw pointers inside {}", ccx.const_kind()), - ) - .emit(); + let mut err = ccx + .tcx + .sess + .struct_span_err(span, "pointers cannot be reliably compared during const eval."); + err.note( + "see issue #53020 \ + for more information", + ); + err.emit(); } } diff --git a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs index 124606fb423e6..1fd907f89fe18 100644 --- a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs +++ b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs @@ -58,7 +58,7 @@ impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { impl CheckLiveDrops<'mir, 'tcx> { fn check_live_drop(&self, span: Span) { - ops::non_const(self.ccx, ops::LiveDrop, span); + ops::non_const(self.ccx, ops::LiveDrop(None), span); } } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 35a8df62cb83a..d263bf12e8868 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -588,7 +588,10 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { }; if needs_drop { - self.check_op_spanned(ops::LiveDrop, err_span); + self.check_op_spanned( + ops::LiveDrop(Some(terminator.source_info.span)), + err_span, + ); } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 9898cde520778..b8f725e967ddb 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -171,21 +171,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { _ => {} } } - // raw pointer and fn pointer operations are unsafe as it is not clear whether one - // pointer would be "less" or "equal" to another, because we cannot know where llvm - // or the linker will place various statics in memory. Without this information the - // result of a comparison of addresses would differ between runtime and compile-time. - Rvalue::BinaryOp(_, ref lhs, _) - if self.const_context && self.tcx.features().const_compare_raw_pointers => - { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { - self.require_unsafe( - "pointer operation", - "operations on pointers in constants", - UnsafetyViolationKind::General, - ); - } - } _ => {} } self.super_rvalue(rvalue, location); diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 970a26325926c..06d1f36622b94 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -588,6 +588,8 @@ symbols! { proc_macro_non_items, proc_macro_path_invoc, profiler_runtime, + ptr_guaranteed_eq, + ptr_guaranteed_ne, ptr_offset_from, pub_restricted, pure, diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs index 706cbf058b713..3ec7fe2bf25c6 100644 --- a/src/librustc_trait_selection/traits/coherence.rs +++ b/src/librustc_trait_selection/traits/coherence.rs @@ -120,12 +120,13 @@ fn overlap<'cx, 'tcx>( debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { - overlap_within_probe(selcx, a_def_id, b_def_id, snapshot) + overlap_within_probe(selcx, skip_leak_check, a_def_id, b_def_id, snapshot) }) } fn overlap_within_probe( selcx: &mut SelectionContext<'cx, 'tcx>, + skip_leak_check: SkipLeakCheck, a_def_id: DefId, b_def_id: DefId, snapshot: &CombinedSnapshot<'_, 'tcx>, @@ -180,6 +181,13 @@ fn overlap_within_probe( return None; } + if !skip_leak_check.is_yes() { + if let Err(_) = infcx.leak_check(true, snapshot) { + debug!("overlap: leak check failed"); + return None; + } + } + let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 574d50a4fccc2..bc696214cbc66 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -149,15 +149,12 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>( debug!("poly_project_and_unify_type(obligation={:?})", obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|snapshot| { - let (placeholder_predicate, placeholder_map) = + infcx.commit_if_ok(|_snapshot| { + let (placeholder_predicate, _) = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation = obligation.with(placeholder_predicate); let result = project_and_unify_type(selcx, &placeholder_obligation)?; - infcx - .leak_check(false, &placeholder_map, snapshot) - .map_err(|err| MismatchedProjectionTypes { err })?; Ok(result) }) } diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 9045451056b19..4dab5814f7b7e 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -163,9 +163,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, } - let result = self.infcx.probe(|snapshot| { - self.match_projection_obligation_against_definition_bounds(obligation, snapshot) - }); + let result = self + .infcx + .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); if result { candidates.vec.push(ProjectionCandidate); @@ -345,8 +345,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.infcx.probe(|snapshot| { - if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) { + self.infcx.probe(|_| { + if let Ok(_substs) = self.match_impl(impl_def_id, obligation) { candidates.vec.push(ImplCandidate(impl_def_id)); } }); diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs index 50c04e8fc3452..834bf17227d2e 100644 --- a/src/librustc_trait_selection/traits/select/confirmation.rs +++ b/src/librustc_trait_selection/traits/select/confirmation.rs @@ -121,9 +121,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.commit_unconditionally(|snapshot| { - let result = - self.match_projection_obligation_against_definition_bounds(obligation, snapshot); + self.infcx.commit_unconditionally(|_| { + let result = self.match_projection_obligation_against_definition_bounds(obligation); assert!(result); }) } @@ -265,8 +264,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.commit_unconditionally(|snapshot| { - let substs = self.rematch_impl(impl_def_id, obligation, snapshot); + self.infcx.commit_unconditionally(|_| { + let substs = self.rematch_impl(impl_def_id, obligation); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); ensure_sufficient_stack(|| { @@ -612,24 +611,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. - // - // FIXME: This condition is arguably too strong -- it would - // suffice for the source trait to be a *subtype* of the target - // trait. In particular, changing from something like - // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be - // permitted. And, indeed, in the in commit - // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this - // condition was loosened. However, when the leak check was - // added back, using subtype here actually guides the coercion - // code in such a way that it accepts `old-lub-glb-object.rs`. - // This is probably a good thing, but I've modified this to `.eq` - // because I want to continue rejecting that test (as we have - // done for quite some time) before we are firmly comfortable - // with what our behavior should be there. -nikomatsakis let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(target, source_trait) // FIXME -- see below + .sup(target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index 076bdad423ab8..cff5efbfd0fd1 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -21,7 +21,7 @@ use super::{Normalized, ProjectionCacheKey}; use super::{ObligationCause, PredicateObligation, TraitObligation}; use super::{Overflow, SelectionError, Unimplemented}; -use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; +use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectionCacheKeyExt; use rustc_ast::attr; @@ -347,6 +347,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { self.infcx.probe(|snapshot| -> Result { let result = op(self)?; + + match self.infcx.leak_check(true, snapshot) { + Ok(()) => {} + Err(_) => return Ok(EvaluatedToErr), + } + match self.infcx.region_constraints_added_in_snapshot(snapshot) { None => Ok(result), Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)), @@ -1262,10 +1268,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); - let (placeholder_trait_predicate, placeholder_map) = + let (placeholder_trait_predicate, _) = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ @@ -1293,13 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::PredicateKind::Trait(bound, _) = bound.kind() { let bound = bound.to_poly_trait_ref(); if self.infcx.probe(|_| { - self.match_projection( - obligation, - bound, - placeholder_trait_predicate.trait_ref, - &placeholder_map, - snapshot, - ) + self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref) }) { return Some(bound); } @@ -1316,13 +1315,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => false, Some(bound) => { // Repeat the successful match, if any, this time outside of a probe. - let result = self.match_projection( - obligation, - bound, - placeholder_trait_predicate.trait_ref, - &placeholder_map, - snapshot, - ); + let result = + self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref); assert!(result); true @@ -1335,15 +1329,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, - placeholder_map: &PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() - && self.infcx.leak_check(false, placeholder_map, snapshot).is_ok() } fn evaluate_where_clause<'o>( @@ -1808,9 +1799,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Normalized<'tcx, SubstsRef<'tcx>> { - match self.match_impl(impl_def_id, obligation, snapshot) { + match self.match_impl(impl_def_id, obligation) { Ok(substs) => substs, Err(()) => { bug!( @@ -1826,7 +1816,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Result>, ()> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); @@ -1837,7 +1826,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let (placeholder_obligation, placeholder_map) = + let (placeholder_obligation, _) = self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; @@ -1869,11 +1858,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); - if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) { - debug!("match_impl: failed leak check due to `{}`", e); - return Err(()); - } - if !self.intercrate && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 33d57e2571173..1b08bf2fc7710 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -8,8 +8,7 @@ use crate::collect::PlaceholderHirTyCollector; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; -use rustc_ast::ast::ParamKindOrd; -use rustc_ast::util::lev_distance::find_best_match_for_name; +use rustc_ast::{ast::ParamKindOrd, util::lev_distance::find_best_match_for_name}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::ErrorReported; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, FatalError}; @@ -27,7 +26,7 @@ use rustc_middle::ty::{GenericParamDef, GenericParamDefKind}; use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; use rustc_session::parse::feature_err; use rustc_session::Session; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits; @@ -475,7 +474,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Report an error that a generic argument did not match the generic parameter that was /// expected. - fn generic_arg_mismatch_err(sess: &Session, arg: &GenericArg<'_>, kind: &'static str) { + fn generic_arg_mismatch_err( + sess: &Session, + arg: &GenericArg<'_>, + kind: &'static str, + help: Option<&str>, + ) { let mut err = struct_span_err!( sess, arg.span(), @@ -503,6 +507,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (first, last) = if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) }; err.note(&format!("{} arguments must be provided before {} arguments", first, last)); + + if let Some(help) = help { + err.help(help); + } err.emit(); } @@ -648,7 +656,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if arg_count.correct.is_ok() && arg_count.explicit_late_bound == ExplicitLateBound::No { - Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr()); + // We're going to iterate over the parameters to sort them out, and + // show that order to the user as a possible order for the parameters + let mut param_types_present = defs + .params + .clone() + .into_iter() + .map(|param| { + ( + match param.kind { + GenericParamDefKind::Lifetime => { + ParamKindOrd::Lifetime + } + GenericParamDefKind::Type { .. } => { + ParamKindOrd::Type + } + GenericParamDefKind::Const => { + ParamKindOrd::Const + } + }, + param, + ) + }) + .collect::>(); + param_types_present.sort_by_key(|(ord, _)| *ord); + let (mut param_types_present, ordered_params): ( + Vec, + Vec, + ) = param_types_present.into_iter().unzip(); + param_types_present.dedup(); + + Self::generic_arg_mismatch_err( + tcx.sess, + arg, + kind.descr(), + Some(&format!( + "reorder the arguments: {}: `<{}>`", + param_types_present + .into_iter() + .map(|ord| format!("{}s", ord.to_string())) + .collect::>() + .join(", then "), + ordered_params + .into_iter() + .filter_map(|param| { + if param.name == kw::SelfUpper { + None + } else { + Some(param.name.to_string()) + } + }) + .collect::>() + .join(", ") + )), + ); } // We've reported the error, but we want to make sure that this @@ -680,7 +741,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert_eq!(kind, "lifetime"); let provided = force_infer_lt.expect("lifetimes ought to have been inferred"); - Self::generic_arg_mismatch_err(tcx.sess, provided, kind); + Self::generic_arg_mismatch_err(tcx.sess, provided, kind, None); } break; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index dec53c369bb18..b6cd8da236260 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -895,7 +895,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let prev_ty = self.resolve_vars_with_obligations(prev_ty); let new_ty = self.resolve_vars_with_obligations(new_ty); - debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty); + debug!( + "coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)", + prev_ty, + new_ty, + exprs.len() + ); // Special-case that coercion alone cannot handle: // Function items or non-capturing closures of differing IDs or InternalSubsts. @@ -1001,6 +1006,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(ok) => { let (adjustments, target) = self.register_infer_ok_obligations(ok); self.apply_adjustments(new, adjustments); + debug!( + "coercion::try_find_coercion_lub: was able to coerce from previous type {:?} to new type {:?}", + prev_ty, new_ty, + ); return Ok(target); } Err(e) => first_error = Some(e), @@ -1031,6 +1040,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if !noop { + debug!( + "coercion::try_find_coercion_lub: older expression {:?} had adjustments, requiring LUB", + expr, + ); + return self .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) .map(|ok| self.register_infer_ok_obligations(ok)); @@ -1048,6 +1062,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } Ok(ok) => { + debug!( + "coercion::try_find_coercion_lub: was able to coerce previous type {:?} to new type {:?}", + prev_ty, new_ty, + ); let (adjustments, target) = self.register_infer_ok_obligations(ok); for expr in exprs { let expr = expr.as_coercion_site(); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 3ec6973a17d56..ef6c7c14404a7 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -74,9 +74,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely" - | "minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64" | "type_name" => { - hir::Unsafety::Normal - } + | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32" + | "maxnumf64" | "type_name" => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, } } @@ -258,6 +257,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool])) } + "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { + (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool) + } + "ptr_offset_from" => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) } diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index cf5f2ec69d8d8..3dd9c9c5c39db 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -10,8 +10,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits; @@ -303,25 +302,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty), GenericParamKind::Const { ty: ref hir_ty, .. } => { let ty = icx.to_ty(hir_ty); - if !tcx.features().const_compare_raw_pointers { - let err = match ty.peel_refs().kind { - ty::FnPtr(_) => Some("function pointers"), - ty::RawPtr(_) => Some("raw pointers"), - _ => None, - }; - if let Some(unsupported_type) = err { - feature_err( - &tcx.sess.parse_sess, - sym::const_compare_raw_pointers, + let err = match ty.peel_refs().kind { + ty::FnPtr(_) => Some("function pointers"), + ty::RawPtr(_) => Some("raw pointers"), + _ => None, + }; + if let Some(unsupported_type) = err { + tcx.sess + .struct_span_err( hir_ty.span, &format!( - "using {} as const generic parameters is unstable", + "using {} as const generic parameters is forbidden", unsupported_type ), ) .emit(); - }; - } + }; if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty) .is_some() { diff --git a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir index 9742530bd812f..aeb38f3f91068 100644 --- a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -12,7 +12,7 @@ | 8: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24 | 9: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24 | 10: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:18:5: 18:18 -| 11: Canonical { max_universe: U3, variables: [CanonicalVarInfo { kind: Region(U3) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25 +| 11: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25 | 12: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20 | 13: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20 | 14: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) } at $DIR/address-of.rs:24:12: 24:28 @@ -22,7 +22,7 @@ | 18: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24 | 19: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24 | 20: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:28:5: 28:16 -| 21: Canonical { max_universe: U6, variables: [CanonicalVarInfo { kind: Region(U6) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23 +| 21: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23 | 22: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18 | 23: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18 | 24: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) } at $DIR/address-of.rs:34:12: 34:26 diff --git a/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr new file mode 100644 index 0000000000000..25e9f726ba53a --- /dev/null +++ b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr @@ -0,0 +1,33 @@ +error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` + --> $DIR/associated-types-eq-hr.rs:87:5 + | +LL | fn foo() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>, + | ------------- required by this bound in `foo` +... +LL | foo::(); + | ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` + | + = note: expected reference `&isize` + found reference `&usize` + +error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` + --> $DIR/associated-types-eq-hr.rs:91:5 + | +LL | fn bar() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, + | ------------- required by this bound in `bar` +... +LL | bar::(); + | ^^^^^^^^^^^^^^^^ expected `usize`, found `isize` + | + = note: expected reference `&usize` + found reference `&isize` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index e6afa3f71c2f0..fb391913c321e 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -7,7 +7,7 @@ pub trait TheTrait { } struct IntStruct { - x: isize + x: isize, } impl<'a> TheTrait<&'a isize> for IntStruct { @@ -19,7 +19,7 @@ impl<'a> TheTrait<&'a isize> for IntStruct { } struct UintStruct { - x: isize + x: isize, } impl<'a> TheTrait<&'a isize> for UintStruct { @@ -30,8 +30,7 @@ impl<'a> TheTrait<&'a isize> for UintStruct { } } -struct Tuple { -} +struct Tuple {} impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { type A = &'a isize; @@ -42,37 +41,43 @@ impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { } fn foo() - where T : for<'x> TheTrait<&'x isize, A = &'x isize> +where + T: for<'x> TheTrait<&'x isize, A = &'x isize>, { // ok for IntStruct, but not UintStruct } fn bar() - where T : for<'x> TheTrait<&'x isize, A = &'x usize> +where + T: for<'x> TheTrait<&'x isize, A = &'x usize>, { // ok for UintStruct, but not IntStruct } fn tuple_one() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, { // not ok for tuple, two lifetimes and we pick first } fn tuple_two() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, { // not ok for tuple, two lifetimes and we pick second } fn tuple_three() - where T : for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize> +where + T: for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>, { // ok for tuple } fn tuple_four() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, { // not ok for tuple, two lifetimes, and lifetime matching is invariant } @@ -89,14 +94,14 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); - //~^ ERROR not satisfied - //~| ERROR type mismatch + //~^ ERROR implementation of `TheTrait` is not general enough + //~| ERROR implementation of `TheTrait` is not general enough } pub fn call_tuple_two() { tuple_two::(); - //~^ ERROR not satisfied - //~| ERROR type mismatch + //~^ ERROR implementation of `TheTrait` is not general enough + //~| ERROR implementation of `TheTrait` is not general enough } pub fn call_tuple_three() { @@ -105,7 +110,7 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::(); - //~^ ERROR not satisfied + //~^ ERROR implementation of `TheTrait` is not general enough } -fn main() { } +fn main() {} diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 58d72746e76aa..127ab8673556d 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -1,10 +1,11 @@ error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:82:5 + --> $DIR/associated-types-eq-hr.rs:87:5 | LL | fn foo() | --- required by a bound in this -LL | where T : for<'x> TheTrait<&'x isize, A = &'x isize> - | ------------- required by this bound in `foo` +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>, + | ------------- required by this bound in `foo` ... LL | foo::(); | ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` @@ -13,12 +14,13 @@ LL | foo::(); found reference `&usize` error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` - --> $DIR/associated-types-eq-hr.rs:86:5 + --> $DIR/associated-types-eq-hr.rs:91:5 | LL | fn bar() | --- required by a bound in this -LL | where T : for<'x> TheTrait<&'x isize, A = &'x usize> - | ------------- required by this bound in `bar` +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, + | ------------- required by this bound in `bar` ... LL | bar::(); | ^^^^^^^^^^^^^^^^ expected `usize`, found `isize` @@ -26,71 +28,86 @@ LL | bar::(); = note: expected reference `&usize` found reference `&isize` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:91:17 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> - | ---------------------------------------------------------- required by this bound in `tuple_one` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_one::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | - = help: the following implementations were found: - > + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:91:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> - | ------------- required by this bound in `tuple_one` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:97:17 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:102:5 | -LL | fn tuple_two() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> - | ---------------------------------------------------------- required by this bound in `tuple_two` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_two::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | - = help: the following implementations were found: - > + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` - --> $DIR/associated-types-eq-hr.rs:97:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:102:5 | -LL | fn tuple_two() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> - | ------------- required by this bound in `tuple_two` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:107:18 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:112:5 | -LL | fn tuple_four() - | ---------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> - | ------------------------------------------- required by this bound in `tuple_four` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_four::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | - = help: the following implementations were found: - > + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr index 71a533a36f418..4fc336122fa9d 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr @@ -1,26 +1,26 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:55:4 + --> $DIR/project-fn-ret-invariant.rs:56:5 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | (a, b) - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:55:4 + --> $DIR/project-fn-ret-invariant.rs:56:5 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | (a, b) - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr index 5009e0868a7d4..9462121bdf203 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -1,23 +1,23 @@ error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:53:21 + --> $DIR/project-fn-ret-invariant.rs:54:22 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -LL | let a = bar(foo, y); - | ^ ...but data from `x` is returned here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +LL | let a = bar(foo, y); + | ^ ...but data from `x` is returned here error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:54:21 + --> $DIR/project-fn-ret-invariant.rs:56:9 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -LL | let a = bar(foo, y); -LL | let b = bar(foo, x); - | ^ ...but data from `y` is returned here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +... +LL | (a, b) + | ^ ...but data from `x` is returned here error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr index 8f445acf2b98c..2156ecb17393f 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr @@ -1,8 +1,8 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/project-fn-ret-invariant.rs:59:1 + --> $DIR/project-fn-ret-invariant.rs:60:1 | -LL | fn main() { } - | ^^^^^^^^^^^^^ +LL | fn main() {} + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr index c39030fbed1e1..44850df7b2f42 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr @@ -1,26 +1,26 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:38:12 + --> $DIR/project-fn-ret-invariant.rs:39:13 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let f = foo; // <-- No consistent type can be inferred for `f` here. -LL | let a = bar(f, x); - | ^^^^^^^^^ argument requires that `'a` must outlive `'b` +LL | let f = foo; // <-- No consistent type can be inferred for `f` here. +LL | let a = bar(f, x); + | ^^^^^^^^^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:39:12 + --> $DIR/project-fn-ret-invariant.rs:40:13 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | let b = bar(f, y); - | ^^^^^^^^^ argument requires that `'b` must outlive `'a` +LL | let b = bar(f, y); + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr index 65d16440ac9b0..64b5722390858 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -1,13 +1,13 @@ error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:39:19 + --> $DIR/project-fn-ret-invariant.rs:40:20 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... ... -LL | let b = bar(f, y); - | ^ ...but data from `x` is returned here +LL | let b = bar(f, y); + | ^ ...but data from `x` is returned here error: aborting due to previous error diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 23d873212ed1e..0034d796826de 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -1,60 +1,61 @@ #![feature(unboxed_closures)] #![feature(rustc_attrs)] - // Test for projection cache. We should be able to project distinct // lifetimes from `foo` as we reinstantiate it multiple times, but not // if we do it just once. In this variant, the region `'a` is used in // an invariant position, which affects the results. // revisions: ok oneuse transmute krisskross - #![allow(dead_code, unused_variables)] use std::marker::PhantomData; struct Type<'a> { // Invariant - data: PhantomData &'a u32> + data: PhantomData &'a u32>, } -fn foo<'a>() -> Type<'a> { loop { } } +fn foo<'a>() -> Type<'a> { + loop {} +} fn bar(t: T, x: T::Output) -> T::Output - where T: FnOnce<()> +where + T: FnOnce<()>, { t() } #[cfg(ok)] // two instantiations: OK -fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { let a = bar(foo, x); let b = bar(foo, y); (a, b) } #[cfg(oneuse)] // one instantiation: BAD -fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - let f = foo; // <-- No consistent type can be inferred for `f` here. - let a = bar(f, x); - let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623] - (a, b) +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let f = foo; // <-- No consistent type can be inferred for `f` here. + let a = bar(f, x); + let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623] + (a, b) } #[cfg(transmute)] // one instantiations: BAD -fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { - // Cannot instantiate `foo` with any lifetime other than `'a`, - // since it is provided as input. +fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { + // Cannot instantiate `foo` with any lifetime other than `'a`, + // since it is provided as input. - bar(foo, x) //[transmute]~ ERROR E0495 + bar(foo, x) //[transmute]~ ERROR E0495 } #[cfg(krisskross)] // two instantiations, mixing and matching: BAD -fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - let a = bar(foo, y); //[krisskross]~ ERROR E0623 - let b = bar(foo, x); //[krisskross]~ ERROR E0623 - (a, b) +fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let a = bar(foo, y); //[krisskross]~ ERROR E0623 + let b = bar(foo, x); + (a, b) //[krisskross]~ ERROR E0623 } #[rustc_error] -fn main() { } +fn main() {} //[ok]~^ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr index f74d4ba73bf4e..db82c9fd43794 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr @@ -1,11 +1,11 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:48:4 + --> $DIR/project-fn-ret-invariant.rs:49:5 | -LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | -- lifetime `'a` defined here ... -LL | bar(foo, x) - | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` +LL | bar(foo, x) + | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` | = help: consider replacing `'a` with `'static` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 0a05fc6bb8286..ef57f9e0bc480 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,27 +1,27 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/project-fn-ret-invariant.rs:48:4 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/project-fn-ret-invariant.rs:49:9 | -LL | bar(foo, x) - | ^^^^^^^^^^^ +LL | bar(foo, x) + | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8... - --> $DIR/project-fn-ret-invariant.rs:44:8 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8... + --> $DIR/project-fn-ret-invariant.rs:45:8 | -LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | ^^ note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:48:13 + --> $DIR/project-fn-ret-invariant.rs:49:14 | -LL | bar(foo, x) - | ^ +LL | bar(foo, x) + | ^ = note: expected `Type<'_>` found `Type<'a>` = note: but, the lifetime must be valid for the static lifetime... note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:48:4 + --> $DIR/project-fn-ret-invariant.rs:49:5 | -LL | bar(foo, x) - | ^^^^^^^^^^^ +LL | bar(foo, x) + | ^^^^^^^^^^^ = note: expected `Type<'static>` found `Type<'_>` diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr new file mode 100644 index 0000000000000..2e03986a9ed8f --- /dev/null +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/higher-ranked-projection.rs:25:5 + | +LL | foo(()); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 3b3e4c3ea117a..811c9a8f5e12b 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,14 +1,12 @@ -error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` +error[E0308]: mismatched types --> $DIR/higher-ranked-projection.rs:25:5 | -LL | fn foo(_t: T) - | --- required by a bound in this -LL | where for<'a> &'a T: Mirror - | ------- required by this bound in `foo` -... LL | foo(()); - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other + | + = note: expected type `&'a ()` + found type `&()` error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5315e21b0f5a9..1b5476d4c364f 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,5 +23,5 @@ fn foo(_t: T) #[rustc_error] fn main() { //[good]~ ERROR fatal error triggered by #[rustc_error] foo(()); - //[bad]~^ ERROR type mismatch + //[bad]~^ ERROR mismatched types } diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr index 6b5a739899cac..b00affdca850a 100644 --- a/src/test/ui/check-static-values-constraints.stderr +++ b/src/test/ui/check-static-values-constraints.stderr @@ -5,7 +5,9 @@ LL | ..SafeStruct{field1: SafeEnum::Va | ___________________________________________^ LL | | LL | | field2: SafeEnum::Variant1}}; - | |________________________________________________________________________________^ statics cannot evaluate destructors + | | ^- value is dropped here + | |________________________________________________________________________________| + | statics cannot evaluate destructors error[E0010]: allocations are not allowed in statics --> $DIR/check-static-values-constraints.rs:79:33 diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr index 97fdb76dd11c7..64a0b52a1fac5 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr @@ -1,42 +1,43 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:30:5 +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 | -LL | fn with_closure_expecting_fn_with_free_region(_: F) - | ------------------------------------------ required by a bound in this -LL | where F: for<'a> FnOnce(fn(&'a u32), &i32) - | ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region` +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here ... -LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `fn(fn(&'a u32), &i32) -> _` +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ + | | + | has type `fn(&'1 u32)` + | requires that `'1` must outlive `'x` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here ... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ requires that `'x` must outlive `'static` + | + = help: consider replacing `'x` with `'static` + +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:32:49 + | +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^ + +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:39:50 + | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:48:50 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` -... LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index a4e43da91baf8..c81c40c18b45b 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -1,10 +1,12 @@ fn with_closure_expecting_fn_with_free_region(_: F) - where F: for<'a> FnOnce(fn(&'a u32), &i32) +where + F: for<'a> FnOnce(fn(&'a u32), &i32), { } fn with_closure_expecting_fn_with_bound_region(_: F) - where F: FnOnce(fn(&u32), &i32) +where + F: FnOnce(fn(&u32), &i32), { } @@ -28,14 +30,14 @@ fn expect_free_supply_bound() { // Here, we are given a function whose region is bound at closure level, // but we expect one bound in the argument. Error results. with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - //~^ ERROR type mismatch + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { // Here, we are given a `fn(&u32)` but we expect a `fn(&'x // u32)`. In principle, this could be ok, but we demand equality. with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - //~^ ERROR type mismatch + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_closure() { @@ -44,7 +46,7 @@ fn expect_bound_supply_free_from_closure() { // the argument level. type Foo<'a> = fn(&'a u32); with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - //~^ ERROR type mismatch + //~^ ERROR mismatched types }); } @@ -52,8 +54,7 @@ fn expect_bound_supply_bound<'x>(x: &'x u32) { // No error in this case. The supplied type supplies the bound // regions, and hence we are able to figure out the type of `y` // from the expected type - with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| { - }); + with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {}); } -fn main() { } +fn main() {} diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index fae41c4114abc..0de15dfa7357d 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -1,81 +1,68 @@ error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:14:52 + --> $DIR/expect-fn-supply-fn.rs:16:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^ lifetime mismatch | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the anonymous lifetime #2 defined on the body at 14:48... - --> $DIR/expect-fn-supply-fn.rs:14:48 +note: the anonymous lifetime #2 defined on the body at 16:48... + --> $DIR/expect-fn-supply-fn.rs:16:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 11:36 - --> $DIR/expect-fn-supply-fn.rs:11:36 +note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 13:36 + --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { | ^^ error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:14:52 + --> $DIR/expect-fn-supply-fn.rs:16:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^ lifetime mismatch | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the lifetime `'x` as defined on the function body at 11:36... - --> $DIR/expect-fn-supply-fn.rs:11:36 +note: the lifetime `'x` as defined on the function body at 13:36... + --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { | ^^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 14:48 - --> $DIR/expect-fn-supply-fn.rs:14:48 +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 16:48 + --> $DIR/expect-fn-supply-fn.rs:16:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:30:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:32:52 | -LL | fn with_closure_expecting_fn_with_free_region(_: F) - | ------------------------------------------ required by a bound in this -LL | where F: for<'a> FnOnce(fn(&'a u32), &i32) - | ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region` -... LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `fn(fn(&'a u32), &i32) -> _` + | ^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `fn(&u32)` + found fn pointer `for<'r> fn(&'r u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:39:53 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` -... LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&'x u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:48:53 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` -... LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&u32)` error: aborting due to 5 previous errors -Some errors have detailed explanations: E0308, E0631. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs index 5cae0e76d1acb..af1e37ba867de 100644 --- a/src/test/ui/closures/issue-41366.rs +++ b/src/test/ui/closures/issue-41366.rs @@ -7,7 +7,6 @@ impl<'g> T<'g> for u32 { } fn main() { - (&|_|()) as &dyn for<'x> Fn(>::V); + (&|_| ()) as &dyn for<'x> Fn(>::V); //~^ ERROR: type mismatch in closure arguments - //~| ERROR: type mismatch resolving } diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index 2f2871e9f0e90..9c4b7d529ef4d 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -1,23 +1,14 @@ error[E0631]: type mismatch in closure arguments --> $DIR/issue-41366.rs:10:5 | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^-----^ +LL | (&|_| ()) as &dyn for<'x> Fn(>::V); + | ^^------^ | | | - | | found signature of `fn(_) -> _` - | expected signature of `for<'x> fn(>::V) -> _` + | | found signature of `fn(u16) -> _` + | expected signature of `fn(>::V) -> _` | = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` -error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(>::V,)>>::Output == ()` - --> $DIR/issue-41366.rs:10:5 - | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | - = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs new file mode 100644 index 0000000000000..99f805f7f0f63 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs @@ -0,0 +1,26 @@ +// Test that impls for these two types are considered ovelapping: +// +// * `for<'r> fn(fn(&'r u32))` +// * `fn(fn(&'a u32)` where `'a` is free +// +// This is because, for `'a = 'static`, the two types overlap. +// Effectively for them to be equal to you get: +// +// * `for<'r> fn(fn(&'r u32)) <: fn(fn(&'static u32))` +// * true if `exists<'r> { 'r: 'static }` (obviously true) +// * `fn(fn(&'static u32)) <: for<'r> fn(fn(&'r u32))` +// * true if `forall<'r> { 'static: 'r }` (also true) + +trait Trait {} + +impl Trait for for<'r> fn(fn(&'r ())) {} +impl<'a> Trait for fn(fn(&'a ())) {} +//~^ ERROR conflicting implementations +// +// Note in particular that we do NOT get a future-compatibility warning +// here. This is because the new leak-check proposed in [MCP 295] does not +// "error" when these two types are equated. +// +// [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295 + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr new file mode 100644 index 0000000000000..49271edf8e5e4 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`: + --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1 + | +LL | impl Trait for for<'r> fn(fn(&'r ())) {} + | ------------------------------------- first implementation here +LL | impl<'a> Trait for fn(fn(&'a ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.rs b/src/test/ui/coherence/coherence-fn-implied-bounds.rs new file mode 100644 index 0000000000000..4539af9a32e38 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.rs @@ -0,0 +1,26 @@ +// Test that our leak-check is not smart enough to take implied bounds +// into account (yet). Here we have two types that look like they +// should not be equivalent, but because of the rules on implied +// bounds we ought to know that, in fact, `'a = 'b` must always hold, +// and hence they are. +// +// Rustc can't figure this out and hence it accepts the impls but +// gives a future-compatibility warning (because we'd like to make +// this an error someday). +// +// Note that while we would like to make this a hard error, we also +// give the same warning for `coherence-wasm-bindgen.rs`, which ought +// to be accepted. + +#![deny(coherence_leak_check)] + +trait Trait {} + +impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + +impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + //~^ ERROR conflicting implementations + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr new file mode 100644 index 0000000000000..a3e7f0bcde376 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`: + --> $DIR/coherence-fn-implied-bounds.rs:21:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + | ------------------------------------------------------------------ first implementation here +LL | +LL | impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32` + | +note: the lint level is defined here + --> $DIR/coherence-fn-implied-bounds.rs:15:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/coherence/coherence-fn-inputs.rs b/src/test/ui/coherence/coherence-fn-inputs.rs new file mode 100644 index 0000000000000..3afec5c5459af --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.rs @@ -0,0 +1,25 @@ +// Test that we consider these two types completely equal: +// +// * `for<'a, 'b> fn(&'a u32, &'b u32)` +// * `for<'c> fn(&'c u32, &'c u32)` +// +// For a long time we considered these to be distinct types. But in fact they +// are equivalent, if you work through the implications of subtyping -- this is +// because: +// +// * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection) +// * `'a` and `'b` can both be equal to `'c` + +trait Trait {} +impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} +impl Trait for for<'c> fn(&'c u32, &'c u32) { + //~^ ERROR conflicting implementations + // + // Note in particular that we do NOT get a future-compatibility warning + // here. This is because the new leak-check proposed in [MCP 295] does not + // "error" when these two types are equated. + // + // [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295 +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-inputs.stderr b/src/test/ui/coherence/coherence-fn-inputs.stderr new file mode 100644 index 0000000000000..56ab873a39320 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`: + --> $DIR/coherence-fn-inputs.rs:15:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} + | ----------------------------------------------- first implementation here +LL | impl Trait for for<'c> fn(&'c u32, &'c u32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.rs b/src/test/ui/coherence/coherence-free-vs-bound-region.rs new file mode 100644 index 0000000000000..2f5c49d293d5d --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.rs @@ -0,0 +1,21 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait TheTrait {} + +impl<'a> TheTrait for fn(&'a u8) {} + +impl TheTrait for fn(&u8) { + //~^ ERROR conflicting implementations of trait + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr new file mode 100644 index 0000000000000..97aa491272143 --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `TheTrait` for type `fn(&u8)`: + --> $DIR/coherence-free-vs-bound-region.rs:16:1 + | +LL | impl<'a> TheTrait for fn(&'a u8) {} + | -------------------------------- first implementation here +LL | +LL | impl TheTrait for fn(&u8) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&u8)` + | +note: the lint level is defined here + --> $DIR/coherence-free-vs-bound-region.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.rs b/src/test/ui/coherence/coherence-wasm-bindgen.rs new file mode 100644 index 0000000000000..ee09a72449be1 --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.rs @@ -0,0 +1,37 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait IntoWasmAbi { + fn some_method(&self) {} +} + +trait FromWasmAbi {} +trait RefFromWasmAbi {} +trait ReturnWasmAbi {} + +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +where + A: FromWasmAbi, + R: ReturnWasmAbi, +{ +} + +// Explicitly writing the bound lifetime. +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +where + A: RefFromWasmAbi, + R: ReturnWasmAbi, +{ + //~^^^^^ ERROR conflicting implementation + //~| WARNING this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.stderr b/src/test/ui/coherence/coherence-wasm-bindgen.stderr new file mode 100644 index 0000000000000..c77483bb847f5 --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.stderr @@ -0,0 +1,32 @@ +error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn std::ops::Fn(&_) -> _`: + --> $DIR/coherence-wasm-bindgen.rs:28:1 + | +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +LL | | where +LL | | A: FromWasmAbi, +LL | | R: ReturnWasmAbi, +LL | | { +LL | | } + | |_- first implementation here +... +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +LL | | where +LL | | A: RefFromWasmAbi, +LL | | R: ReturnWasmAbi, +... | +LL | | +LL | | } + | |_^ conflicting implementation for `&dyn std::ops::Fn(&_) -> _` + | +note: the lint level is defined here + --> $DIR/coherence-wasm-bindgen.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: downstream crates may implement trait `FromWasmAbi` for type `&_` + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr index ad38b632b75f0..4a6241de1b453 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -14,6 +14,7 @@ LL | fn foo() -> Array { | ^ | = note: type arguments must be provided before constant arguments + = help: reorder the arguments: types, then consts: `` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index afa577fa67ff2..90c438b05cb81 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -1,15 +1,14 @@ -// run-pass - -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete fn function() -> u32 { 17 } -struct Wrapper u32>; +struct Wrapper u32>; //~ ERROR: using function pointers as const generic parameters impl u32> Wrapper { +//~^ ERROR: using function pointers as const generic parameters fn call() -> u32 { F() } diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr index 9c0f7e3ab9b87..b5811243caa8a 100644 --- a/src/test/ui/const-generics/fn-const-param-call.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -1,11 +1,23 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fn-const-param-call.rs:3:12 + --> $DIR/fn-const-param-call.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: 1 warning emitted +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:8:25 + | +LL | struct Wrapper u32>; + | ^^^^^^^^^^^ + +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:10:15 + | +LL | impl u32> Wrapper { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index 08f6e0db31cae..14fa3b494b3fc 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -1,7 +1,8 @@ -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete struct Checked bool>; +//~^ ERROR: using function pointers as const generic parameters fn not_one(val: usize) -> bool { val != 1 } fn not_two(val: usize) -> bool { val != 2 } @@ -13,14 +14,14 @@ fn generic(val: usize) -> bool { val != 1 } fn main() { let _: Option> = None; let _: Checked = Checked::; - let _: Checked = Checked::; //~ mismatched types + let _: Checked = Checked::; let _ = Checked::; let _ = Checked::<{generic_arg::}>; - let _ = Checked::<{generic_arg::}>; //~ mismatched types + let _ = Checked::<{generic_arg::}>; - let _ = Checked::; //~ type annotations needed + let _ = Checked::; let _ = Checked::<{generic::}>; let _: Checked<{generic::}> = Checked::<{generic::}>; - let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types + let _: Checked<{generic::}> = Checked::<{generic::}>; } diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index de41d2984a655..7aaa41eb7d7b1 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -1,46 +1,17 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/fn-const-param-infer.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:16:31 +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-infer.rs:4:25 | -LL | let _: Checked = Checked::; - | ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}` - | - = note: expected type `{not_one as fn(usize) -> bool}` - found type `{not_two as fn(usize) -> bool}` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:20:24 - | -LL | let _ = Checked::<{generic_arg::}>; - | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32` - | - = note: expected fn pointer `fn(usize) -> _` - found fn item `fn(u32) -> _ {generic_arg::}` - -error[E0282]: type annotations needed - --> $DIR/fn-const-param-infer.rs:22:23 - | -LL | let _ = Checked::; - | ^^^^^^^ cannot infer type for type parameter `T` declared on the function `generic` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:25:40 - | -LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic:: as fn(usize) -> bool}`, found `{generic:: as fn(usize) -> bool}` - | - = note: expected type `{generic:: as fn(usize) -> bool}` - found type `{generic:: as fn(usize) -> bool}` +LL | struct Checked bool>; + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs index c498bfe2e9781..97ca9d6a44c9e 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -1,12 +1,11 @@ -// run-pass -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete const A: u32 = 3; -struct Const; +struct Const; //~ ERROR: using raw pointers as const generic parameters -impl Const

{ +impl Const

{ //~ ERROR: using raw pointers as const generic parameters fn get() -> u32 { unsafe { *P diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr index 1ffc63ffdac03..1ce8bb9c05423 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr @@ -1,11 +1,23 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/raw-ptr-const-param-deref.rs:2:12 + --> $DIR/raw-ptr-const-param-deref.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: 1 warning emitted +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:6:23 + | +LL | struct Const; + | ^^^^^^^^^^ + +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:8:15 + | +LL | impl Const

{ + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index d7d970e952b65..237b410e073d6 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -1,9 +1,9 @@ -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete -struct Const; +struct Const; //~ ERROR: using raw pointers as const generic parameters fn main() { - let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types + let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>; } diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 7a665397c1207..6e64f8a327fd5 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -1,21 +1,17 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/raw-ptr-const-param.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:7:40 +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param.rs:4:23 | -LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}` - | - = note: expected type `{0xf as *const u32}` - found type `{0xa as *const u32}` +LL | struct Const; + | ^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr index 4753222a7c07d..47f39b703e460 100644 --- a/src/test/ui/consts/const-eval/const_let.stderr +++ b/src/test/ui/consts/const-eval/const_let.stderr @@ -2,25 +2,33 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:16:32 | LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:20:33 | LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:24:21 | LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:28:22 | LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs index 9be1374f85d99..e238e13b8e2da 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -1,17 +1,6 @@ -#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] - fn main() {} // unconst and bad, will thus error in miri -const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this -// unconst and bad, will thus error in miri -const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR any use of this -// unconst and fine -const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; -// unconst and bad, will thus error in miri -const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this -// unconst and fine -const Z: i32 = unsafe { *(&1 as *const i32) }; +const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably // unconst and bad, will thus error in miri -const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause -const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause +const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index cc40728e6b574..21d3f5e7e8536 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -1,44 +1,18 @@ -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:6:26 +error: pointers cannot be reliably compared during const eval. + --> $DIR/const_raw_ptr_ops.rs:4:26 | LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; - | -------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[deny(const_err)]` on by default + = note: see issue #53020 for more information -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:8:27 +error: pointers cannot be reliably compared during const eval. + --> $DIR/const_raw_ptr_ops.rs:6:27 | LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; - | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:12:28 - | -LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; - | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^------- - | | - | "pointer-to-integer cast" needs an rfc before being allowed inside constants - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:16:26 - | -LL | const Z2: i32 = unsafe { *(42 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn bytes into a pointer - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:17:26 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | const Z3: i32 = unsafe { *(44 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn bytes into a pointer + = note: see issue #53020 for more information -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs new file mode 100644 index 0000000000000..d2a7623837a23 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -0,0 +1,13 @@ +#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] + +fn main() {} + +// unconst and fine +const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; +// unconst and bad, will thus error in miri +const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this +// unconst and fine +const Z: i32 = unsafe { *(&1 as *const i32) }; +// unconst and bad, will thus error in miri +const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause +const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr new file mode 100644 index 0000000000000..93f2261745d6f --- /dev/null +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr @@ -0,0 +1,28 @@ +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:8:28 + | +LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; + | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^------- + | | + | "pointer-to-integer cast" needs an rfc before being allowed inside constants + | + = note: `#[deny(const_err)]` on by default + +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:12:26 + | +LL | const Z2: i32 = unsafe { *(42 as *const i32) }; + | -------------------------^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn bytes into a pointer + +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:13:26 + | +LL | const Z3: i32 = unsafe { *(44 as *const i32) }; + | -------------------------^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn bytes into a pointer + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr index f843a94fabd8d..771d368d78391 100644 --- a/src/test/ui/consts/const-eval/issue-65394.stderr +++ b/src/test/ui/consts/const-eval/issue-65394.stderr @@ -9,6 +9,9 @@ error[E0493]: destructors cannot be evaluated at compile-time | LL | let mut x = Vec::::new(); | ^^^^^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/livedrop.rs b/src/test/ui/consts/const-eval/livedrop.rs new file mode 100644 index 0000000000000..f00d1c70659fd --- /dev/null +++ b/src/test/ui/consts/const-eval/livedrop.rs @@ -0,0 +1,20 @@ +#![feature(const_if_match)] +#![feature(const_loop)] + +const _: Option> = { + let mut never_returned = Some(Vec::new()); + let mut always_returned = None; //~ ERROR destructors cannot be evaluated at compile-time + + let mut i = 0; + loop { + always_returned = never_returned; + never_returned = None; + + i += 1; + if i == 10 { + break always_returned; + } + } +}; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/livedrop.stderr b/src/test/ui/consts/const-eval/livedrop.stderr new file mode 100644 index 0000000000000..b802d23d9a89c --- /dev/null +++ b/src/test/ui/consts/const-eval/livedrop.stderr @@ -0,0 +1,12 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/livedrop.rs:6:9 + | +LL | let mut always_returned = None; + | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors +... +LL | always_returned = never_returned; + | --------------- value is dropped here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs index c6fb5eeab5aec..d724fe3060b21 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs @@ -1,4 +1,4 @@ -#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] +#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] fn main() { let x: &'static bool = &(42 as *const i32 == 43 as *const i32); diff --git a/src/test/ui/consts/control-flow/drop-fail.stock.stderr b/src/test/ui/consts/control-flow/drop-fail.stock.stderr index 77cded5c438b5..6a9ea91d20e1f 100644 --- a/src/test/ui/consts/control-flow/drop-fail.stock.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.stock.stderr @@ -3,24 +3,36 @@ error[E0493]: destructors cannot be evaluated at compile-time | LL | let x = Some(Vec::new()); | ^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-fail.rs:23:9 | LL | let vec_tuple = (Vec::new(),); | ^^^^^^^^^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-fail.rs:31:9 | LL | let x: Result<_, Vec> = Ok(Vec::new()); | ^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-fail.rs:41:9 | LL | let mut tmp = None; | ^^^^^^^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 512b343011b40..4b0401ebf9dba 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | LL | const fn into_inner(self) -> T { self.0 } - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0723]: mutable references in const fn are unstable --> $DIR/min_const_fn.rs:39:36 @@ -17,7 +19,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:44:28 | LL | const fn into_inner_lt(self) -> T { self.0 } - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0723]: mutable references in const fn are unstable --> $DIR/min_const_fn.rs:46:42 @@ -32,7 +36,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:51:27 | LL | const fn into_inner_s(self) -> T { self.0 } - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0723]: mutable references in const fn are unstable --> $DIR/min_const_fn.rs:53:38 diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr index 37016664ac58f..0b6cb2fab46f1 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:11:20 | LL | const F: u32 = (U::X, 42).1; - | ^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to previous error diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr index 805ba9c6b0307..21f11dda5a667 100644 --- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr @@ -12,7 +12,7 @@ LL | let _v = x + 0; warning: skipping const checks | -help: skipping check for `const_compare_raw_pointers` feature +help: skipping check that does not even have a feature gate --> $DIR/ptr_arith.rs:9:14 | LL | let _v = x == x; diff --git a/src/test/ui/consts/miri_unleashed/slice_eq.rs b/src/test/ui/consts/miri_unleashed/slice_eq.rs new file mode 100644 index 0000000000000..fd843105daf2a --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/slice_eq.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// run-pass + +#![feature(const_raw_ptr_comparison)] + +const EMPTY_SLICE: &[i32] = &[]; +const EMPTY_EQ: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[] as *const _); +const EMPTY_EQ2: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[] as *const _); +const EMPTY_NE: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[1] as *const _); +const EMPTY_NE2: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[1] as *const _); + +fn main() { + assert!(!EMPTY_EQ); + assert!(!EMPTY_EQ2); + assert!(!EMPTY_NE); + assert!(!EMPTY_NE2); +} diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr index a8455cefd01cf..928605356a16e 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr @@ -9,12 +9,18 @@ error[E0493]: destructors cannot be evaluated at compile-time | LL | const fn unwrap_or_else T>(self, f: F) -> T { | ^ constant functions cannot evaluate destructors +... +LL | } + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:47 | LL | const fn unwrap_or_else T>(self, f: F) -> T { | ^^^^ constant functions cannot evaluate destructors +... +LL | } + | - value is dropped here error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs index bbefff27d7f68..d2edd97efb232 100644 --- a/src/test/ui/error-codes/E0395.rs +++ b/src/test/ui/error-codes/E0395.rs @@ -1,10 +1,8 @@ -// gate-test-const_compare_raw_pointers - static FOO: i32 = 42; static BAR: i32 = 42; static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; -//~^ ERROR comparing raw pointers inside static +//~^ ERROR pointers cannot be reliably compared during const eval fn main() { } diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 20c8622f33726..674cc69645029 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -1,12 +1,10 @@ -error[E0658]: comparing raw pointers inside static - --> $DIR/E0395.rs:6:29 +error: pointers cannot be reliably compared during const eval. + --> $DIR/E0395.rs:4:29 | LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs index 1ab11ce3b4423..dc602ba7e6f21 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs @@ -1,9 +1,9 @@ struct ConstFn; //~^ ERROR const generics are unstable -//~^^ ERROR using function pointers as const generic parameters is unstable +//~^^ ERROR using function pointers as const generic parameters is forbidden struct ConstPtr; //~^ ERROR const generics are unstable -//~^^ ERROR using raw pointers as const generic parameters is unstable +//~^^ ERROR using raw pointers as const generic parameters is forbidden fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr index dc7ef55e7ab99..b2c96d3810f98 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr @@ -16,23 +16,17 @@ LL | struct ConstPtr; = note: see issue #44580 for more information = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0658]: using function pointers as const generic parameters is unstable +error: using function pointers as const generic parameters is forbidden --> $DIR/feature-gate-const_generics-ptr.rs:1:25 | LL | struct ConstFn; | ^^^^ - | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable -error[E0658]: using raw pointers as const generic parameters is unstable +error: using raw pointers as const generic parameters is forbidden --> $DIR/feature-gate-const_generics-ptr.rs:5:26 | LL | struct ConstPtr; | ^^^^^^^^^^ - | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable error: aborting due to 4 previous errors diff --git a/src/test/ui/generator/resume-arg-late-bound.nll.stderr b/src/test/ui/generator/resume-arg-late-bound.nll.stderr new file mode 100644 index 0000000000000..7d71219192407 --- /dev/null +++ b/src/test/ui/generator/resume-arg-late-bound.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/resume-arg-late-bound.rs:15:5 + | +LL | test(gen); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/generator/resume-arg-late-bound.rs b/src/test/ui/generator/resume-arg-late-bound.rs index 87b1f1a065bc8..a8f657eaabe47 100644 --- a/src/test/ui/generator/resume-arg-late-bound.rs +++ b/src/test/ui/generator/resume-arg-late-bound.rs @@ -13,5 +13,6 @@ fn main() { *arg = true; }; test(gen); - //~^ ERROR type mismatch in function arguments + //~^ ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr index ffa440daed8c4..c379d9eae8ecd 100644 --- a/src/test/ui/generator/resume-arg-late-bound.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.stderr @@ -1,15 +1,21 @@ -error[E0631]: type mismatch in function arguments - --> $DIR/resume-arg-late-bound.rs:15:10 +error[E0308]: mismatched types + --> $DIR/resume-arg-late-bound.rs:15:5 | -LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} - | ------------------------------- required by this bound in `test` -... LL | test(gen); - | ^^^ - | | - | expected signature of `for<'a> fn(&'a mut bool) -> _` - | found signature of `fn(&mut bool) -> _` + | ^^^^ one type is more general than the other + | + = note: expected type `for<'a> std::ops::Generator<&'a mut bool>` + found type `std::ops::Generator<&mut bool>` + +error[E0308]: mismatched types + --> $DIR/resume-arg-late-bound.rs:15:5 + | +LL | test(gen); + | ^^^^ one type is more general than the other + | + = note: expected type `for<'a> std::ops::Generator<&'a mut bool>` + found type `std::ops::Generator<&mut bool>` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr new file mode 100644 index 0000000000000..d5343566633d5 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, +LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + | |_____________________________________________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index b91798fa12379..92a85825030c2 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, -LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } - | |_________________________________________________________________________________________- in this macro invocation +LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + | |_____________________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(&'a u32, &'b u32) -> &'a u32>` found enum `std::option::Option fn(&'a u32, &'a u32) -> &'a u32>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 45f53d4fe99db..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), -LL | | for<'a> fn(&'a u32, &'a u32)) } - | |__________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(&'a u32, &'b u32)>` - found enum `std::option::Option fn(&'a u32, &'a u32)>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr new file mode 100644 index 0000000000000..f115609396756 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), +LL | | fn(&'x u32)) } + | |______________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index c3e4f6d2ed0c1..98f5bff732762 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), -LL | | fn(&'x u32)) } - | |___________________________________________- in this macro invocation +LL | | fn(&'x u32)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option fn(&'a u32)>` found enum `std::option::Option` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 4d7b86027f564..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), -LL | | for<'a> fn(Co<'a>, Co<'a>)) } - | |______________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(Co<'a>, Co<'b>)>` - found enum `std::option::Option fn(Co<'a>, Co<'a>)>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 7f0a4197dd7fe..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, -LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } - | |______________________________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(Co<'a>, Co<'b>) -> Contra<'a>>` - found enum `std::option::Option fn(Co<'a>, Co<'a>) -> Contra<'a>>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index c12e543a44e79..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, -LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } - | |______________________________________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(Contra<'a>, Contra<'b>) -> Co<'a>>` - found enum `std::option::Option fn(Contra<'a>, Contra<'a>) -> Co<'a>>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr new file mode 100644 index 0000000000000..4541c462ee056 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr @@ -0,0 +1,26 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 460356856bd56..100ba6ac27e25 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), -LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } - | |__________________________________________________________________________- in this macro invocation +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(Inv<'a>, Inv<'b>)>` found enum `std::option::Option fn(Inv<'a>, Inv<'a>)>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr index 6b5e7a5a6345a..af5cf41be0a48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr @@ -1,33 +1,33 @@ error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:33:13 + --> $DIR/hr-subtype.rs:39:13 | -LL | fn subtype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t2>(None::<$t1>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:39:13 + --> $DIR/hr-subtype.rs:45:13 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index fc3643306e628..3c8af20e50cef 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -1,65 +1,65 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:33:26 + --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t2>(None::<$t1>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option)>` found enum `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 32:20... - --> $DIR/hr-subtype.rs:32:20 +note: the lifetime `'x` as defined on the function body at 38:20... + --> $DIR/hr-subtype.rs:38:20 | -LL | fn subtype<'x,'y:'x,'z:'y>() { +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23 - --> $DIR/hr-subtype.rs:32:23 +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:24 + --> $DIR/hr-subtype.rs:38:24 | -LL | fn subtype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option)>` found enum `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 38:22... - --> $DIR/hr-subtype.rs:38:22 +note: the lifetime `'x` as defined on the function body at 44:22... + --> $DIR/hr-subtype.rs:44:22 | -LL | fn supertype<'x,'y:'x,'z:'y>() { +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 - --> $DIR/hr-subtype.rs:38:25 +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 + --> $DIR/hr-subtype.rs:44:26 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr index 7c0770924daaa..75d7e0e46b72a 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr @@ -1,16 +1,16 @@ error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:39:13 + --> $DIR/hr-subtype.rs:45:13 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr index 0dde27788f629..7b4cdd4a419b4 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -1,33 +1,33 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option` found enum `std::option::Option` -note: the lifetime `'x` as defined on the function body at 38:22... - --> $DIR/hr-subtype.rs:38:22 +note: the lifetime `'x` as defined on the function body at 44:22... + --> $DIR/hr-subtype.rs:44:22 | -LL | fn supertype<'x,'y:'x,'z:'y>() { +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 - --> $DIR/hr-subtype.rs:38:25 +LL | | fn(&'y u32)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 + --> $DIR/hr-subtype.rs:44:26 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index b31f198bd97bf..ad9500eedca93 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -18,60 +18,62 @@ // revisions: bound_inv_a_b_vs_bound_inv_a // revisions: bound_a_b_ret_a_vs_bound_a_ret_a -fn gimme(_: Option) { } +fn gimme(_: Option) {} -struct Inv<'a> { x: *mut &'a u32 } +struct Inv<'a> { + x: *mut &'a u32, +} -struct Co<'a> { x: fn(&'a u32) } +struct Co<'a> { + x: fn(&'a u32), +} -struct Contra<'a> { x: &'a u32 } +struct Contra<'a> { + x: &'a u32, +} macro_rules! check { ($rev:ident: ($t1:ty, $t2:ty)) => { #[cfg($rev)] - fn subtype<'x,'y:'x,'z:'y>() { + fn subtype<'x, 'y: 'x, 'z: 'y>() { gimme::<$t2>(None::<$t1>); //[free_inv_x_vs_free_inv_y]~^ ERROR } #[cfg($rev)] - fn supertype<'x,'y:'x,'z:'y>() { + fn supertype<'x, 'y: 'x, 'z: 'y>() { gimme::<$t1>(None::<$t2>); //[bound_a_vs_free_x]~^ ERROR //[free_x_vs_free_y]~^^ ERROR //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR - //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types - //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR - //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR - //[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR } - } + }; } // If both have bound regions, they are equivalent, regardless of // variant. check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32), - for<'a> fn(&'a u32)) } +for<'a> fn(&'a u32)) } check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32), - for<'b> fn(&'b u32)) } +for<'b> fn(&'b u32)) } check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>), - for<'b> fn(Inv<'b>)) } +for<'b> fn(Inv<'b>)) } check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>), - for<'b> fn(Co<'b>)) } +for<'b> fn(Co<'b>)) } // Bound is a subtype of free. check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), - fn(&'x u32)) } +fn(&'x u32)) } // Two free regions are relatable if subtyping holds. check! { free_x_vs_free_x: (fn(&'x u32), - fn(&'x u32)) } +fn(&'x u32)) } check! { free_x_vs_free_y: (fn(&'x u32), - fn(&'y u32)) } +fn(&'y u32)) } check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), - fn(Inv<'y>)) } +fn(Inv<'y>)) } // Somewhat surprisingly, a fn taking two distinct bound lifetimes and // a fn taking one bound lifetime can be interchangeable, but only if @@ -82,25 +84,29 @@ check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), // intersection; // - if we are contravariant, then 'a can be inferred to 'static. check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), - for<'a> fn(&'a u32, &'a u32)) } +for<'a> fn(&'a u32, &'a u32)) } check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), - for<'a> fn(Co<'a>, Co<'a>)) } +for<'a> fn(Co<'a>, Co<'a>)) } check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, - for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } +for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, - for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } +for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } // If we make those lifetimes invariant, then the two types are not interchangeable. check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), - for<'a> fn(Inv<'a>, Inv<'a>)) } +for<'a> fn(Inv<'a>, Inv<'a>)) } check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, - for<'a> fn(&'a u32, &'a u32) -> &'a u32) } +for<'a> fn(&'a u32, &'a u32) -> &'a u32) } #[rustc_error] fn main() { -//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error] -//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error] -//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error] -//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error] -//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error] + //[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error] + //[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error] + //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error] + //[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error] + //[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error] + //[bound_co_a_b_vs_bound_co_a]~^^^^^^ ERROR + //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR + //[bound_a_b_vs_bound_a]~^^^^^^^^ ERROR + //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR } diff --git a/src/test/ui/hr-subtype/return-static.rs b/src/test/ui/hr-subtype/return-static.rs new file mode 100644 index 0000000000000..6455854f34db8 --- /dev/null +++ b/src/test/ui/hr-subtype/return-static.rs @@ -0,0 +1,13 @@ +// check-pass + +fn make() -> T { + panic!() +} + +fn take(x: T) {} + +fn main() { + let x: for<'a> fn(&'a u32) -> _ = make(); + let y: &'static u32 = x(&22); + take:: fn(&'b u32) -> &'b u32>(x); +} diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr new file mode 100644 index 0000000000000..f290a93326f37 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 7250935ea296b..45573814d13c0 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied - --> $DIR/hrtb-conflate-regions.rs:27:22 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn want_foo2() - | --------- required by a bound in this -LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | -------------------------------------- required by this bound in `want_foo2` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - > + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr new file mode 100644 index 0000000000000..11390d9e2d265 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-fn.rs:17:12 + | +LL | let _: for<'b> fn(&'b u32) = foo(); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 328e98657effb..9914783d9767d 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -2,9 +2,7 @@ error[E0308]: mismatched types --> $DIR/hrtb-exists-forall-fn.rs:17:34 | LL | let _: for<'b> fn(&'b u32) = foo(); - | ------------------- ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b - | | - | expected due to this + | ^^^^^ one type is more general than the other | = note: expected fn pointer `for<'b> fn(&'b u32)` found fn pointer `fn(&u32)` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr new file mode 100644 index 0000000000000..a4c3ffd1f6c08 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 4c1d4d28a09b0..921061916fc95 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -32,5 +32,5 @@ fn main() { // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); - //~^ ERROR not satisfied + //~^ ERROR implementation of `Trait` is not general enough } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 7a7285d3d76e0..fe8209d054c8a 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,18 +1,14 @@ -error[E0277]: the trait bound `(): Trait fn(&'b u32)>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11 +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(&'b u32)>, - | -------------------------- required by this bound in `foo` +LL | trait Trait {} + | ----------------- trait `Trait` defined here ... LL | foo::<()>(); - | ^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | ^^^^^^^^^ implementation of `Trait` is not general enough | - = help: the following implementations were found: - <() as Trait> + = note: `()` must implement `Trait fn(&'b u32)>` + = note: ...but `()` actually implements `Trait`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs index 95b57d6c5bb5e..f95496a6c3cc0 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -2,6 +2,8 @@ // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. +// +// check-pass trait Trait {} @@ -30,9 +32,6 @@ fn main() { // - `?b: ?a` -- solveable if `?b` is inferred to `'static` // - So the subtyping check succeeds, somewhat surprisingly. // This is because we can use `'static`. - // - // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); - //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr deleted file mode 100644 index 1e335f9ee9610..0000000000000 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0277]: the trait bound `(): Trait fn(fn(&'b u32))>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:11 - | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(fn(&'b u32))>, - | ------------------------------ required by this bound in `foo` -... -LL | foo::<()>(); - | ^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` - | - = help: the following implementations were found: - <() as Trait> - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr new file mode 100644 index 0000000000000..e2a399b2faa9d --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs index 827a68beee8bd..b1b7ec6bcf1a5 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -25,5 +25,5 @@ fn main() { // yielding `fn(&!b u32)`, in a fresh universe U1 // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. - foo::<()>(); //~ ERROR not satisfied + foo::<()>(); //~ ERROR implementation of `Trait` is not general enough } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 9174ea4d8419d..720e2276d5343 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,18 +1,14 @@ -error[E0277]: the trait bound `(): Trait fn(std::cell::Cell<&'b u32>)>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:11 +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(Cell<&'b u32>)>, - | -------------------------------- required by this bound in `foo` +LL | trait Trait {} + | ----------------- trait `Trait` defined here ... LL | foo::<()>(); - | ^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` + | ^^^^^^^^^ implementation of `Trait` is not general enough | - = help: the following implementations were found: - <() as Trait)>> + = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` + = note: ...but `()` actually implements `Trait)>`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr new file mode 100644 index 0000000000000..8901a1b46817d --- /dev/null +++ b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr @@ -0,0 +1,24 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-just-for-static.rs:24:5 + | +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | fn give_some<'a>() { + | -- lifetime `'a` defined here +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: higher-ranked subtype error + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 4fa404624775b..5e3014317f5bc 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,31 +1,30 @@ -error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:24:17 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | fn want_hrtb() - | --------- required by a bound in this -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- required by this bound in `want_hrtb` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | want_hrtb::() - | ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - > + = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` -error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:30:17 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:30:5 | -LL | fn want_hrtb() - | --------- required by a bound in this -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- required by this bound in `want_hrtb` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | want_hrtb::<&'a u32>() - | ^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - <&'a u32 as Foo<&'a isize>> + = note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0`... + = note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index c0e3fd3cf4679..90a7cadca41b7 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -1,17 +1,43 @@ -error: implementation of `Stream` is not general enough - --> $DIR/issue-30786.rs:108:22 +error[E0599]: no method named `filterx` found for struct `Map` in the current scope + --> $DIR/issue-30786.rs:128:22 | -LL | / pub trait Stream { -LL | | type Item; -LL | | fn next(self) -> Option; -LL | | } - | |_- trait `Stream` defined here +LL | pub struct Map { + | -------------------- + | | + | method `filterx` not found for this + | doesn't satisfy `_: StreamExt` ... -LL | let map = source.map(|x: &_| x); - | ^^^ implementation of `Stream` is not general enough +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method not found in `Map` | - = note: `Stream` would have to be implemented for the type `&'0 mut Map`, for any lifetime `'0`... - = note: ...but `Stream` is actually implemented for the type `&'1 mut Map`, for some specific lifetime `'1` + = note: the method `filterx` exists but the following trait bounds were not satisfied: + `&'a mut Map: Stream` + which is required by `Map: StreamExt` + `&'a mut &Map: Stream` + which is required by `&Map: StreamExt` + `&'a mut &mut Map: Stream` + which is required by `&mut Map: StreamExt` -error: aborting due to previous error +error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope + --> $DIR/issue-30786.rs:141:24 + | +LL | pub struct Filter { + | ----------------------- + | | + | method `countx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | + = note: the method `countx` exists but the following trait bounds were not satisfied: + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index c736c5479f848..90a7cadca41b7 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -1,56 +1,43 @@ -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:108:15 - | -LL | let map = source.map(|x: &_| x); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: aborting due to 9 previous errors - +error[E0599]: no method named `filterx` found for struct `Map` in the current scope + --> $DIR/issue-30786.rs:128:22 + | +LL | pub struct Map { + | -------------------- + | | + | method `filterx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method not found in `Map` + | + = note: the method `filterx` exists but the following trait bounds were not satisfied: + `&'a mut Map: Stream` + which is required by `Map: StreamExt` + `&'a mut &Map: Stream` + which is required by `&Map: StreamExt` + `&'a mut &mut Map: Stream` + which is required by `&mut Map: StreamExt` + +error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope + --> $DIR/issue-30786.rs:141:24 + | +LL | pub struct Filter { + | ----------------------- + | | + | method `countx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | + = note: the method `countx` exists but the following trait bounds were not satisfied: + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs index c656f84306536..8ce5c090b543e 100644 --- a/src/test/ui/hrtb/issue-30786.rs +++ b/src/test/ui/hrtb/issue-30786.rs @@ -16,7 +16,7 @@ //[nll]compile-flags: -Z borrowck=mir -pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here +pub trait Stream { type Item; fn next(self) -> Option; } @@ -37,8 +37,9 @@ pub struct Map { } impl<'a, A, F, T> Stream for &'a mut Map -where &'a mut A: Stream, - F: FnMut(<&'a mut A as Stream>::Item) -> T, +where + &'a mut A: Stream, + F: FnMut(<&'a mut A as Stream>::Item) -> T, { type Item = T; fn next(self) -> Option { @@ -55,8 +56,9 @@ pub struct Filter { } impl<'a, A, F, T> Stream for &'a mut Filter -where for<'b> &'b mut A: Stream, // <---- BAD - F: FnMut(&T) -> bool, +where + for<'b> &'b mut A: Stream, // <---- BAD + F: FnMut(&T) -> bool, { type Item = <&'a mut A as Stream>::Item; fn next(self) -> Option { @@ -69,29 +71,29 @@ where for<'b> &'b mut A: Stream, // <---- BAD } } -pub trait StreamExt where for<'b> &'b mut Self: Stream { - fn map(self, func: F) -> Map - where Self: Sized, - for<'a> &'a mut Map: Stream, +pub trait StreamExt +where + for<'b> &'b mut Self: Stream, +{ + fn mapx(self, func: F) -> Map + where + Self: Sized, + for<'a> &'a mut Map: Stream, { - Map { - func: func, - stream: self, - } + Map { func: func, stream: self } } - fn filter(self, func: F) -> Filter - where Self: Sized, - for<'a> &'a mut Filter: Stream, + fn filterx(self, func: F) -> Filter + where + Self: Sized, + for<'a> &'a mut Filter: Stream, { - Filter { - func: func, - stream: self, - } + Filter { func: func, stream: self } } - fn count(mut self) -> usize - where Self: Sized, + fn countx(mut self) -> usize + where + Self: Sized, { let mut count = 0; while let Some(_) = self.next() { @@ -101,24 +103,44 @@ pub trait StreamExt where for<'b> &'b mut Self: Stream { } } -impl StreamExt for T where for<'a> &'a mut T: Stream { } +impl StreamExt for T where for<'a> &'a mut T: Stream {} -fn main() { +fn identity(x: &T) -> &T { + x +} + +fn variant1() { let source = Repeat(10); - let map = source.map(|x: &_| x); - //[nll]~^ ERROR higher-ranked subtype error - //[migrate]~^^ ERROR implementation of `Stream` is not general enough - //[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map - //[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1 - //[migrate]~| NOTE implementation of `Stream` is not general enough - let filter = map.filter(|x: &_| true); - //[nll]~^ ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - let count = filter.count(); // Assert that we still have a valid stream. - //[nll]~^ ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error + + // Here, the call to `mapx` returns a type `T` to which `StreamExt` + // is not applicable, because `for<'b> &'b mut T: Stream`) doesn't hold. + // + // More concretely, the type `T` is `Map`, and + // the where clause doesn't hold because the signature of the + // closure gets inferred to a signature like `|&'_ Stream| -> &'_` + // for some specific `'_`, rather than a more generic + // signature. + // + // Why *exactly* we opt for this signature is a bit unclear to me, + // we deduce it somehow from a reuqirement that `Map: Stream` I + // guess. + let map = source.mapx(|x: &_| x); + let filter = map.filterx(|x: &_| true); + //[migrate]~^ ERROR no method named `filterx` + //[nll]~^^ ERROR no method named `filterx` } + +fn variant2() { + let source = Repeat(10); + + // Here, we use a function, which is not subject to the vagaries + // of closure signature inference. In this case, we get the error + // on `countx` as, I think, the test originally expected. + let map = source.mapx(identity); + let filter = map.filterx(|x: &_| true); + let count = filter.countx(); + //[migrate]~^ ERROR no method named `countx` + //[nll]~^^ ERROR no method named `countx` +} + +fn main() {} diff --git a/src/test/ui/hrtb/issue-46989.nll.stderr b/src/test/ui/hrtb/issue-46989.nll.stderr new file mode 100644 index 0000000000000..6c127b92d97d1 --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/issue-46989.rs:38:5 + | +LL | assert_foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs index 2c85905545807..4a09f4be156e2 100644 --- a/src/test/ui/hrtb/issue-46989.rs +++ b/src/test/ui/hrtb/issue-46989.rs @@ -28,15 +28,13 @@ // // holds because 'a can be instantiated to 'empty. -trait Foo { +trait Foo {} -} - -impl Foo for fn(A) { } +impl Foo for fn(A) {} fn assert_foo() {} fn main() { assert_foo::(); - //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied + //~^ ERROR implementation of `Foo` is not general enough } diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index 0a7382c4dd818..c85c37ff9239e 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,15 +1,14 @@ -error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied - --> $DIR/issue-46989.rs:40:18 +error: implementation of `Foo` is not general enough + --> $DIR/issue-46989.rs:38:5 | -LL | fn assert_foo() {} - | --- required by this bound in `assert_foo` +LL | trait Foo {} + | ------------ trait `Foo` defined here ... LL | assert_foo::(); - | ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - + = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)` + = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index ca9ca8a9debe2..3b339c5c3d7fc 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -53,7 +53,15 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:33:69 + --> $DIR/must_outlive_least_region_or_bound.rs:30:24 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:37:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -62,7 +70,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:38:61 + --> $DIR/must_outlive_least_region_or_bound.rs:42:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` @@ -72,14 +80,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 = help: consider adding the following bound: `'b: 'a` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:43:51 + --> $DIR/must_outlive_least_region_or_bound.rs:47:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | ^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0310, E0621. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 837244b022721..9bf86fa66cded 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -27,6 +27,10 @@ fn elided4(x: &i32) -> Box { Box::new(x) } fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } //~^ ERROR cannot infer an appropriate lifetime +fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } +//~^ ERROR cannot infer an appropriate lifetime +//~| ERROR cannot infer an appropriate lifetime + trait LifetimeTrait<'a> {} impl<'a> LifetimeTrait<'a> for &'a i32 {} diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index e1fa4f02b6fcf..ffadcaae08e05 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -87,13 +87,48 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:33:69 + --> $DIR/must_outlive_least_region_or_bound.rs:30:65 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ^^^^ +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:30:69 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:30:41 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ^^^^^^^^^^ +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ^^^^ +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:37:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- this data with lifetime `'a`... ^ ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:33:34 + --> $DIR/must_outlive_least_region_or_bound.rs:37:34 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +142,7 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ^^^^^^^^^^^^ error[E0623]: lifetime mismatch - --> $DIR/must_outlive_least_region_or_bound.rs:38:61 + --> $DIR/must_outlive_least_region_or_bound.rs:42:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | ------- ^^^^^^^^^^^^^^^^ @@ -116,7 +151,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | this parameter and the return type are declared with different lifetimes... error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:43:51 + --> $DIR/must_outlive_least_region_or_bound.rs:47:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds @@ -181,7 +216,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0310, E0621, E0623, E0759. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs index 36a69cf4c22ff..d1093c205798a 100644 --- a/src/test/ui/issues/issue-25826.rs +++ b/src/test/ui/issues/issue-25826.rs @@ -1,6 +1,6 @@ fn id(t: T) -> T { t } fn main() { const A: bool = unsafe { id:: as *const () < id:: as *const () }; - //~^ ERROR comparing raw pointers inside constant + //~^ ERROR pointers cannot be reliably compared during const eval println!("{}", A); } diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr index 3a5a6b509ba9d..67d1b3ab9bed6 100644 --- a/src/test/ui/issues/issue-25826.stderr +++ b/src/test/ui/issues/issue-25826.stderr @@ -1,12 +1,10 @@ -error[E0658]: comparing raw pointers inside constant +error: pointers cannot be reliably compared during const eval. --> $DIR/issue-25826.rs:3:30 | LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-40000.nll.stderr b/src/test/ui/issues/issue-40000.nll.stderr new file mode 100644 index 0000000000000..f673fbae8b79c --- /dev/null +++ b/src/test/ui/issues/issue-40000.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/issue-40000.rs:6:9 + | +LL | foo(bar); + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index 983fdb13083a1..3eb3482ac910e 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | LL | foo(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter + | ^^^ one type is more general than the other | - = note: expected struct `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>` - found struct `std::boxed::Box` + = note: expected trait object `dyn for<'r> std::ops::Fn(&'r i32)` + found trait object `dyn std::ops::Fn(&i32)` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43623.rs b/src/test/ui/issues/issue-43623.rs index b259e9e269d06..99cae46fd9cf2 100644 --- a/src/test/ui/issues/issue-43623.rs +++ b/src/test/ui/issues/issue-43623.rs @@ -9,11 +9,12 @@ impl<'a> Trait<'a> for Type { } pub fn break_me(f: F) -where T: for<'b> Trait<'b>, - F: for<'b> FnMut(>::Assoc) { +where + T: for<'b> Trait<'b>, + F: for<'b> FnMut(>::Assoc), +{ break_me::; //~^ ERROR: type mismatch in function arguments - //~| ERROR: type mismatch resolving } fn main() {} diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index 99fb2a1f5d030..80aca482b3d29 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -1,29 +1,18 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-43623.rs:14:5 + --> $DIR/issue-43623.rs:16:5 | LL | pub fn break_me(f: F) | -------- required by a bound in this -LL | where T: for<'b> Trait<'b>, -LL | F: for<'b> FnMut(>::Assoc) { - | -------------------------------------- required by this bound in `break_me` +... +LL | F: for<'b> FnMut(>::Assoc), + | ------------------------------ required by this bound in `break_me` +LL | { LL | break_me::; | ^^^^^^^^^^^^^^^^^^^^^^^ | | - | expected signature of `for<'b> fn(>::Assoc) -> _` - | found signature of `fn(_) -> _` + | expected signature of `fn(>::Assoc) -> _` + | found signature of `fn(()) -> _` -error[E0271]: type mismatch resolving `for<'b> >::Assoc,)>>::Output == ()` - --> $DIR/issue-43623.rs:14:5 - | -LL | pub fn break_me(f: F) - | -------- required by a bound in this -LL | where T: for<'b> Trait<'b>, -LL | F: for<'b> FnMut(>::Assoc) { - | ------------------------------ required by this bound in `break_me` -LL | break_me::; - | ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 2edc009746455..47cc64ec470a5 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -4,6 +4,8 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | + = note: the method `make_g` exists but the following trait bounds were not satisfied: + `for<'r> fn(&'r ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57362-2.rs:8:1 diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs index e5a9caa32fae7..9c2b2dc9f4dae 100644 --- a/src/test/ui/issues/issue-60283.rs +++ b/src/test/ui/issues/issue-60283.rs @@ -7,11 +7,13 @@ impl<'a> Trait<'a> for () { } pub fn foo(_: T, _: F) -where T: for<'a> Trait<'a>, - F: for<'a> FnMut(>::Item) {} +where + T: for<'a> Trait<'a>, + F: for<'a> FnMut(>::Item), +{ +} fn main() { foo((), drop) //~^ ERROR type mismatch in function arguments - //~| ERROR type mismatch resolving } diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index e74a34e247a67..ad679bfa22063 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -1,31 +1,18 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-60283.rs:14:13 + --> $DIR/issue-60283.rs:17:13 | LL | pub fn foo(_: T, _: F) | --- required by a bound in this -LL | where T: for<'a> Trait<'a>, -LL | F: for<'a> FnMut(>::Item) {} - | ------------------------------------- required by this bound in `foo` +... +LL | F: for<'a> FnMut(>::Item), + | ----------------------------- required by this bound in `foo` ... LL | foo((), drop) | ^^^^ | | - | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | found signature of `fn(_) -> _` - -error[E0271]: type mismatch resolving `for<'a> } as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()` - --> $DIR/issue-60283.rs:14:5 - | -LL | pub fn foo(_: T, _: F) - | --- required by a bound in this -LL | where T: for<'a> Trait<'a>, -LL | F: for<'a> FnMut(>::Item) {} - | ----------------------------- required by this bound in `foo` -... -LL | foo((), drop) - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | expected signature of `fn(<() as Trait<'a>>::Item) -> _` + | found signature of `fn(()) -> _` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs similarity index 57% rename from src/test/ui/lub-glb/old-lub-glb-hr.rs rename to src/test/ui/lub-glb/old-lub-glb-hr-eq.rs index bc7b787cd65ac..fbf4aee02045d 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs @@ -4,23 +4,19 @@ // longer get an error, because we recognize these two types as // equivalent! // -// Whoops -- now that we reinstituted the leak-check, we get an error -// again. +// check-pass -fn foo( - x: fn(&u8, &u8), - y: for<'a> fn(&'a u8, &'a u8), -) { +fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { + // The two types above are actually equivalent. With the older + // leak check, though, we didn't consider them as equivalent, and + // hence we gave errors. But now we've fixed that. let z = match 22 { 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( - x: fn(&u8, &u8), - y: for<'a> fn(&'a u8, &'a u8), -) { +fn foo_cast(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { let z = match 22 { // No error with an explicit cast: 0 => x as for<'a> fn(&'a u8, &'a u8), @@ -28,5 +24,4 @@ fn bar( }; } -fn main() { -} +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr new file mode 100644 index 0000000000000..b95e247d2a8cf --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/old-lub-glb-hr-noteq1.rs:11:14 + | +LL | _ => y, + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs new file mode 100644 index 0000000000000..918542d471b58 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs @@ -0,0 +1,24 @@ +// Test taking the LUB of two function types that are not equatable but where one is more +// general than the other. Test the case where the more general type (`x`) is the first +// match arm specifically. + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => x, + _ => y, //~ ERROR `match` arms have incompatible types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr new file mode 100644 index 0000000000000..305e952d6046b --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr @@ -0,0 +1,18 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq1.rs:11:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => x, + | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` +LL | | _ => y, + | | ^ one type is more general than the other +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs new file mode 100644 index 0000000000000..4bdd05b4f92fa --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs @@ -0,0 +1,33 @@ +// Test taking the LUB of two function types that are not equatable but where +// one is more general than the other. Test the case where the more general type +// (`x`) is the second match arm specifically. +// +// FIXME(#73154) Skip for compare-mode because the pure NLL checker accepts this +// test. (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens +// is that, due to the ordering of the match arms, we pick the correct "more +// general" fn type, and we ignore the errors from the non-NLL type checker that +// requires equality. The NLL type checker only requires a subtyping +// relationship, and that holds. +// +// ignore-compare-mode-nll + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => y, + _ => x, //~ ERROR `match` arms have incompatible types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr new file mode 100644 index 0000000000000..252e13aada054 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr @@ -0,0 +1,18 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq2.rs:20:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => y, + | | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8` +LL | | _ => x, + | | ^ one type is more general than the other +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr deleted file mode 100644 index 6d5d51174699f..0000000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:16:14 - | -LL | let z = match 22 { - | _____________- -LL | | 0 => x, - | | - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)` -LL | | _ => y, - | | ^ expected bound lifetime parameter, found concrete lifetime -LL | | }; - | |_____- `match` arms have incompatible types - | - = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` - found fn pointer `for<'a> fn(&'a u8, &'a u8)` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr new file mode 100644 index 0000000000000..51bf96f32335b --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 63bbae59991bc..39d351c235574 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,22 +1,17 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. -trait Foo { } +trait Foo {} -fn foo( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn foo(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { let z = match 22 { + //~^ ERROR mismatched types 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn bar(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { // Accepted with explicit case: let z = match 22 { 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>, @@ -24,5 +19,4 @@ fn bar( }; } -fn main() { -} +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 65c797f6b19d7..6eabe5eaeeeeb 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,17 +1,16 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-object.rs:12:14 +error[E0308]: mismatched types + --> $DIR/old-lub-glb-object.rs:7:13 | LL | let z = match 22 { - | _____________- + | _____________^ +LL | | LL | | 0 => x, - | | - this is found to be of type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` LL | | _ => y, - | | ^ expected bound lifetime parameter 'a, found concrete lifetime LL | | }; - | |_____- `match` arms have incompatible types + | |_____^ one type is more general than the other | - = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found reference `&dyn for<'a> Foo<&'a u8, &'a u8>` + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr new file mode 100644 index 0000000000000..6ed91b20ab8a6 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr @@ -0,0 +1,27 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:3:14 + | +LL | a.iter().map(|_: (u32, u32)| 45); + | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:4:14 + | +LL | a.iter().map(|_: &(u16, u16)| 45); + | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:5:14 + | +LL | a.iter().map(|_: (u16, u16)| 45); + | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index 521bd3695dfe5..e278049c8cc42 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,6 +7,9 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR type mismatch - //~| ERROR type mismatch + baz(f); + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 69a4b458ebf50..664fa4bcaf328 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,28 +22,43 @@ LL | a.iter().map(|_: (u16, u16)| 45); | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0631]: type mismatch in function arguments - --> $DIR/closure-arg-type-mismatch.rs:10:9 +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^ - | | - | expected signature of `for<'r> fn(*mut &'r u32) -> _` - | found signature of `fn(*mut &'a u32) -> _` + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` -error[E0271]: type mismatch resolving `for<'r> >::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr new file mode 100644 index 0000000000000..745a61b866ed2 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 40a4641fe7196..d2b78b4b7dba5 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,6 +5,5 @@ impl Foo for T {} fn baz(_: T) {} fn main() { - baz(|_| ()); //~ ERROR type mismatch - //~^ ERROR type mismatch + baz(|_| ()); //~ ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 389b21574465a..d6c17d125cf1e 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,28 +1,12 @@ -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | -LL | fn baz(_: T) {} - | --- required by this bound in `baz` -... LL | baz(|_| ()); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` + = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` + found type `std::ops::Fn<(&(),)>` -error[E0631]: type mismatch in closure arguments - --> $DIR/closure-mismatch.rs:8:5 - | -LL | fn baz(_: T) {} - | --- required by this bound in `baz` -... -LL | baz(|_| ()); - | ^^^ ------ found signature of `fn(_) -> _` - | | - | expected signature of `for<'r> fn(&'r ()) -> _` - | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr new file mode 100644 index 0000000000000..d762f55f9d5f1 --- /dev/null +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:5 + | +LL | want_G(baz); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index 2dd0c9796e258..539221b5a046c 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -13,11 +13,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -25,7 +25,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -37,7 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } @@ -48,5 +48,4 @@ fn supply_G() { want_G(baz); //~ ERROR mismatched types } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 27704b3e0a8c7..c9ce936c7d43f 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,21 +1,12 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | LL | want_G(baz); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | ^^^ one type is more general than the other | = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` - found fn item `for<'r> fn(&'r S) -> &'r S {baz}` + found fn pointer `for<'r> fn(&'r S) -> &'r S` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr index c3e8789a903b1..695f5506d5e38 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 159d32b50b03c..b83e07663faba 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr index 2aadd8f4f8c7e..a28f7aa3e08ca 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,46 @@ -error[E0308]: mismatched types - --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 + | +LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 + | +LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y, z); + | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 + | +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index dda6129e19536..c93f2890f1110 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -31,12 +31,10 @@ error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` + found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index fa2cc37d05b2b..de14d5ba82a1b 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,6 +5,8 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. +// +// check-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -14,11 +16,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -26,7 +28,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -38,10 +40,9 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr deleted file mode 100644 index a8a7e97e6acf6..0000000000000 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static.rs:41:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr index 434a3e47b492a..37f7fcf2e331a 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index 01f43aeebaf7c..2b2dd0dbbf250 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr new file mode 100644 index 0000000000000..848d4fef1abfc --- /dev/null +++ b/src/test/ui/rfc1623.nll.stderr @@ -0,0 +1,68 @@ +error[E0277]: `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + --> $DIR/rfc1623.rs:21:1 + | +LL | / static SOME_STRUCT: &SomeStruct = &SomeStruct { +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |__^ `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + | + = help: within `&SomeStruct`, the trait `std::marker::Sync` is not implemented for `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `&dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `SomeStruct` + = note: required because it appears within the type `&SomeStruct` + = note: shared static variables must have a type that implements `Sync` + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 55f5d0b94dcb0..aa6b1c0012c93 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -8,23 +8,21 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); - struct SomeStruct<'x, 'y, 'z: 'x> { foo: &'x Foo<'z>, bar: &'x Bar<'z>, - f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>, + f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>, } fn id(t: T) -> T { t } -static SOME_STRUCT: &SomeStruct = SomeStruct { //~ ERROR mismatched types +static SOME_STRUCT: &SomeStruct = &SomeStruct { foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR type mismatch in function arguments - //~| ERROR type mismatch resolving + //~^ ERROR mismatched types }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index ca956004ef76f..2efc58ac3819c 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,46 +1,12 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:22:35 - | -LL | static SOME_STRUCT: &SomeStruct = SomeStruct { - | ___________________________________^ -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, -LL | | -LL | | -LL | | }; - | |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct` - | -help: consider borrowing here - | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { -LL | foo: &Foo { bools: &[false, true] }, -LL | bar: &Bar { bools: &[true, true] }, -LL | f: &id, -LL | -LL | - ... - -error[E0631]: type mismatch in function arguments - --> $DIR/rfc1623.rs:25:8 - | -LL | fn id(t: T) -> T { - | ------------------- found signature of `fn(_) -> _` -... -LL | f: &id, - | ^^^ expected signature of `for<'a, 'b> fn(&'a Foo<'b>) -> _` - | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` - -error[E0271]: type mismatch resolving `for<'a, 'b> _ {id::<_>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>` - --> $DIR/rfc1623.rs:25:8 + --> $DIR/rfc1623.rs:24:8 | LL | f: &id, - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: expected type `std::ops::FnOnce<(&'a Foo<'b>,)>` + found type `std::ops::FnOnce<(&Foo<'_>,)>` -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0308, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 88bd990b1e81b..f2fbb0ba7d755 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -6,6 +6,11 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | | | | | this data with an anonymous lifetime `'_`... | ...is captured here... + | +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index d05e89e257f45..29d1b00094321 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/E0493.rs:17:17 | LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to previous error diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index bc08f33f82093..ed81734f6ebd7 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:9:60 | LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); - | ^^^^^^^^ statics cannot evaluate destructors + | ^^^^^^^^- value is dropped here + | | + | statics cannot evaluate destructors error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:9:60 @@ -18,7 +20,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:13:59 | LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); - | ^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^- value is dropped here + | | + | constants cannot evaluate destructors error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:13:59 @@ -34,37 +38,50 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:17:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; - | ^^^^^^^^^^^^^ statics cannot evaluate destructors + | ^^^^^^^^^^^^^ - value is dropped here + | | + | statics cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:20:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; - | ^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:23:24 | LL | const fn const_drop(_: T) {} - | ^ constant functions cannot evaluate destructors + | ^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:27:5 | LL | (x, ()).1 | ^^^^^^^ constant functions cannot evaluate destructors +LL | +LL | } + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:31:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; - | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:36:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; - | ^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to 10 previous errors diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr new file mode 100644 index 0000000000000..2407d13714a2a --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr @@ -0,0 +1,53 @@ +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:27:23 + | +LL | fn iter(&self) -> impl Iterator> { + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:39:9 + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | - let's call the lifetime of this reference `'1` +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:50:9 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | -- lifetime `'a` defined here +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` + | | + | lifetime `'a` defined here + | + = help: consider replacing `'a` with `'static` +help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs new file mode 100644 index 0000000000000..f78edb1c83a4c --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs @@ -0,0 +1,68 @@ +trait Foo {} +impl<'a, T: Foo> Foo for &'a T {} +impl Foo for Box {} + +struct Iter<'a, T> { + current: Option>, + remaining: T, +} + +impl<'a, T> Iterator for Iter<'a, T> +where + T: Iterator, + T::Item: Foo + 'a, +{ + type Item = Box; + + fn next(&mut self) -> Option { + let result = self.current.take(); + self.current = Box::new(self.remaining.next()).map(|f| Box::new(f) as _); + result + } +} + +struct Bar(Vec>); + +impl Bar { + fn iter(&self) -> impl Iterator> { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +struct Baz(Vec>); + +impl Baz { + fn iter(&self) -> impl Iterator> + '_ { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +struct Bat(Vec>); + +impl Bat { + fn iter<'a>(&'a self) -> impl Iterator> + 'a { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +struct Ban(Vec>); + +impl Ban { + fn iter<'a>(&'a self) -> impl Iterator> { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr new file mode 100644 index 0000000000000..1257e9b172cf7 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -0,0 +1,95 @@ +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:30:31 + | +LL | fn iter(&self) -> impl Iterator> { + | ----- this data with an anonymous lifetime `'_`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:27:23 + | +LL | fn iter(&self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:41:31 + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ----- this data with an anonymous lifetime `'_`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:38:23 + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:52:31 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | -------- this data with lifetime `'a`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:49:30 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:63:31 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | -------- this data with lifetime `'a`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr index 96f1656bae4ac..3c2226574ee9e 100644 --- a/src/test/ui/suggestions/suggest-move-types.stderr +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -125,6 +125,7 @@ LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime` error[E0747]: lifetime provided when a type was expected --> $DIR/suggest-move-types.rs:82:56 @@ -133,6 +134,7 @@ LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime` error: aborting due to 12 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr new file mode 100644 index 0000000000000..8c9cb742fac91 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 1c2051e7eaeeb..41e019247c942 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -14,8 +14,8 @@ trait Foo { struct X; impl Foo for X { - type Bar = impl Baz; //~ ERROR type mismatch in closure arguments - //~^ ERROR type mismatch resolving + type Bar = impl Baz; + //~^ ERROR mismatched types fn bar(&self) -> Self::Bar { |x| x diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index cc121ac89fb8d..cd637056c94ad 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -1,23 +1,12 @@ -error[E0631]: type mismatch in closure arguments +error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _` -... -LL | |x| x - | ----- found signature of `fn(_) -> _` + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: the return type of a function must have a statically known size + = note: expected type `std::ops::FnOnce<(&X,)>` + found type `std::ops::FnOnce<(&X,)>` -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X` - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime - | - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs index a6e26614a6a50..e2082d4f78e70 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: &isize) -> isize { (*x) * (*x) } +unsafe fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index b9ee9e460201a..b06f745e7c1f1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:26 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs index dd3b1afc39f31..dd76c597d28ad 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -extern "C" fn square(x: &isize) -> isize { (*x) * (*x) } +extern "C" fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 654b626cf65cc..8f6945cda806c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 + --> $DIR/unboxed-closures-wrong-abi.rs:20:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 + --> $DIR/unboxed-closures-wrong-abi.rs:25:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:24:26 + --> $DIR/unboxed-closures-wrong-abi.rs:30:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs index c689d79266187..02e8b7b47ae19 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -1,24 +1,30 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: isize) -> isize { x * x } +unsafe fn square(x: isize) -> isize { + x * x +} // note: argument type here is `isize`, not `&isize` -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -26,4 +32,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 434c8a579f671..93a645b485ef0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:26 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs index d9d85ee913266..963d892931a75 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs @@ -1,13 +1,13 @@ #![stable(feature = "foo", since = "1.33.0")] #![feature(staged_api)] -#![feature(const_compare_raw_pointers)] +#![feature(const_raw_ptr_deref)] #![feature(const_fn)] #[stable(feature = "foo", since = "1.33.0")] #[rustc_const_unstable(feature = "const_foo", issue = "none")] -const fn unstable(a: *const i32, b: *const i32) -> bool { - a == b - //~^ pointer operation is unsafe +const fn unstable(a: *const i32, b: i32) -> bool { + *a == b + //~^ dereference of raw pointer is unsafe } fn main() {} diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr b/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr index d8f3737c8f541..4642a7a5fc9f8 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr @@ -1,10 +1,10 @@ -error[E0133]: pointer operation is unsafe and requires unsafe function or block +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block --> $DIR/unsafe-unstable-const-fn.rs:9:5 | -LL | a == b - | ^^^^^^ pointer operation +LL | *a == b + | ^^ dereference of raw pointer | - = note: operations on pointers in constants + = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-for-self-2.nll.stderr b/src/test/ui/where-clauses/where-for-self-2.nll.stderr new file mode 100644 index 0000000000000..d0c476dc6ec05 --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self-2.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/where-for-self-2.rs:23:5 + | +LL | foo(&X); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 31174fd4cf163..37c6954fd52ee 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -14,9 +14,11 @@ impl Bar for &'static u32 { } fn foo(x: &T) - where for<'a> &'a T: Bar -{} +where + for<'a> &'a T: Bar, +{ +} fn main() { - foo(&X); //~ ERROR trait bound + foo(&X); //~ ERROR implementation of `Bar` is not general enough } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 9976243b200dc..30eb78b2da4f7 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied - --> $DIR/where-for-self-2.rs:21:5 +error: implementation of `Bar` is not general enough + --> $DIR/where-for-self-2.rs:23:5 | -LL | fn foo(x: &T) - | --- required by a bound in this -LL | where for<'a> &'a T: Bar - | --- required by this bound in `foo` +LL | / trait Bar { +LL | | fn bar(&self); +LL | | } + | |_- trait `Bar` defined here ... -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` +LL | foo(&X); + | ^^^ implementation of `Bar` is not general enough | - = help: the following implementations were found: - <&'static u32 as Bar> + = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index d9320e9147cff..3fa637b5a696f 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -444,10 +444,7 @@ fn map_lib_features( level: Status::Unstable, since: None, has_gate_test: false, - // FIXME(#57563): #57563 is now used as a common tracking issue, - // although we would like to have specific tracking issues for each - // `rustc_const_unstable` in the future. - tracking_issue: NonZeroU32::new(57563), + tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), }; mf(Ok((feature_name, feature)), file, i + 1); continue;