diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 24332690bec31..92d2d04f23f23 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,13 +7,16 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). +use crate::type_check::constraint_conversion::ConstraintConversion; use rustc_index::vec::Idx; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::*; -use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::Ty; use rustc_span::Span; -use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; +use rustc_trait_selection::traits::query::Fallible; +use type_op::TypeOpOutput; use crate::universal_regions::UniversalRegions; @@ -30,6 +33,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let (&normalized_output_ty, normalized_input_tys) = normalized_inputs_and_output.split_last().unwrap(); + debug!(?normalized_output_ty); + debug!(?normalized_input_tys); + let mir_def_id = body.source.def_id().expect_local(); // If the user explicitly annotated the input types, extract @@ -75,10 +81,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .delay_span_bug(body.span, "found more normalized_input_ty than local_decls"); break; } + // In MIR, argument N is stored in local N+1. let local = Local::new(argument_index + 1); let mir_input_ty = body.local_decls[local].ty; + let mir_input_span = body.local_decls[local].source_info.span; self.equate_normalized_input_or_output( normalized_input_ty, @@ -100,6 +108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // If the user explicitly annotated the input types, enforce those. let user_provided_input_ty = self.normalize(user_provided_input_ty, Locations::All(mir_input_span)); + self.equate_normalized_input_or_output( user_provided_input_ty, mir_input_ty, @@ -167,30 +176,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd // like to normalize *before* inserting into `local_decls`, but // doing so ends up causing some other trouble. - let b = match self - .infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .normalize(b) - { - Ok(n) => { - debug!("equate_inputs_and_outputs: {:?}", n); - if n.obligations.iter().all(|o| { - matches!( - o.predicate.kind().skip_binder(), - ty::PredicateKind::RegionOutlives(_) - | ty::PredicateKind::TypeOutlives(_) - ) - }) { - n.value - } else { - b - } - } + let b = match self.normalize_and_add_constraints(b) { + Ok(n) => n, Err(_) => { debug!("equate_inputs_and_outputs: NoSolution"); b } }; + // Note: if we have to introduce new placeholders during normalization above, then we won't have // added those universes to the universe info, which we would want in `relate_tys`. if let Err(terr) = @@ -207,4 +200,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } } + + pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible> { + let TypeOpOutput { output: norm_ty, constraints, .. } = + self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?; + + debug!("{:?} normalized to {:?}", t, norm_ty); + + for data in constraints.into_iter().collect::>() { + ConstraintConversion::new( + self.infcx, + &self.borrowck_context.universal_regions, + &self.region_bound_pairs, + Some(self.implicit_region_bound), + self.param_env, + Locations::All(DUMMY_SP), + ConstraintCategory::Internal, + &mut self.borrowck_context.constraints, + ) + .convert_all(&*data); + } + + Ok(norm_ty) + } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index ddd077c22faf8..da26d9c7b8779 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -893,11 +893,11 @@ struct TypeChecker<'a, 'tcx> { } struct BorrowCheckContext<'a, 'tcx> { - universal_regions: &'a UniversalRegions<'tcx>, + pub(crate) universal_regions: &'a UniversalRegions<'tcx>, location_table: &'a LocationTable, all_facts: &'a mut Option, borrow_set: &'a BorrowSet<'tcx>, - constraints: &'a mut MirTypeckRegionConstraints<'tcx>, + pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>, upvars: &'a [Upvar<'tcx>], } @@ -1157,6 +1157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category) } + #[instrument(skip(self, category), level = "debug")] fn eq_types( &mut self, expected: Ty<'tcx>, diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 64bd586662d38..f3a2382ef32d9 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -316,7 +316,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { extended_asm.add_input_operand(None, "r", result.llval); extended_asm.add_clobber("memory"); extended_asm.set_volatile_flag(true); - + // We have copied the value to `result` already. return; } @@ -363,10 +363,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { cond } - fn sideeffect(&mut self) { - // TODO(antoyo) - } - fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Value) -> Self::Value { // Unsupported. self.context.new_rvalue_from_int(self.int_type, 0) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1dba264a9614a..613a8df891ce4 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -597,7 +597,6 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); - ifn!("llvm.sideeffect", fn() -> void); ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 924bb803b368f..a7e34b080594b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -392,15 +392,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)]) } - fn sideeffect(&mut self) { - // This kind of check would make a ton of sense in the caller, but currently the only - // caller of this function is in `rustc_codegen_ssa`, which is agnostic to whether LLVM - // codegen backend being used, and so is unable to check the LLVM version. - if unsafe { llvm::LLVMRustVersionMajor() } < 12 { - self.call_intrinsic("llvm.sideeffect", &[]); - } - } - fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value { // Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time // optimization pass replaces calls to this intrinsic with code to test type membership. diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1ba0c4fa05b5b..638b2a7b5a9f2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1034,8 +1034,10 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( SplitDebuginfo::Packed => link_dwarf_object(sess, &out_filename), } + let strip = strip_value(sess); + if sess.target.is_like_osx { - match sess.opts.debugging_opts.strip { + match strip { Strip::Debuginfo => strip_symbols_in_osx(sess, &out_filename, Some("-S")), Strip::Symbols => strip_symbols_in_osx(sess, &out_filename, None), Strip::None => {} @@ -1043,6 +1045,14 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( } } +// Temporarily support both -Z strip and -C strip +fn strip_value(sess: &Session) -> Strip { + match (sess.opts.debugging_opts.strip, sess.opts.cg.strip) { + (s, Strip::None) => s, + (_, s) => s, + } +} + fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: Option<&str>) { let mut cmd = Command::new("strip"); if let Some(option) = option { @@ -2014,7 +2024,7 @@ fn add_order_independent_options( cmd.optimize(); // Pass debuginfo and strip flags down to the linker. - cmd.debuginfo(sess.opts.debugging_opts.strip); + cmd.debuginfo(strip_value(sess)); // We want to prevent the compiler from accidentally leaking in any system libraries, // so by default we tell linkers not to link to any default libraries. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a9471f7b77160..c8f388bfa1d5a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -980,17 +980,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - if bb == target { - // This is an unconditional branch back to this same basic block. That means we - // have something like a `loop {}` statement. LLVM versions before 12.0 - // miscompile this because they assume forward progress. For older versions - // try to handle just this specific case which comes up commonly in practice - // (e.g., in embedded code). - // - // NB: the `sideeffect` currently checks for the LLVM version used internally. - bx.sideeffect(); - } - helper.funclet_br(self, &mut bx, target); } diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index 78bf22ef9f2e2..02be6cd360c72 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -20,10 +20,6 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn abort(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; - /// Emits a forced side effect. - /// - /// Currently has any effect only when LLVM versions prior to 12.0 are used as the backend. - fn sideeffect(&mut self); /// Trait method used to test whether a given pointer is associated with a type identifier. fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value; /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index b8b6ff93753f0..4aa3c83cc0243 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1057,20 +1057,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(dest_ptr) => dest_ptr, }; + // This checks relocation edges on the src, which needs to happen before + // `prepare_relocation_copy`. + let src_bytes = src_alloc + .get_bytes_with_uninit_and_ptr(&tcx, src_range) + .map_err(|e| e.to_interp_error(src_alloc_id))? + .as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation // first copy the relocations to a temporary buffer, because // `get_bytes_mut` will clear the relocations, which is correct, // since we don't want to keep any relocations at the target. - // (`get_bytes_with_uninit_and_ptr` below checks that there are no - // relocations overlapping the edges; those would not be handled correctly). let relocations = src_alloc.prepare_relocation_copy(self, src_range, dest_offset, num_copies); // Prepare a copy of the initialization mask. let compressed = src_alloc.compress_uninit_range(src_range); - // This checks relocation edges on the src. - let src_bytes = src_alloc - .get_bytes_with_uninit_and_ptr(&tcx, src_range) - .map_err(|e| e.to_interp_error(src_alloc_id))? - .as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation // Destination alloc preparations and access hooks. let (dest_alloc, extra) = self.get_raw_mut(dest_alloc_id)?; diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c839f824d1c9c..92f74af4eb3eb 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -5,6 +5,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; use rustc_span::symbol::Ident; +use rustc_span::Span; pub fn anonymize_predicate<'tcx>( tcx: TyCtxt<'tcx>, @@ -97,6 +98,22 @@ pub fn elaborate_predicates<'tcx>( elaborate_obligations(tcx, obligations) } +pub fn elaborate_predicates_with_span<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: impl Iterator, Span)>, +) -> Elaborator<'tcx> { + let obligations = predicates + .map(|(predicate, span)| { + predicate_obligation( + predicate, + ty::ParamEnv::empty(), + ObligationCause::dummy_with_span(span), + ) + }) + .collect(); + elaborate_obligations(tcx, obligations) +} + pub fn elaborate_obligations<'tcx>( tcx: TyCtxt<'tcx>, mut obligations: Vec>, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index eed2e07e890e7..6b666d7c29222 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -551,6 +551,7 @@ fn test_codegen_options_tracking_hash() { untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")])); untracked!(rpath, true); untracked!(save_temps, true); + untracked!(strip, Strip::Debuginfo); macro_rules! tracked { ($name: ident, $non_default_value: expr) => { @@ -684,7 +685,6 @@ fn test_debugging_options_tracking_hash() { untracked!(self_profile_events, Some(vec![String::new()])); untracked!(span_debug, true); untracked!(span_free_formats, true); - untracked!(strip, Strip::Debuginfo); untracked!(temps_dir, Some(String::from("abc"))); untracked!(terminal_width, Some(80)); untracked!(threads, 99); diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e57075ed33811..59601e1484956 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2067,7 +2067,9 @@ impl<'tcx> TyS<'tcx> { ) -> Option> { match self.kind() { TyKind::Adt(adt, _) if adt.variants.is_empty() => { - bug!("discriminant_for_variant called on zero variant enum"); + // This can actually happen during CTFE, see + // https://github.com/rust-lang/rust/issues/89765. + None } TyKind::Adt(adt, _) if adt.is_enum() => { Some(adt.discriminant_for_variant(tcx, variant_index)) diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 569f186a72766..7f68112a427ba 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -82,6 +82,33 @@ pub(crate) fn emit_unescape_error( Applicability::MachineApplicable, ); } + } else { + let printable: Vec = lit + .chars() + .filter(|&x| { + unicode_width::UnicodeWidthChar::width(x).unwrap_or(0) != 0 + && !x.is_whitespace() + }) + .collect(); + + if let [ch] = printable.as_slice() { + has_help = true; + + handler.span_note( + span, + &format!( + "there are non-printing characters, the full sequence is `{}`", + lit.escape_default(), + ), + ); + + handler.span_suggestion( + span, + "consider removing the non-printing characters", + ch.to_string(), + Applicability::MaybeIncorrect, + ); + } } if !has_help { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 129a9fdab8234..a095cc73629db 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -112,6 +112,7 @@ impl CheckAttrVisitor<'tcx> { self.check_default_method_body_is_const(attr, span, target) } sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), + sym::must_use => self.check_must_use(hir_id, &attr, span, target), sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -1046,6 +1047,37 @@ impl CheckAttrVisitor<'tcx> { is_valid } + /// Warns against some misuses of `#[must_use]` + fn check_must_use( + &self, + hir_id: HirId, + attr: &Attribute, + span: &Span, + _target: Target, + ) -> bool { + let node = self.tcx.hir().get(hir_id); + if let Some(fn_node) = node.fn_kind() { + if let rustc_hir::IsAsync::Async = fn_node.asyncness() { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build( + "`must_use` attribute on `async` functions \ + applies to the anonymous `Future` returned by the \ + function, not the value within.", + ) + .span_label( + *span, + "this attribute does nothing, the `Future`s \ + returned by async functions are already `must_use`", + ) + .emit(); + }); + } + } + + // For now, its always valid + true + } + /// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid. fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool { match target { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3afe094733928..5e6bbe0391881 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -37,7 +37,7 @@ use std::iter::{self, FromIterator}; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; -/// The different settings that the `-Z strip` flag can have. +/// The different settings that the `-C strip` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Strip { /// Do not strip at all. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d1d8606a75a45..3f279a045f159 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -219,7 +219,7 @@ top_level_options!( /// generated code to parse an option into its respective field in the struct. There are a few /// hand-written parsers for parsing specific types of values in this module. macro_rules! options { - ($struct_name:ident, $stat:ident, $prefix:expr, $outputname:expr, + ($struct_name:ident, $stat:ident, $optmod:ident, $prefix:expr, $outputname:expr, $($( #[$attr:meta] )* $opt:ident : $t:ty = ( $init:expr, $parse:ident, @@ -264,13 +264,15 @@ macro_rules! options { } pub const $stat: OptionDescrs<$struct_name> = - &[ $( (stringify!($opt), $opt, desc::$parse, $desc) ),* ]; + &[ $( (stringify!($opt), $optmod::$opt, desc::$parse, $desc) ),* ]; + mod $optmod { $( - fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { - parse::$parse(&mut redirect_field!(cg.$opt), v) + pub(super) fn $opt(cg: &mut super::$struct_name, v: Option<&str>) -> bool { + super::parse::$parse(&mut redirect_field!(cg.$opt), v) } )* + } ) } @@ -918,7 +920,7 @@ mod parse { } options! { - CodegenOptions, CG_OPTIONS, "C", "codegen", + CodegenOptions, CG_OPTIONS, cgopts, "C", "codegen", // This list is in alphabetical order. // @@ -1013,6 +1015,8 @@ options! { "use soft float ABI (*eabihf targets only) (default: no)"), split_debuginfo: Option = (None, parse_split_debuginfo, [TRACKED], "how to handle split-debuginfo, a platform-specific option"), + strip: Strip = (Strip::None, parse_strip, [UNTRACKED], + "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], @@ -1027,7 +1031,7 @@ options! { } options! { - DebuggingOptions, DB_OPTIONS, "Z", "debugging", + DebuggingOptions, DB_OPTIONS, dbopts, "Z", "debugging", // This list is in alphabetical order. // diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index aaf81648c51b3..0f01a78c8c592 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_gnu_base::opts(); + let mut base = super::linux_base::opts(); base.os = "android".to_string(); // Many of the symbols defined in compiler-rt are also defined in libgcc. // Android's linker doesn't like that by default. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7d9568e0ca352..63877177fd18f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -706,36 +706,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } let param_env = obligation.param_env; - let trait_ref = poly_trait_ref.skip_binder(); - - let found_ty = trait_ref.self_ty(); - let found_ty_str = found_ty.to_string(); - let imm_borrowed_found_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, found_ty); - let imm_substs = self.tcx.mk_substs_trait(imm_borrowed_found_ty, &[]); - let mut_borrowed_found_ty = self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, found_ty); - let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]); // Try to apply the original trait binding obligation by borrowing. - let mut try_borrowing = |new_imm_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - new_mut_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + let mut try_borrowing = |old_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, blacklist: &[DefId]| -> bool { - if blacklist.contains(&expected_trait_ref.def_id()) { + if blacklist.contains(&old_ref.def_id()) { return false; } - let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new( - ObligationCause::dummy(), - param_env, - new_imm_trait_ref.without_const().to_predicate(self.tcx), - )); - - let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new( - ObligationCause::dummy(), - param_env, - new_mut_trait_ref.without_const().to_predicate(self.tcx), - )); + let orig_ty = old_ref.self_ty().skip_binder(); + let mk_result = |new_ty| { + let new_ref = old_ref.rebind(ty::TraitRef::new( + old_ref.def_id(), + self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]), + )); + self.predicate_must_hold_modulo_regions(&Obligation::new( + ObligationCause::dummy(), + param_env, + new_ref.without_const().to_predicate(self.tcx), + )) + }; + let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty)); + let mut_result = mk_result(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, orig_ty)); if imm_result || mut_result { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { @@ -747,8 +740,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let msg = format!( "the trait bound `{}: {}` is not satisfied", - found_ty_str, - expected_trait_ref.print_only_trait_path(), + orig_ty.to_string(), + old_ref.print_only_trait_path(), ); if has_custom_message { err.note(&msg); @@ -764,7 +757,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, &format!( "expected an implementor of trait `{}`", - expected_trait_ref.print_only_trait_path(), + old_ref.print_only_trait_path(), ), ); @@ -807,21 +800,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code { - let expected_trait_ref = obligation.parent_trait_ref; - let new_imm_trait_ref = poly_trait_ref - .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs)); - let new_mut_trait_ref = poly_trait_ref - .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs)); - return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]); + try_borrowing(obligation.parent_trait_ref, &[]) } else if let ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ItemObligation(_) = &*code { - return try_borrowing( - poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, imm_substs)), - poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, mut_substs)), - *poly_trait_ref, - &never_suggest_borrow[..], - ); + try_borrowing(*poly_trait_ref, &never_suggest_borrow[..]) } else { false } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d4a586b0124a2..91671994c5ace 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -65,7 +65,8 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError} pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_match::NonStructuralMatchTy; pub use self::util::{ - elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs, + elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span, + elaborate_trait_ref, elaborate_trait_refs, }; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index c1adc2894ccfc..0050ac99cb19a 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1641,19 +1641,38 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) { /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that /// aren't true. -fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { +fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirId) { let empty_env = ty::ParamEnv::empty(); let def_id = fcx.tcx.hir().local_def_id(id); - let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p); + let predicates_with_span = + fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, span)| (*p, *span)); // Check elaborated bounds. - let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); + let implied_obligations = traits::elaborate_predicates_with_span(fcx.tcx, predicates_with_span); for obligation in implied_obligations { let pred = obligation.predicate; // Match the existing behavior. if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() { let pred = fcx.normalize_associated_types_in(span, pred); + let hir_node = fcx.tcx.hir().find(id); + + // only use the span of the predicate clause (#90869) + + if let Some(hir::Generics { where_clause, .. }) = + hir_node.and_then(|node| node.generics()) + { + let obligation_span = obligation.cause.span(fcx.tcx); + + span = where_clause + .predicates + .iter() + // There seems to be no better way to find out which predicate we are in + .find(|pred| pred.span().contains(obligation_span)) + .map(|pred| pred.span()) + .unwrap_or(obligation_span); + } + let obligation = traits::Obligation::new( traits::ObligationCause::new(span, id, traits::TrivialBound), empty_env, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 584b90d613f6b..e4a566f589582 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -402,11 +402,13 @@ pub mod arch { #[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] #[allow(rustdoc::bare_urls)] #[unstable(feature = "portable_simd", issue = "86656")] +#[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics #[cfg(not(bootstrap))] mod core_simd; #[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] #[unstable(feature = "portable_simd", issue = "86656")] +#[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics #[cfg(not(bootstrap))] pub mod simd { #[unstable(feature = "portable_simd", issue = "86656")] diff --git a/library/core/tests/simd.rs b/library/core/tests/simd.rs index 8c11d788c67ae..50c92968c9d82 100644 --- a/library/core/tests/simd.rs +++ b/library/core/tests/simd.rs @@ -1,3 +1,5 @@ +#![cfg(not(miri))] // Miri does not support all SIMD intrinsics + use core::simd::f32x4; #[test] diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 628de13156c67..1417d860c47f5 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -833,20 +833,11 @@ fn symlink_noexist() { fn read_link() { if cfg!(windows) { // directory symlink - assert_eq!( - check!(fs::read_link(r"C:\Users\All Users")).to_str().unwrap(), - r"C:\ProgramData" - ); + assert_eq!(check!(fs::read_link(r"C:\Users\All Users")), Path::new(r"C:\ProgramData")); // junction - assert_eq!( - check!(fs::read_link(r"C:\Users\Default User")).to_str().unwrap(), - r"C:\Users\Default" - ); + assert_eq!(check!(fs::read_link(r"C:\Users\Default User")), Path::new(r"C:\Users\Default")); // junction with special permissions - assert_eq!( - check!(fs::read_link(r"C:\Documents and Settings\")).to_str().unwrap(), - r"C:\Users" - ); + assert_eq!(check!(fs::read_link(r"C:\Documents and Settings\")), Path::new(r"C:\Users")); } let tmpdir = tmpdir(); let link = tmpdir.join("link"); diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 4f8c4c66f8891..0201b88417a8b 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -525,6 +525,22 @@ platforms. Possible values are: Note that `packed` and `unpacked` are gated behind `-Z unstable-options` on non-macOS platforms at this time. +## strip + +The option `-C strip=val` controls stripping of debuginfo and similar auxiliary +data from binaries during linking. + +Supported values for this option are: + +- `none` - debuginfo and symbols (if they exist) are copied to the produced + binary or separate files depending on the target (e.g. `.pdb` files in case + of MSVC). +- `debuginfo` - debuginfo sections and debuginfo symbols from the symbol table + section are stripped at link time and are not copied to the produced binary + or separate files. +- `symbols` - same as `debuginfo`, but the rest of the symbol table section is + stripped as well if the linker supports it. + ## target-cpu This instructs `rustc` to generate code specifically for a particular processor. diff --git a/src/doc/unstable-book/src/compiler-flags/strip.md b/src/doc/unstable-book/src/compiler-flags/strip.md deleted file mode 100644 index 52cb98113c0c1..0000000000000 --- a/src/doc/unstable-book/src/compiler-flags/strip.md +++ /dev/null @@ -1,17 +0,0 @@ -# `strip` - -The tracking issue for this feature is: [#72110](https://github.com/rust-lang/rust/issues/72110). - ------------------------- - -Option `-Z strip=val` controls stripping of debuginfo and similar auxiliary data from binaries -during linking. - -Supported values for this option are: - -- `none` - debuginfo and symbols (if they exist) are copied to the produced binary or separate files -depending on the target (e.g. `.pdb` files in case of MSVC). -- `debuginfo` - debuginfo sections and debuginfo symbols from the symbol table section -are stripped at link time and are not copied to the produced binary or separate files. -- `symbols` - same as `debuginfo`, but the rest of the symbol table section is stripped as well -if the linker supports it. diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index c1a04e2014749..18bb6f6bc1edc 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -9,11 +9,10 @@ trait Bar {} impl Bar for [u16; 4] {} impl Bar for [[u16; 3]; 3] {} -trait Foo //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] - //~^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] - where - [::Quaks; 2]: Bar, - ::Quaks: Bar, +trait Foo +where + [::Quaks; 2]: Bar, //~ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + ::Quaks: Bar, //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] { } diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 7167bea94bbb6..89aa3d395e25b 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -1,14 +1,8 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:12:1 + --> $DIR/issue-67185-2.rs:15:5 | -LL | / trait Foo -LL | | -LL | | where -LL | | [::Quaks; 2]: Bar, -LL | | ::Quaks: Bar, -LL | | { -LL | | } - | |_^ the trait `Bar` is not implemented for `[u16; 3]` +LL | ::Quaks: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> @@ -17,16 +11,10 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:12:1 + --> $DIR/issue-67185-2.rs:14:5 | -LL | / trait Foo -LL | | -LL | | where -LL | | [::Quaks; 2]: Bar, -LL | | ::Quaks: Bar, -LL | | { -LL | | } - | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` +LL | [::Quaks; 2]: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> @@ -35,7 +23,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:22:6 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` @@ -44,16 +32,16 @@ LL | impl Foo for FooImpl {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:16:29 + --> $DIR/issue-67185-2.rs:15:25 | LL | trait Foo | --- required by a bound in this ... -LL | ::Quaks: Bar, - | ^^^ required by this bound in `Foo` +LL | ::Quaks: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:22:6 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` @@ -62,16 +50,16 @@ LL | impl Foo for FooImpl {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:15:34 + --> $DIR/issue-67185-2.rs:14:30 | LL | trait Foo | --- required by a bound in this -... -LL | [::Quaks; 2]: Bar, - | ^^^ required by this bound in `Foo` +LL | where +LL | [::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:26:14 + --> $DIR/issue-67185-2.rs:25:14 | LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` @@ -80,16 +68,16 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:15:34 + --> $DIR/issue-67185-2.rs:14:30 | LL | trait Foo | --- required by a bound in this -... -LL | [::Quaks; 2]: Bar, - | ^^^ required by this bound in `Foo` +LL | where +LL | [::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:26:14 + --> $DIR/issue-67185-2.rs:25:14 | LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` @@ -98,13 +86,13 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:16:29 + --> $DIR/issue-67185-2.rs:15:25 | LL | trait Foo | --- required by a bound in this ... -LL | ::Quaks: Bar, - | ^^^ required by this bound in `Foo` +LL | ::Quaks: Bar, + | ^^^ required by this bound in `Foo` error: aborting due to 6 previous errors diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index a47f6af02965b..f623c5101f4cd 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -25,6 +25,13 @@ enum SingleVariant { const TEST_V: Discriminant = discriminant(&SingleVariant::V); +pub const TEST_VOID: () = { + // This is UB, but CTFE does not check validity so it does not detect this. + // This is a regression test for https://github.com/rust-lang/rust/issues/89765. + unsafe { std::mem::discriminant(&*(&() as *const () as *const Void)); }; +}; + + fn main() { assert_eq!(TEST_A, TEST_A_OTHER); assert_eq!(TEST_A, discriminant(black_box(&Test::A(17)))); diff --git a/src/test/ui/consts/issue-miri-1910.rs b/src/test/ui/consts/issue-miri-1910.rs new file mode 100644 index 0000000000000..20efa145dbe1e --- /dev/null +++ b/src/test/ui/consts/issue-miri-1910.rs @@ -0,0 +1,12 @@ +// error-pattern unable to turn pointer into raw bytes +#![feature(const_ptr_read)] +#![feature(const_ptr_offset)] + +const C: () = unsafe { + let foo = Some(&42 as *const i32); + let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3; + (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); +}; + +fn main() { +} diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr new file mode 100644 index 0000000000000..e2f4ef635887c --- /dev/null +++ b/src/test/ui/consts/issue-miri-1910.stderr @@ -0,0 +1,26 @@ +error: any use of this value will cause an error + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | +LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn pointer into raw bytes + | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | inside `ptr::const_ptr::::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | inside `C` at $DIR/issue-miri-1910.rs:8:5 + | + ::: $DIR/issue-miri-1910.rs:5:1 + | +LL | / const C: () = unsafe { +LL | | let foo = Some(&42 as *const i32); +LL | | let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3; +LL | | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); +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/cross/cross-fn-cache-hole.rs b/src/test/ui/cross/cross-fn-cache-hole.rs index 249c6474c9420..c38a5001ac86d 100644 --- a/src/test/ui/cross/cross-fn-cache-hole.rs +++ b/src/test/ui/cross/cross-fn-cache-hole.rs @@ -12,8 +12,8 @@ trait Bar { } // We don't always check where clauses for sanity, but in this case // wfcheck does report an error here: -fn vacuous() //~ ERROR the trait bound `i32: Bar` is not satisfied - where i32: Foo +fn vacuous() + where i32: Foo //~ ERROR the trait bound `i32: Bar` is not satisfied { // ... the original intention was to check that we don't use that // vacuous where clause (which could never be satisfied) to accept diff --git a/src/test/ui/cross/cross-fn-cache-hole.stderr b/src/test/ui/cross/cross-fn-cache-hole.stderr index 0d325bb7ec102..7e15562b0816b 100644 --- a/src/test/ui/cross/cross-fn-cache-hole.stderr +++ b/src/test/ui/cross/cross-fn-cache-hole.stderr @@ -1,14 +1,8 @@ error[E0277]: the trait bound `i32: Bar` is not satisfied - --> $DIR/cross-fn-cache-hole.rs:15:1 + --> $DIR/cross-fn-cache-hole.rs:16:11 | -LL | / fn vacuous() -LL | | where i32: Foo -LL | | { -LL | | // ... the original intention was to check that we don't use that -... | -LL | | require::(); -LL | | } - | |_^ the trait `Bar` is not implemented for `i32` +LL | where i32: Foo + | ^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr index 1d0554ad0477f..13097edf0adf9 100644 --- a/src/test/ui/derives/deriving-copyclone.stderr +++ b/src/test/ui/derives/deriving-copyclone.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `C: Copy` is not satisfied +error[E0277]: the trait bound `B: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:31:13 | LL | is_copy(B { a: 1, b: C }); @@ -22,7 +22,7 @@ help: consider borrowing here LL | is_copy(&B { a: 1, b: C }); | + -error[E0277]: the trait bound `C: Clone` is not satisfied +error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/deriving-copyclone.rs:32:14 | LL | is_clone(B { a: 1, b: C }); @@ -46,7 +46,7 @@ help: consider borrowing here LL | is_clone(&B { a: 1, b: C }); | + -error[E0277]: the trait bound `D: Copy` is not satisfied +error[E0277]: the trait bound `B: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:35:13 | LL | is_copy(B { a: 1, b: D }); diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr index 78904b383f49a..28c49c33bf6b5 100644 --- a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -1,87 +1,71 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:10:1 + --> $DIR/feature-gate-trivial_bounds.rs:10:14 | LL | enum E where i32: Foo { V } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:12:1 + --> $DIR/feature-gate-trivial_bounds.rs:12:16 | LL | struct S where i32: Foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:14:1 + --> $DIR/feature-gate-trivial_bounds.rs:14:15 | LL | trait T where i32: Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:16:1 + --> $DIR/feature-gate-trivial_bounds.rs:16:15 | LL | union U where i32: Foo { f: i32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:20:1 + --> $DIR/feature-gate-trivial_bounds.rs:20:23 | -LL | / impl Foo for () where i32: Foo { -LL | | fn test(&self) { -LL | | 3i32.test(); -LL | | Foo::test(&4i32); -LL | | generic_function(5i32); -LL | | } -LL | | } - | |_^ the trait `Foo` is not implemented for `i32` +LL | impl Foo for () where i32: Foo { + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:28:1 + --> $DIR/feature-gate-trivial_bounds.rs:28:14 | -LL | / fn f() where i32: Foo -LL | | { -LL | | let s = S; -LL | | 3i32.test(); -LL | | Foo::test(&4i32); -LL | | generic_function(5i32); -LL | | } - | |_^ the trait `Foo` is not implemented for `i32` +LL | fn f() where i32: Foo + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `String: Neg` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:36:1 + --> $DIR/feature-gate-trivial_bounds.rs:36:38 | -LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg { -LL | | -s -LL | | } - | |_^ the trait `Neg` is not implemented for `String` +LL | fn use_op(s: String) -> String where String: ::std::ops::Neg { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Neg` is not implemented for `String` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: `i32` is not an iterator - --> $DIR/feature-gate-trivial_bounds.rs:40:1 + --> $DIR/feature-gate-trivial_bounds.rs:40:20 | -LL | / fn use_for() where i32: Iterator { -LL | | for _ in 2i32 {} -LL | | } - | |_^ `i32` is not an iterator +LL | fn use_for() where i32: Iterator { + | ^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` @@ -89,22 +73,20 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:52:1 + --> $DIR/feature-gate-trivial_bounds.rs:52:32 | LL | struct TwoStrs(str, str) where str: Sized; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:55:1 + --> $DIR/feature-gate-trivial_bounds.rs:55:26 | -LL | / fn unsized_local() where Dst: Sized { -LL | | let x: Dst = *(Box::new(Dst { x: 1 }) as Box>); -LL | | } - | |_^ doesn't have a size known at compile-time +LL | fn unsized_local() where Dst: Sized { + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)` note: required because it appears within the type `Dst<(dyn A + 'static)>` @@ -116,12 +98,10 @@ LL | struct Dst { = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:59:1 + --> $DIR/feature-gate-trivial_bounds.rs:59:30 | -LL | / fn return_str() -> str where str: Sized { -LL | | *"Sized".to_string().into_boxed_str() -LL | | } - | |_^ doesn't have a size known at compile-time +LL | fn return_str() -> str where str: Sized { + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` = help: see issue #48214 diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs new file mode 100644 index 0000000000000..e150ecfe9a0dc --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs @@ -0,0 +1,43 @@ +// check-pass + +#![feature(generic_associated_types)] + +use std::marker::PhantomData; + +trait Family: Sized { + type Item<'a>; + + fn apply_all(&self, f: F) + where + F: FamilyItemFn { } +} + +struct Array(PhantomData); + +impl Family for Array { + type Item<'a> = &'a T; +} + +trait FamilyItemFn { + fn apply(&self, item: T::Item<'_>); +} + +impl FamilyItemFn for F +where + T: Family, + for<'a> F: Fn(T::Item<'a>) +{ + fn apply(&self, item: T::Item<'_>) { + (*self)(item); + } +} + +fn process(array: Array) { + // Works + array.apply_all(|x: &T| { }); + + // ICE: NoSolution + array.apply_all(|x: as Family>::Item<'_>| { }); +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs new file mode 100644 index 0000000000000..18b7f383482a1 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs @@ -0,0 +1,37 @@ +//check-pass + +#![feature(generic_associated_types)] + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + +trait IsCovariant<'a> {} + +struct Yoke Yokeable<'a>> { + data: Y, +} + +impl Yokeable<'a>> Yoke { + fn project Yokeable<'a>>(&self, _f: for<'a> fn(>::Output, &'a ()) + -> >::Output) -> Yoke { + + unimplemented!() + } +} + +fn _upcast(x: Yoke) -> Yoke + 'static>> where + Y: for<'a> Yokeable<'a>, + for<'a> >::Output: IsCovariant<'a> + { + x.project(|data, _| { + Box::new(data) + }) +} + + +impl<'a> Yokeable<'a> for Box + 'static> { + type Output = Box + 'a>; +} + +fn main() {} diff --git a/src/test/ui/lint/unused/unused-async.rs b/src/test/ui/lint/unused/unused-async.rs new file mode 100644 index 0000000000000..7d17af1157379 --- /dev/null +++ b/src/test/ui/lint/unused/unused-async.rs @@ -0,0 +1,43 @@ +// edition:2018 +// run-pass +#![allow(dead_code)] + +#[must_use] +//~^ WARNING `must_use` +async fn test() -> i32 { + 1 +} + + +struct Wowee {} + +impl Wowee { + #[must_use] + //~^ WARNING `must_use` + async fn test_method() -> i32 { + 1 + } +} + +/* FIXME(guswynn) update this test when async-fn-in-traits works +trait Doer { + #[must_use] + async fn test_trait_method() -> i32; + WARNING must_use + async fn test_other_trait() -> i32; +} + +impl Doer for Wowee { + async fn test_trait_method() -> i32 { + 1 + } + #[must_use] + async fn test_other_trait() -> i32 { + WARNING must_use + 1 + } +} +*/ + +fn main() { +} diff --git a/src/test/ui/lint/unused/unused-async.stderr b/src/test/ui/lint/unused/unused-async.stderr new file mode 100644 index 0000000000000..e470b6dac9473 --- /dev/null +++ b/src/test/ui/lint/unused/unused-async.stderr @@ -0,0 +1,26 @@ +warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within. + --> $DIR/unused-async.rs:5:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ +LL | +LL | / async fn test() -> i32 { +LL | | 1 +LL | | } + | |_- this attribute does nothing, the `Future`s returned by async functions are already `must_use` + | + = note: `#[warn(unused_attributes)]` on by default + +warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within. + --> $DIR/unused-async.rs:15:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ +LL | +LL | / async fn test_method() -> i32 { +LL | | 1 +LL | | } + | |_____- this attribute does nothing, the `Future`s returned by async functions are already `must_use` + +warning: 2 warnings emitted + diff --git a/src/test/ui/parser/char/whitespace-character-literal.rs b/src/test/ui/parser/char/whitespace-character-literal.rs new file mode 100644 index 0000000000000..de5e09204b462 --- /dev/null +++ b/src/test/ui/parser/char/whitespace-character-literal.rs @@ -0,0 +1,10 @@ +// This tests that the error generated when a character literal has multiple +// characters in it contains a note about non-printing characters. + +fn main() { + let _hair_space_around = ' x​'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + //~| HELP: consider removing the non-printing characters + //~| SUGGESTION: x +} diff --git a/src/test/ui/parser/char/whitespace-character-literal.stderr b/src/test/ui/parser/char/whitespace-character-literal.stderr new file mode 100644 index 0000000000000..d73de41a8099b --- /dev/null +++ b/src/test/ui/parser/char/whitespace-character-literal.stderr @@ -0,0 +1,16 @@ +error: character literal may only contain one codepoint + --> $DIR/whitespace-character-literal.rs:5:30 + | +LL | let _hair_space_around = ' x​'; + | ^--^ + | | + | help: consider removing the non-printing characters: `x` + | +note: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + --> $DIR/whitespace-character-literal.rs:5:31 + | +LL | let _hair_space_around = ' x​'; + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr index 1cf73fcdebd0b..1ab130e0ab143 100644 --- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -65,7 +65,7 @@ LL | is_send(Box::new(TestType)); | | | required by a bound introduced by this call | - = note: the trait bound `dummy2::TestType: Send` is not satisfied + = note: the trait bound `Unique: Send` is not satisfied = note: required because of the requirements on the impl of `Send` for `Unique` = note: required because it appears within the type `Box` note: required by a bound in `is_send` @@ -104,11 +104,11 @@ error[E0277]: `main::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:66:13 | LL | is_sync(Outer2(TestType)); - | ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Sync` + | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely | | | required by a bound introduced by this call | - = note: the trait bound `main::TestType: Sync` is not satisfied + = help: the trait `Send` is not implemented for `main::TestType` note: required because of the requirements on the impl of `Sync` for `Outer2` --> $DIR/negated-auto-traits-error.rs:14:22 | @@ -119,12 +119,6 @@ note: required by a bound in `is_sync` | LL | fn is_sync(_: T) {} | ^^^^ required by this bound in `is_sync` -help: consider borrowing here - | -LL | is_sync(&Outer2(TestType)); - | + -LL | is_sync(&mut Outer2(TestType)); - | ++++ error: aborting due to 7 previous errors diff --git a/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs new file mode 100644 index 0000000000000..f891a42fc2af0 --- /dev/null +++ b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs @@ -0,0 +1,11 @@ +// Do not suggest referencing the parameter to `check` + +trait Marker {} + +impl Marker for T {} + +pub fn check>(_: T) {} + +pub fn main() { + check::<()>(()); //~ ERROR [E0277] +} diff --git a/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr new file mode 100644 index 0000000000000..08eab0253701e --- /dev/null +++ b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `(): Marker` is not satisfied + --> $DIR/issue-90804-incorrect-reference-suggestion.rs:10:17 + | +LL | check::<()>(()); + | ----------- ^^ the trait `Marker` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/issue-90804-incorrect-reference-suggestion.rs:7:17 + | +LL | pub fn check>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 2c0f433fd2e83..73668334f05c3 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 2c0f433fd2e838ae181f87019b6f1fefe33c6f54 +Subproject commit 73668334f05c3446b04116ccc3156240d2d8ab19