diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index f71cf09ecf630..8d97c3cbb0b0e 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -256,7 +256,6 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty // See issue #87748 - let constraints_implied_1 = self.add_implied_bounds(ty); let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) @@ -284,10 +283,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { // } // ``` // Both &Self::Bar and &() are WF - let constraints_implied_2 = - if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None }; + let constraints_implied = self.add_implied_bounds(norm_ty); normalized_inputs_and_output.push(norm_ty); - constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2) + constraints1.into_iter().chain(constraints_implied) }) .collect(); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 44da27a43db0a..025d2998b0052 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -394,10 +394,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::transmute => { self.copy_op_transmute(&args[0], dest)?; } - sym::assert_inhabited => { + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { let ty = instance.substs.type_at(0); let layout = self.layout_of(ty)?; + // For *all* intrinsics we first check `is_uninhabited` to give a more specific + // error message. if layout.abi.is_uninhabited() { // The run-time intrinsic panics just to get a good backtrace; here we abort // since there is no problem showing a backtrace even for aborts. @@ -409,6 +411,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), )?; } + if intrinsic_name == sym::assert_zero_valid + && !layout.might_permit_raw_init(self, /*zero:*/ true) + { + M::abort( + self, + format!( + "aborted execution: attempted to zero-initialize type `{}`, which is invalid", + ty + ), + )?; + } + if intrinsic_name == sym::assert_uninit_valid + && !layout.might_permit_raw_init(self, /*zero:*/ false) + { + M::abort( + self, + format!( + "aborted execution: attempted to leave type `{}` uninitialized, which is invalid", + ty + ), + )?; + } } sym::simd_insert => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); diff --git a/compiler/rustc_const_eval/src/transform/mod.rs b/compiler/rustc_const_eval/src/transform/mod.rs index 38c28f34934a4..a2928bdf51b83 100644 --- a/compiler/rustc_const_eval/src/transform/mod.rs +++ b/compiler/rustc_const_eval/src/transform/mod.rs @@ -1,5 +1,3 @@ pub mod check_consts; pub mod promote_consts; pub mod validate; - -pub use rustc_middle::mir::MirPass; diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index a92b20f5cb520..464155db89f48 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -27,7 +27,6 @@ use std::cell::Cell; use std::{cmp, iter, mem}; use crate::transform::check_consts::{qualifs, ConstCx}; -use crate::transform::MirPass; /// A `MirPass` for promotion. /// diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 0ab077cf2bf40..c86c8f81dbd96 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1,14 +1,13 @@ //! Validates the MIR to ensure that invariants are upheld. -use super::MirPass; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ - AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem, - PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, + AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPass, MirPhase, Operand, + PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index d64a589bd9b2a..3104bc185e756 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -214,7 +214,7 @@ pub trait Emitter { /// Formats the substitutions of the primary_span /// - /// The are a lot of conditions to this method, but in short: + /// There are a lot of conditions to this method, but in short: /// /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, /// we format the `help` suggestion depending on the content of the @@ -736,7 +736,9 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); - let left = margin.left(source_string.len()); // Left trim + // Left trim + let left = margin.left(source_string.len()); + // Account for unicode characters of width !=0 that were removed. let left = source_string .chars() @@ -1623,18 +1625,27 @@ impl EmitterWriter { suggestions.iter().take(MAX_SUGGESTIONS) { notice_capitalization |= only_capitalization; - // Only show underline if the suggestion spans a single line and doesn't cover the - // entirety of the code output. If you have multiple replacements in the same line - // of code, show the underline. - let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim()) - && complete.lines().count() == 1; let has_deletion = parts.iter().any(|p| p.is_deletion()); let is_multiline = complete.lines().count() > 1; - let show_diff = has_deletion && !is_multiline; + enum DisplaySuggestion { + Underline, + Diff, + None, + } + + let show_code_change = if has_deletion && !is_multiline { + DisplaySuggestion::Diff + } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim()) + && !is_multiline + { + DisplaySuggestion::Underline + } else { + DisplaySuggestion::None + }; - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { row_num += 1; } @@ -1657,7 +1668,7 @@ impl EmitterWriter { &self.maybe_anonymized(line_start + line_pos), Style::LineNumber, ); - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { // Add the line number for both addition and removal to drive the point home. // // N - fn foo(bar: A) { @@ -1727,7 +1738,7 @@ impl EmitterWriter { let mut offsets: Vec<(usize, isize)> = Vec::new(); // Only show an underline in the suggestions if the suggestion is not the // entirety of the code being shown and the displayed code is not multiline. - if show_underline { + if let DisplaySuggestion::Diff | DisplaySuggestion::Underline = show_code_change { draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); for part in parts { let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display; @@ -1755,7 +1766,7 @@ impl EmitterWriter { assert!(underline_start >= 0 && underline_end >= 0); let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { - if !show_diff { + if let DisplaySuggestion::Underline = show_code_change { // If this is a replacement, underline with `^`, if this is an addition // underline with `+`. buffer.putc( @@ -1766,7 +1777,7 @@ impl EmitterWriter { ); } } - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { // Colorize removal with red in diff format. buffer.set_style_range( row_num - 2, @@ -1797,7 +1808,7 @@ impl EmitterWriter { // if we elided some lines, add an ellipsis if lines.next().is_some() { buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); - } else if !show_underline { + } else if let DisplaySuggestion::None = show_code_change { draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1); row_num += 1; } @@ -2083,7 +2094,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\t', " "), // We do our own tab replacement ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently - ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk + ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always. ('\u{202E}', ""), ('\u{2066}', ""), diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index f9ef314627807..b0bea7312a7eb 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -27,7 +27,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor as _; -use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPhase, Promoted}; +use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; @@ -78,7 +78,6 @@ mod unreachable_prop; use rustc_const_eval::transform::check_consts; use rustc_const_eval::transform::promote_consts; use rustc_const_eval::transform::validate; -pub use rustc_const_eval::transform::MirPass; use rustc_mir_dataflow::rustc_peek; pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index a237ba5f2e880..44fc81a889d17 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -264,14 +264,9 @@ fn compare_predicate_entailment<'tcx>( // First liberate late bound regions and subst placeholders let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); - // Next, add all inputs and output as well-formed tys. Importantly, - // we have to do this before normalization, since the normalized ty may - // not contain the input parameters. See issue #87748. - wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); - // Also add the resulting inputs and output as well-formed. - // This probably isn't strictly necessary. + // Add the resulting inputs and output as well-formed. wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index e7fba3a70ff42..7bfd3f0ee8047 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -391,7 +391,6 @@ fn typeck_with_fallback<'tcx>( let mut wf_tys = FxHashSet::default(); // Compute the fty from point of view of inside the fn. let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); - wf_tys.extend(fn_sig.inputs_and_output.iter()); let fn_sig = inh.normalize_associated_types_in( body.value.span, body_id.hir_id, diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 3cfb4c674ab24..33a0c3275ca2a 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1334,11 +1334,6 @@ fn check_fn_or_method<'fcx, 'tcx>( ) { let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - // Unnormalized types in signature are WF too - implied_bounds.extend(sig.inputs()); - // FIXME(#27579) return types should not be implied bounds - implied_bounds.insert(sig.output()); - // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 23b28766d70ea..edbc250eb0d0c 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -860,12 +860,14 @@ extern "rust-intrinsic" { /// zero-initialization: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] pub fn assert_zero_valid(); /// A guard for unsafe functions that cannot ever be executed if `T` has invalid /// bit patterns: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] pub fn assert_uninit_valid(); /// Gets a reference to a static `Location` indicating where it was called. diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index f3ef6b3d0185e..35ce9400f8f4d 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1023,6 +1023,7 @@ pub trait Iterator { /// assert_eq!(iter.next(), None); /// ``` #[inline] + #[doc(alias = "drop_while")] #[stable(feature = "rust1", since = "1.0.0")] fn skip_while

(self, predicate: P) -> SkipWhile where diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs index 144a746062daa..8470ace24b845 100644 --- a/src/test/debuginfo/rc_arc.rs +++ b/src/test/debuginfo/rc_arc.rs @@ -1,4 +1,4 @@ -// pretty-printers are not loaded +// ignore-windows-gnu: pretty-printers are not loaded // compile-flags:-g // min-gdb-version: 8.1 diff --git a/src/test/ui/consts/assert-type-intrinsics.rs b/src/test/ui/consts/assert-type-intrinsics.rs new file mode 100644 index 0000000000000..31ff6aed03b2f --- /dev/null +++ b/src/test/ui/consts/assert-type-intrinsics.rs @@ -0,0 +1,22 @@ +// error-pattern: any use of this value will cause an error + +#![feature(never_type)] +#![feature(const_maybe_uninit_assume_init, const_assert_type2)] +#![feature(core_intrinsics)] + +use std::intrinsics; + +#[allow(invalid_value)] +fn main() { + use std::mem::MaybeUninit; + + const _BAD1: () = unsafe { + MaybeUninit::::uninit().assume_init(); + }; + const _BAD2: () = unsafe { + intrinsics::assert_uninit_valid::(); + }; + const _BAD3: () = unsafe { + intrinsics::assert_zero_valid::<&'static i32>(); + }; +} diff --git a/src/test/ui/consts/assert-type-intrinsics.stderr b/src/test/ui/consts/assert-type-intrinsics.stderr new file mode 100644 index 0000000000000..bb57ee82cc16f --- /dev/null +++ b/src/test/ui/consts/assert-type-intrinsics.stderr @@ -0,0 +1,39 @@ +error: any use of this value will cause an error + --> $DIR/assert-type-intrinsics.rs:14:9 + | +LL | / const _BAD1: () = unsafe { +LL | | MaybeUninit::::uninit().assume_init(); + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` +LL | | }; + | |______- + | + = note: `#[deny(const_err)]` on by default + = 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 #71800 + +error: any use of this value will cause an error + --> $DIR/assert-type-intrinsics.rs:17:9 + | +LL | / const _BAD2: () = unsafe { +LL | | intrinsics::assert_uninit_valid::(); + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid +LL | | }; + | |______- + | + = 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 #71800 + +error: any use of this value will cause an error + --> $DIR/assert-type-intrinsics.rs:20:9 + | +LL | / const _BAD3: () = unsafe { +LL | | intrinsics::assert_zero_valid::<&'static i32>(); + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid +LL | | }; + | |______- + | + = 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 #71800 + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/consts/assume-type-intrinsics.rs b/src/test/ui/consts/assume-type-intrinsics.rs deleted file mode 100644 index 77370e1ccc59e..0000000000000 --- a/src/test/ui/consts/assume-type-intrinsics.rs +++ /dev/null @@ -1,13 +0,0 @@ -// error-pattern: any use of this value will cause an error - -#![feature(never_type)] -#![feature(const_maybe_uninit_assume_init)] - -#[allow(invalid_value)] -fn main() { - use std::mem::MaybeUninit; - - const _BAD: () = unsafe { - MaybeUninit::::uninit().assume_init(); - }; -} diff --git a/src/test/ui/consts/assume-type-intrinsics.stderr b/src/test/ui/consts/assume-type-intrinsics.stderr deleted file mode 100644 index e660730396fa1..0000000000000 --- a/src/test/ui/consts/assume-type-intrinsics.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: any use of this value will cause an error - --> $DIR/assume-type-intrinsics.rs:11:9 - | -LL | / const _BAD: () = unsafe { -LL | | MaybeUninit::::uninit().assume_init(); - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` -LL | | }; - | |______- - | - = note: `#[deny(const_err)]` on by default - = 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 #71800 - -error: aborting due to previous error - diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr new file mode 100644 index 0000000000000..e37ec7f26651c --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5 + | +LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | s + | ^ returning this value requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs new file mode 100644 index 0000000000000..2e5ac7d7398eb --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs @@ -0,0 +1,22 @@ +// check-fail +// See issue #91068. Types in the substs of an associated type can't be implied +// to be WF, since they don't actually have to be constructed. + +trait Trait { + type Type; +} + +impl Trait for T { + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + s //~ ERROR lifetime mismatch [E0623] +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + println!("{}", y); +} diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr new file mode 100644 index 0000000000000..93ab5dceee947 --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr @@ -0,0 +1,13 @@ +error[E0623]: lifetime mismatch + --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5 + | +LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + | ------- ---------- + | | + | these two types are declared with different lifetimes... +LL | s + | ^ ...but data from `s` flows here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs deleted file mode 100644 index 93c3b3937cb81..0000000000000 --- a/src/test/ui/generic-associated-types/issue-87748.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Checks that we properly add implied bounds from unnormalized projections in -// inputs when typechecking functions. - -// check-pass - -#![feature(generic_associated_types)] - -trait MyTrait { - type Assoc<'a, 'b> where 'b: 'a; - fn do_sth(arg: Self::Assoc<'_, '_>); -} - -struct A; -struct B; -struct C; - -impl MyTrait for A { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: u32) {} -} -impl MyTrait for B { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: Self::Assoc<'_, '_>) {} -} -impl MyTrait for C { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: Self::Assoc<'static, 'static>) {} -} - -fn main () {} diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 183ef048f61ae..d9b2291f546ab 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 183ef048f61ae36aa389d1d0345cde940fe788e9 +Subproject commit d9b2291f546abc77d24499339a72a89127464b95