diff --git a/RELEASES.md b/RELEASES.md index 977796c66132e..b3d8c2f65f633 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,128 @@ +Version 1.46.0 (2020-08-27) +========================== + +Language +-------- +- [`if`, `match`, and `loop` expressions can now be used in const functions.][72437] +- [Additionally you are now also able to coerce and cast to slices (`&[T]`) in + const functions.][73862] +- [The `#[track_caller]` attribute can now be added to functions to use the + function's caller's location information for panic messages.][72445] +- [Recursively indexing into tuples no longer needs parentheses.][71322] E.g. + `x.0.0` over `(x.0).0`. +- [`mem::transmute` can now be used in static and constants.][72920] **Note** + You currently can't use `mem::transmute` in constant functions. + +Compiler +-------- +- [You can now use the `cdylib` target on Apple iOS and tvOS platforms.][73516] +- [Enabled static "Position Independent Executables" by default + for `x86_64-unknown-linux-musl`.][70740] + +Libraries +--------- +- [`mem::forget` is now a `const fn`.][73887] +- [`String` now implements `From`.][73466] +- [The `leading_ones`, and `trailing_ones` methods have been stabilised for all + integer types.][73032] +- [`vec::IntoIter` now implements `AsRef<[T]>`.][72583] +- [All non-zero integer types (`NonZeroU8`) now implement `TryFrom` for their + zero-able equivalent (e.g. `TryFrom`).][72717] +- [`&[T]` and `&mut [T]` now implement `PartialEq>`.][71660] +- [`(String, u16)` now implements `ToSocketAddrs`.][73007] +- [`vec::Drain<'_, T>` now implements `AsRef<[T]>`.][72584] + +Stabilized APIs +--------------- +- [`Option::zip`] +- [`vec::Drain::as_slice`] + +Cargo +----- +Added a number of new environment variables that are now available when +compiling your crate. + +- [`CARGO_BIN_NAME` and `CARGO_CRATE_NAME`][cargo/8270] Providing the name of + the specific binary being compiled and the name of the crate. +- [`CARGO_PKG_LICENSE`][cargo/8325] The license from the manifest of the package. +- [`CARGO_PKG_LICENSE_FILE`][cargo/8387] The path to the license file. + +Compatibility Notes +------------------- +- [The target configuration option `abi_blacklist` has been renamed + to `unsupported_abis`.][74150] The old name will still continue to work. +- [Rustc will now warn if you have a C-like enum that implements `Drop`.][72331] + This was previously accepted but will become a hard error in a future release. +- [Rustc will fail to compile if you have a struct with + `#[repr(i128)]` or `#[repr(u128)]`.][74109] This representation is currently only + allowed on `enum`s. +- [Tokens passed to `macro_rules!` are now always captured.][73293] This helps + ensure that spans have the correct information, and may cause breakage if you + were relying on receiving spans with dummy information. +- [The InnoSetup installer for Windows is no longer available.][72569] This was + a legacy installer that was replaced by a MSI installer a few years ago but + was still being built. +- [`{f32, f64}::asinh` now returns the correct values for negative numbers.][72486] +- [Rustc will no longer accept overlapping trait implementations that only + differ in how the lifetime was bound.][72493] +- [Rustc now correctly relates the lifetime of an existential associated + type.][71896] This fixes some edge cases where `rustc` would erroneously allow + you to pass a shorter lifetime than expected. + +[74109]: https://github.com/rust-lang/rust/pull/74109/ +[74150]: https://github.com/rust-lang/rust/pull/74150/ +[73862]: https://github.com/rust-lang/rust/pull/73862/ +[73887]: https://github.com/rust-lang/rust/pull/73887/ +[73466]: https://github.com/rust-lang/rust/pull/73466/ +[73516]: https://github.com/rust-lang/rust/pull/73516/ +[73293]: https://github.com/rust-lang/rust/pull/73293/ +[73007]: https://github.com/rust-lang/rust/pull/73007/ +[73032]: https://github.com/rust-lang/rust/pull/73032/ +[72920]: https://github.com/rust-lang/rust/pull/72920/ +[72569]: https://github.com/rust-lang/rust/pull/72569/ +[72583]: https://github.com/rust-lang/rust/pull/72583/ +[72584]: https://github.com/rust-lang/rust/pull/72584/ +[72717]: https://github.com/rust-lang/rust/pull/72717/ +[72437]: https://github.com/rust-lang/rust/pull/72437/ +[72445]: https://github.com/rust-lang/rust/pull/72445/ +[72486]: https://github.com/rust-lang/rust/pull/72486/ +[72493]: https://github.com/rust-lang/rust/pull/72493/ +[72331]: https://github.com/rust-lang/rust/pull/72331/ +[71896]: https://github.com/rust-lang/rust/pull/71896/ +[71660]: https://github.com/rust-lang/rust/pull/71660/ +[71322]: https://github.com/rust-lang/rust/pull/71322/ +[70740]: https://github.com/rust-lang/rust/pull/70740/ +[cargo/8270]: https://github.com/rust-lang/cargo/pull/8270/ +[cargo/8325]: https://github.com/rust-lang/cargo/pull/8325/ +[cargo/8387]: https://github.com/rust-lang/cargo/pull/8387/ +[`Option::zip`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.zip +[`vec::Drain::as_slice`]: https://doc.rust-lang.org/stable/std/vec/struct.Drain.html#method.as_slice + + +Version 1.45.2 (2020-08-03) +========================== + +* [Fix bindings in tuple struct patterns][74954] +* [Fix track_caller integration with trait objects][74784] + +[74954]: https://github.com/rust-lang/rust/issues/74954 +[74784]: https://github.com/rust-lang/rust/issues/74784 + + +Version 1.45.1 (2020-07-30) +========================== + +* [Fix const propagation with references.][73613] +* [rustfmt accepts rustfmt_skip in cfg_attr again.][73078] +* [Avoid spurious implicit region bound.][74509] +* [Install clippy on x.py install][74457] + +[73613]: https://github.com/rust-lang/rust/pull/73613 +[73078]: https://github.com/rust-lang/rust/issues/73078 +[74509]: https://github.com/rust-lang/rust/pull/74509 +[74457]: https://github.com/rust-lang/rust/pull/74457 + + Version 1.45.0 (2020-07-16) ========================== @@ -47,7 +172,7 @@ Libraries // Prints "abcdefghijklmnopqrstuvwxyz" ``` - [`OsString` now implements `FromStr`.][71662] -- [The `saturating_neg` method as been added to all signed integer primitive +- [The `saturating_neg` method has been added to all signed integer primitive types, and the `saturating_abs` method has been added for all integer primitive types.][71886] - [`Arc`, `Rc` now implement `From>`, and `Box` now @@ -82,6 +207,9 @@ Stabilized APIs Cargo ----- +- [Cargo uses the `embed-bitcode` flag to optimize disk usage and build + time.][cargo/8066] + Misc ---- - [Rustdoc now supports strikethrough text in Markdown.][71928] E.g. @@ -97,12 +225,18 @@ Compatibility Notes - [Rustdoc's CLI's extra error exit codes have been removed.][71900] These were previously undocumented and not intended for public use. Rustdoc still provides a non-zero exit code on errors. +- [Rustc's `lto` flag is incompatible with the new `embed-bitcode=no`.][71848] + This may cause issues if LTO is enabled through `RUSTFLAGS` or `cargo rustc` + flags while cargo is adding `embed-bitcode` itself. The recommended way to + control LTO is with Cargo profiles, either in `Cargo.toml` or `.cargo/config`, + or by setting `CARGO_PROFILE__LTO` in the environment. Internals Only -------------- - [Make clippy a git subtree instead of a git submodule][70655] - [Unify the undo log of all snapshot types][69464] +[71848]: https://github.com/rust-lang/rust/issues/71848/ [73420]: https://github.com/rust-lang/rust/issues/73420/ [72324]: https://github.com/rust-lang/rust/pull/72324/ [71843]: https://github.com/rust-lang/rust/pull/71843/ @@ -129,6 +263,7 @@ Internals Only [69813]: https://github.com/rust-lang/rust/pull/69813/ [69464]: https://github.com/rust-lang/rust/pull/69464/ [68717]: https://github.com/rust-lang/rust/pull/68717/ +[cargo/8066]: https://github.com/rust-lang/cargo/pull/8066 [`Arc::as_ptr`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.as_ptr [`BTreeMap::remove_entry`]: https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.remove_entry [`Rc::as_ptr`]: https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.as_ptr diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh index 78bf4527feff1..1c0ef6c2b30b4 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh @@ -7,7 +7,7 @@ target="x86_64-fortanix-unknown-sgx" install_prereq() { curl https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add - - add-apt-repository -y 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main' + add-apt-repository -y 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main' apt-get update apt-get install -y --no-install-recommends \ build-essential \ diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs index 8c8550d377a6e..45dbaead08c11 100644 --- a/src/librustc_trait_selection/traits/auto_trait.rs +++ b/src/librustc_trait_selection/traits/auto_trait.rs @@ -729,7 +729,7 @@ impl AutoTraitFinder<'tcx> { // and turn them into an explicit negative impl for our type. debug!("Projecting and unifying projection predicate {:?}", predicate); - match poly_project_and_unify_type(select, &obligation.with(p)) { + match project::poly_project_and_unify_type(select, &obligation.with(p)) { Err(e) => { debug!( "evaluate_nested_obligations: Unable to unify predicate \ @@ -738,7 +738,11 @@ impl AutoTraitFinder<'tcx> { ); return false; } - Ok(Some(v)) => { + Ok(Err(project::InProgress)) => { + debug!("evaluate_nested_obligations: recursive projection predicate"); + return false; + } + Ok(Ok(Some(v))) => { // We only care about sub-obligations // when we started out trying to unify // some inference variables. See the comment above @@ -757,8 +761,8 @@ impl AutoTraitFinder<'tcx> { } } } - Ok(None) => { - // It's ok not to make progress when hvave no inference variables - + Ok(Ok(None)) => { + // It's ok not to make progress when have no inference variables - // in that case, we were only performing unifcation to check if an // error occurred (which would indicate that it's impossible for our // type to implement the auto trait). diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index 800aef7284f9e..87960076a8939 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -426,14 +426,20 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::Projection(ref data) => { let project_obligation = obligation.with(*data); + let tcx = self.selcx.tcx(); match project::poly_project_and_unify_type(self.selcx, &project_obligation) { - Ok(None) => { - let tcx = self.selcx.tcx(); - pending_obligation.stalled_on = - trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref(tcx)); + Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)), + Ok(Ok(None)) => { + pending_obligation.stalled_on = trait_ref_infer_vars( + self.selcx, + project_obligation.predicate.to_poly_trait_ref(tcx), + ); ProcessResult::Unchanged } - Ok(Some(os)) => ProcessResult::Changed(mk_pending(os)), + // Let the caller handle the recursion + Ok(Err(project::InProgress)) => ProcessResult::Changed(mk_pending(vec![ + pending_obligation.obligation.clone(), + ])), Err(e) => ProcessResult::Error(CodeProjectionError(e)), } } diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index e8006129e3ef8..0585c1bd416fb 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -51,9 +51,7 @@ pub use self::object_safety::is_vtable_safe_method; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::ObjectSafetyViolation; pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; -pub use self::project::{ - normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type, -}; +pub use self::project::{normalize, normalize_projection_type, normalize_to}; pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::specialization_graph::FutureCompatOverlapError; diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index bd86109e5a491..f02702cae0f86 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -40,6 +40,8 @@ pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<' pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>; +pub(super) struct InProgress; + /// When attempting to resolve `::Name` ... #[derive(Debug)] pub enum ProjectionTyError<'tcx> { @@ -142,10 +144,26 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> { /// /// If successful, this may result in additional obligations. Also returns /// the projection cache key used to track these additional obligations. -pub fn poly_project_and_unify_type<'cx, 'tcx>( +/// +/// ## Returns +/// +/// - `Err(_)`: the projection can be normalized, but is not equal to the +/// expected type. +/// - `Ok(Err(InProgress))`: this is called recursively while normalizing +/// the same projection. +/// - `Ok(Ok(None))`: The projection cannot be normalized due to ambiguity +/// (resolving some inference variables in the projection may fix this). +/// - `Ok(Ok(Some(obligations)))`: The projection bound holds subject to +/// the given obligations. If the projection cannot be normalized because +/// the required trait bound doesn't hold this returned with `obligations` +/// being a predicate that cannot be proven. +pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &PolyProjectionObligation<'tcx>, -) -> Result>>, MismatchedProjectionTypes<'tcx>> { +) -> Result< + Result>>, InProgress>, + MismatchedProjectionTypes<'tcx>, +> { debug!("poly_project_and_unify_type(obligation={:?})", obligation); let infcx = selcx.infcx(); @@ -164,10 +182,15 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>( /// ::U == V /// /// If successful, this may result in additional obligations. +/// +/// See [poly_project_and_unify_type] for an explanation of the return value. fn project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionObligation<'tcx>, -) -> Result>>, MismatchedProjectionTypes<'tcx>> { +) -> Result< + Result>>, InProgress>, + MismatchedProjectionTypes<'tcx>, +> { debug!("project_and_unify_type(obligation={:?})", obligation); let mut obligations = vec![]; @@ -179,8 +202,9 @@ fn project_and_unify_type<'cx, 'tcx>( obligation.recursion_depth, &mut obligations, ) { - Some(n) => n, - None => return Ok(None), + Ok(Some(n)) => n, + Ok(None) => return Ok(Ok(None)), + Err(InProgress) => return Ok(Err(InProgress)), }; debug!( @@ -195,7 +219,7 @@ fn project_and_unify_type<'cx, 'tcx>( { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); - Ok(Some(obligations)) + Ok(Ok(Some(obligations))) } Err(err) => { debug!("project_and_unify_type: equating types encountered error {:?}", err); @@ -323,8 +347,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { let ty = ty.super_fold_with(self); match ty.kind { - ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { - // (*) + ty::Opaque(def_id, substs) => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty, @@ -352,9 +375,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } ty::Projection(ref data) if !data.has_escaping_bound_vars() => { - // (*) - - // (*) This is kind of hacky -- we need to be able to + // This is kind of hacky -- we need to be able to // handle normalization within binders because // otherwise we wind up a need to normalize when doing // trait matching (since you can have a trait @@ -421,6 +442,8 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( depth, obligations, ) + .ok() + .flatten() .unwrap_or_else(move || { // if we bottom out in ambiguity, create a type variable // and a deferred predicate to resolve this when more type @@ -457,7 +480,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec>, -) -> Option> { +) -> Result>, InProgress> { let infcx = selcx.infcx(); let projection_ty = infcx.resolve_vars_if_possible(&projection_ty); @@ -489,7 +512,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( "opt_normalize_projection_type: \ found cache entry: ambiguous" ); - return None; + return Ok(None); } Err(ProjectionCacheEntry::InProgress) => { // If while normalized A::B, we are asked to normalize @@ -504,24 +527,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // to normalize `A::B`, we will want to check the // where-clauses in scope. So we will try to unify `A::B` // with `A::B`, which can trigger a recursive - // normalization. In that case, I think we will want this code: - // - // ``` - // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id, - // projection_ty.substs; - // return Some(NormalizedTy { value: v, obligations: vec![] }); - // ``` + // normalization. debug!( "opt_normalize_projection_type: \ found cache entry: in-progress" ); - // But for now, let's classify this as an overflow: - let recursion_limit = selcx.tcx().sess.recursion_limit(); - let obligation = - Obligation::with_depth(cause, recursion_limit.0, param_env, projection_ty); - selcx.infcx().report_overflow_error(&obligation, false); + return Err(InProgress); } Err(ProjectionCacheEntry::NormalizedTy(ty)) => { // This is the hottest path in this function. @@ -557,7 +570,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( cause, depth, )); - return Some(ty.value); + return Ok(Some(ty.value)); } Err(ProjectionCacheEntry::Error) => { debug!( @@ -566,7 +579,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( ); let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); obligations.extend(result.obligations); - return Some(result.value); + return Ok(Some(result.value)); } } @@ -613,7 +626,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( let cache_value = prune_cache_value_obligations(infcx, &result); infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, cache_value); obligations.extend(result.obligations); - Some(result.value) + Ok(Some(result.value)) } Ok(ProjectedTy::NoProgress(projected_ty)) => { debug!( @@ -624,7 +637,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( let result = Normalized { value: projected_ty, obligations: vec![] }; infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); // No need to extend `obligations`. - Some(result.value) + Ok(Some(result.value)) } Err(ProjectionTyError::TooManyCandidates) => { debug!( @@ -632,7 +645,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( too many candidates" ); infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); - None + Ok(None) } Err(ProjectionTyError::TraitSelectionError(_)) => { debug!("opt_normalize_projection_type: ERROR"); @@ -644,7 +657,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( infcx.inner.borrow_mut().projection_cache().error(cache_key); let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); obligations.extend(result.obligations); - Some(result.value) + Ok(Some(result.value)) } } } @@ -1115,11 +1128,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( } super::ImplSourceAutoImpl(..) | super::ImplSourceBuiltin(..) => { // These traits have no associated types. - span_bug!( + selcx.tcx().sess.delay_span_bug( obligation.cause.span, - "Cannot project an associated type from `{:?}`", - impl_source + &format!("Cannot project an associated type from `{:?}`", impl_source), ); + return Err(()); } }; diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs index 59fa4c1598d41..93652329305a5 100644 --- a/src/librustc_trait_selection/traits/query/normalize.rs +++ b/src/librustc_trait_selection/traits/query/normalize.rs @@ -101,8 +101,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { let ty = ty.super_fold_with(self); match ty.kind { - ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { - // (*) + ty::Opaque(def_id, substs) => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty, @@ -140,8 +139,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } ty::Projection(ref data) if !data.has_escaping_bound_vars() => { - // (*) - // (*) This is kind of hacky -- we need to be able to + // This is kind of hacky -- we need to be able to // handle normalization within binders because // otherwise we wind up a need to normalize when doing // trait matching (since you can have a trait diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index ba5e60012da19..5c759e82c244b 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -458,7 +458,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &ty::PredicateKind::Projection(data) => { let project_obligation = obligation.with(data); match project::poly_project_and_unify_type(self, &project_obligation) { - Ok(Some(mut subobligations)) => { + Ok(Ok(Some(mut subobligations))) => { self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); let result = self.evaluate_predicates_recursively( previous_stack, @@ -471,7 +471,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } result } - Ok(None) => Ok(EvaluatedToAmbig), + Ok(Ok(None)) => Ok(EvaluatedToAmbig), + // EvaluatedToRecur might also be acceptable here, but use + // Unknown for now because it means that we won't dismiss a + // selection candidate solely because it has a projection + // cycle. This is closest to the previous behavior of + // immediately erroring. + Ok(Err(project::InProgress)) => Ok(EvaluatedToUnknown), Err(_) => Ok(EvaluatedToErr), } } diff --git a/src/librustc_typeck/check/place_op.rs b/src/librustc_typeck/check/place_op.rs index b7c8f310a1414..cf2a47b59a4e6 100644 --- a/src/librustc_typeck/check/place_op.rs +++ b/src/librustc_typeck/check/place_op.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::autoderef::Autoderef; +use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already. @@ -245,19 +246,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } match expr.kind { - hir::ExprKind::Index(ref base_expr, ref index_expr) => { - // We need to get the final type in case dereferences were needed for the trait - // to apply (#72002). - let index_expr_ty = self.tables.borrow().expr_ty_adjusted(index_expr); - self.convert_place_op_to_mutable( - PlaceOp::Index, - expr, - base_expr, - &[index_expr_ty], - ); + hir::ExprKind::Index(ref base_expr, ..) => { + self.convert_place_op_to_mutable(PlaceOp::Index, expr, base_expr); } hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base_expr) => { - self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr, &[]); + self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr); } _ => {} } @@ -269,9 +262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op: PlaceOp, expr: &hir::Expr<'_>, base_expr: &hir::Expr<'_>, - arg_tys: &[Ty<'tcx>], ) { - debug!("convert_place_op_to_mutable({:?}, {:?}, {:?}, {:?})", op, expr, base_expr, arg_tys); + debug!("convert_place_op_to_mutable({:?}, {:?}, {:?})", op, expr, base_expr); if !self.tables.borrow().is_method_call(expr) { debug!("convert_place_op_to_mutable - builtin, nothing to do"); return; @@ -286,6 +278,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .expect("place op takes something that is not a ref") .ty; + let arg_ty = match op { + PlaceOp::Deref => None, + PlaceOp::Index => { + // We would need to recover the `T` used when we resolve `<_ as Index>::index` + // in try_index_step. This is the subst at index 1. + // + // Note: we should *not* use `expr_ty` of index_expr here because autoderef + // during coercions can cause type of index_expr to differ from `T` (#72002). + // We also could not use `expr_ty_adjusted` of index_expr because reborrowing + // during coercions can also cause type of index_expr to differ from `T`, + // which can potentially cause regionck failure (#74933). + Some(self.tables.borrow().node_substs(expr.hir_id).type_at(1)) + } + }; + let arg_tys = match arg_ty { + None => &[], + Some(ref ty) => slice::from_ref(ty), + }; + let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op); let method = match method { Some(ok) => self.register_infer_ok_obligations(ok), diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs index 71ac914ef5759..fa75f6bc15228 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs @@ -26,16 +26,16 @@ impl Tr for u32 { // ...but only if this actually breaks the cycle impl Tr for bool { -//~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::B == _` type A = Box; - //~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { -//~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::B == _` type B = &'static Self::A; - //~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::A == _` } fn main() { diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr index 6a8526f6aad1b..0aea30b11126b 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -1,33 +1,34 @@ -error[E0275]: overflow evaluating the requirement `<() as Tr>::B` +error[E0275]: overflow evaluating the requirement `<() as Tr>::B == _` --> $DIR/defaults-cyclic-fail-1.rs:10:6 | LL | impl Tr for () {} | ^^ -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-1.rs:28:6 | LL | impl Tr for bool { - | ^^ + | ^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-1.rs:35:6 | LL | impl Tr for usize { - | ^^ + | ^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-1.rs:30:5 | LL | type A = Box; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::A` +error[E0271]: type mismatch resolving `::A == _` --> $DIR/defaults-cyclic-fail-1.rs:37:5 | LL | type B = &'static Self::A; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0275`. +Some errors have detailed explanations: E0271, E0275. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs index 05091e3f498c7..edcd310908aa4 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -10,7 +10,7 @@ trait Tr { // ...but is an error in any impl that doesn't override at least one of the defaults impl Tr for () {} -//~^ ERROR overflow evaluating the requirement +//~^ ERROR type mismatch resolving `<() as Tr>::B == _` // As soon as at least one is redefined, it works: impl Tr for u8 { @@ -28,16 +28,16 @@ impl Tr for u32 { // ...but only if this actually breaks the cycle impl Tr for bool { -//~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::B == _` type A = Box; - //~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { -//~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::B == _` type B = &'static Self::A; - //~^ ERROR overflow evaluating the requirement + //~^ ERROR type mismatch resolving `::A == _` } fn main() { diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr index 78772df963885..f39021c30edc1 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -1,33 +1,33 @@ -error[E0275]: overflow evaluating the requirement `<() as Tr>::B` +error[E0271]: type mismatch resolving `<() as Tr>::B == _` --> $DIR/defaults-cyclic-fail-2.rs:12:6 | LL | impl Tr for () {} - | ^^ + | ^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-2.rs:30:6 | LL | impl Tr for bool { - | ^^ + | ^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-2.rs:37:6 | LL | impl Tr for usize { - | ^^ + | ^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-2.rs:32:5 | LL | type A = Box; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::A` +error[E0271]: type mismatch resolving `::A == _` --> $DIR/defaults-cyclic-fail-2.rs:39:5 | LL | type B = &'static Self::A; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/normalize-cycle-in-eval-no-region.rs b/src/test/ui/associated-types/normalize-cycle-in-eval-no-region.rs new file mode 100644 index 0000000000000..0fd2c707938c6 --- /dev/null +++ b/src/test/ui/associated-types/normalize-cycle-in-eval-no-region.rs @@ -0,0 +1,20 @@ +// Case that the fix for #74868 also allowed to compile + +// check-pass + +trait BoxedDsl { + type Output; +} + +impl BoxedDsl for T +where + T: BoxedDsl, +{ + type Output = ::Output; +} + +trait HandleUpdate {} + +impl HandleUpdate for T where T: BoxedDsl {} + +fn main() {} diff --git a/src/test/ui/associated-types/normalize-cycle-in-eval.rs b/src/test/ui/associated-types/normalize-cycle-in-eval.rs new file mode 100644 index 0000000000000..dff4c9051f47a --- /dev/null +++ b/src/test/ui/associated-types/normalize-cycle-in-eval.rs @@ -0,0 +1,43 @@ +// regression test for #74868 + +// check-pass + +trait BoxedDsl<'a> { + type Output; +} + +impl<'a, T> BoxedDsl<'a> for T +where + T: BoxedDsl<'a>, +{ + type Output = >::Output; +} + +// Showing this trait is wf requires proving +// Self: HandleUpdate +// +// The impl below is a candidate for this projection, as well as the `Self: +// HandleUpdate` bound in the environment. +// We evaluate both candidates to see if we need to consider both applicable. +// Evaluating the impl candidate requires evaluating +// >::Output == () +// The above impl cause normalizing the above type normalize to itself. +// +// This previously compiled because we would generate a new region +// variable each time around the cycle, and evaluation would eventually return +// `EvaluatedToErr` from the `Self: Sized` in the impl, which would in turn +// leave the bound as the only candidate. +// +// #73452 changed this so that region variables are canonicalized when we +// normalize, which means that the projection cycle is detected before +// evaluation returns EvaluatedToErr. The cycle resulted in an error being +// emitted immediately, causing this to fail to compile. +// +// To fix this, normalization doesn't directly emit errors when it finds a +// cycle, instead letting the caller handle it. This restores the original +// behavior. +trait HandleUpdate {} + +impl HandleUpdate for T where T: BoxedDsl<'static, Output = ()> {} + +fn main() {} diff --git a/src/test/ui/auto-traits/issue-23080-2.rs b/src/test/ui/auto-traits/issue-23080-2.rs index 7f6b9e3fba79f..867f24f8cb45e 100644 --- a/src/test/ui/auto-traits/issue-23080-2.rs +++ b/src/test/ui/auto-traits/issue-23080-2.rs @@ -1,5 +1,3 @@ -//~ ERROR - #![feature(optin_builtin_traits)] #![feature(negative_impls)] diff --git a/src/test/ui/auto-traits/issue-23080-2.stderr b/src/test/ui/auto-traits/issue-23080-2.stderr index 48ce09aaa34da..efeceafdd2a7d 100644 --- a/src/test/ui/auto-traits/issue-23080-2.stderr +++ b/src/test/ui/auto-traits/issue-23080-2.stderr @@ -1,17 +1,11 @@ error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080-2.rs:7:10 + --> $DIR/issue-23080-2.rs:5:10 | LL | unsafe auto trait Trait { | ----- auto trait cannot have items LL | type Output; | ^^^^^^ -error[E0275]: overflow evaluating the requirement `<() as Trait>::Output` - | - = note: required because of the requirements on the impl of `Trait` for `()` - = note: required because of the requirements on the impl of `Trait` for `()` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0275, E0380. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0380`. diff --git a/src/test/ui/issues/issue-21946.rs b/src/test/ui/issues/issue-21946.rs index 2d99769cfa31c..0a9f8f50bdcbe 100644 --- a/src/test/ui/issues/issue-21946.rs +++ b/src/test/ui/issues/issue-21946.rs @@ -5,9 +5,9 @@ trait Foo { struct FooStruct; impl Foo for FooStruct { -//~^ ERROR overflow evaluating the requirement `::A` + //~^ ERROR overflow evaluating the requirement `::A == _` type A = ::A; - //~^ ERROR overflow evaluating the requirement `::A` + //~^ ERROR overflow evaluating the requirement `::A == _` } fn main() {} diff --git a/src/test/ui/issues/issue-21946.stderr b/src/test/ui/issues/issue-21946.stderr index 5ac49f61543e4..582ce393d7f54 100644 --- a/src/test/ui/issues/issue-21946.stderr +++ b/src/test/ui/issues/issue-21946.stderr @@ -1,10 +1,10 @@ -error[E0275]: overflow evaluating the requirement `::A` +error[E0275]: overflow evaluating the requirement `::A == _` --> $DIR/issue-21946.rs:7:6 | LL | impl Foo for FooStruct { | ^^^ -error[E0275]: overflow evaluating the requirement `::A` +error[E0275]: overflow evaluating the requirement `::A == _` --> $DIR/issue-21946.rs:9:5 | LL | type A = ::A; diff --git a/src/test/ui/issues/issue-23122-1.stderr b/src/test/ui/issues/issue-23122-1.stderr index 1b752b7afe2e6..4e2e837c07c6b 100644 --- a/src/test/ui/issues/issue-23122-1.stderr +++ b/src/test/ui/issues/issue-23122-1.stderr @@ -1,10 +1,10 @@ -error[E0275]: overflow evaluating the requirement ` as Next>::Next` +error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` --> $DIR/issue-23122-1.rs:7:15 | LL | impl Next for GetNext { | ^^^^ -error[E0275]: overflow evaluating the requirement ` as Next>::Next` +error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` --> $DIR/issue-23122-1.rs:9:5 | LL | type Next = as Next>::Next; diff --git a/src/test/ui/mir/issue-75419-validation-impl-trait.rs b/src/test/ui/mir/issue-75419-validation-impl-trait.rs new file mode 100644 index 0000000000000..a8741befb0cfe --- /dev/null +++ b/src/test/ui/mir/issue-75419-validation-impl-trait.rs @@ -0,0 +1,13 @@ +// build-pass + +// This used to fail MIR validation due to the types on both sides of +// an assignment not being equal. +// The failure doesn't occur with a check-only build. + +fn iter_slice<'a, T>(xs: &'a [T]) -> impl Iterator { + xs.iter() +} + +fn main() { + iter_slice::<()> as fn(_) -> _; +} diff --git a/src/test/ui/typeck/issue-74933.rs b/src/test/ui/typeck/issue-74933.rs new file mode 100644 index 0000000000000..4b6c173b8ce58 --- /dev/null +++ b/src/test/ui/typeck/issue-74933.rs @@ -0,0 +1,38 @@ +// check-pass +// +// rust-lang/rust#74933: Lifetime error when indexing with borrowed index + +use std::ops::{Index, IndexMut}; + +struct S(V); +struct K<'a>(&'a ()); +struct V; + +impl<'a> Index<&'a K<'a>> for S { + type Output = V; + + fn index(&self, _: &'a K<'a>) -> &V { + &self.0 + } +} + +impl<'a> IndexMut<&'a K<'a>> for S { + fn index_mut(&mut self, _: &'a K<'a>) -> &mut V { + &mut self.0 + } +} + +impl V { + fn foo(&mut self) {} +} + +fn test(s: &mut S, k: &K<'_>) { + s[k] = V; + s[k].foo(); +} + +fn main() { + let mut s = S(V); + let k = K(&()); + test(&mut s, &k); +} diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 72437e070044c..88081efabd3ec 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -32,8 +32,7 @@ 'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'}, 'rust-by-example': {'steveklabnik', 'marioidival'}, 'embedded-book': { - 'adamgreig', 'andre-richter', 'jamesmunns', 'korken89', - 'ryankurte', 'thejpster', 'therealprof', + 'adamgreig', 'andre-richter', 'jamesmunns', 'therealprof', }, 'edition-guide': {'ehuss', 'steveklabnik'}, 'rustc-dev-guide': {'mark-i-m', 'spastorino', 'amanjeev', 'JohnTitor'},