diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0b1cb12408003..85b599902b959 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -760,10 +760,28 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::CoroutineKind::Coroutine(_)) | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) | None => { - return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks { - await_kw_span, - item_span: self.current_item, - })); + // Lower to a block `{ EXPR; }` so that the awaited expr + // is not accidentally orphaned. + let stmt_id = self.next_id(); + let expr_err = self.expr( + expr.span, + hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks { + await_kw_span, + item_span: self.current_item, + })), + ); + return hir::ExprKind::Block( + self.block_all( + expr.span, + arena_vec![self; hir::Stmt { + hir_id: stmt_id, + kind: hir::StmtKind::Semi(expr), + span: expr.span, + }], + Some(self.arena.alloc(expr_err)), + ), + None, + ); } }; @@ -1496,12 +1514,31 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> { + let yielded = + opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span)); + let is_async_gen = match self.coroutine_kind { Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false, Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true, Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => { - return hir::ExprKind::Err( - self.dcx().emit_err(AsyncCoroutinesNotSupported { span }), + // Lower to a block `{ EXPR; }` so that the awaited expr + // is not accidentally orphaned. + let stmt_id = self.next_id(); + let expr_err = self.expr( + yielded.span, + hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })), + ); + return hir::ExprKind::Block( + self.block_all( + yielded.span, + arena_vec![self; hir::Stmt { + hir_id: stmt_id, + kind: hir::StmtKind::Semi(yielded), + span: yielded.span, + }], + Some(self.arena.alloc(expr_err)), + ), + None, ); } Some(hir::CoroutineKind::Coroutine(_)) => { @@ -1531,9 +1568,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } }; - let yielded = - opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span)); - if is_async_gen { // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`. // This ensures that we store our resumed `ResumeContext` correctly, and also that diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 2805ca360ad3d..1bad62c4103a3 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -146,9 +146,6 @@ const_eval_intern_kind = {$kind -> *[other] {""} } -const_eval_invalid_align = - align has to be a power of 2 - const_eval_invalid_align_details = invalid align passed to `{$name}`: {$align} is {$err_kind -> [not_power_of_two] not a power of 2 diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index a88e130cd4b78..2cebea9d145bb 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -182,13 +182,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { use rustc_type_ir::TyKind::*; - let val = match src.layout.ty.kind() { - // Floating point - Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty), - Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty), - _ => { - bug!("Can't cast 'Float' type into {}", cast_to.ty); - } + let Float(fty) = src.layout.ty.kind() else { + bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty) + }; + let val = match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty), + FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty), + FloatTy::F128 => unimplemented!("f16_f128"), }; Ok(ImmTy::from_scalar(val, cast_to)) } @@ -275,6 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty); Ok(match *cast_ty.kind() { + // int -> int Int(_) | Uint(_) => { let size = match *cast_ty.kind() { Int(t) => Integer::from_int_ty(self, t).size(), @@ -285,15 +287,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Scalar::from_uint(v, size) } - Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value), - Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value), - Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value), - Float(FloatTy::F64) => Scalar::from_f64(Double::from_u128(v).value), - - Char => { - // `u8` to `char` cast - Scalar::from_u32(u8::try_from(v).unwrap().into()) + // signed int -> float + Float(fty) if signed => { + let v = v as i128; + match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value), + FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value), + FloatTy::F128 => unimplemented!("f16_f128"), + } } + // unsigned int -> float + Float(fty) => match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value), + FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value), + FloatTy::F128 => unimplemented!("f16_f128"), + }, + + // u8 -> char + Char => Scalar::from_u32(u8::try_from(v).unwrap().into()), // Casts to bool are not permitted by rustc, no need to handle them here. _ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty), @@ -339,14 +352,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let v = f.to_i128(size.bits_usize()).value; Scalar::from_int(v, size) } - // float -> f32 - Float(FloatTy::F32) => { - Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)) - } - // float -> f64 - Float(FloatTy::F64) => { - Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)) - } + // float -> float + Float(fty) => match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)), + FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)), + FloatTy::F128 => unimplemented!("f16_f128"), + }, // That's it. _ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty), } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b6e2695590c13..2cc37651ef521 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -791,7 +791,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { } fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option { - tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { + let adt = tcx.adt_def(def_id); + if adt.is_enum() { + return None; + } + + adt.non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { if field.is_unnamed() { let field_ty = tcx.type_of(field.did).instantiate_identity(); let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index 2de87cbe631ac..e44a6ae3b3f2e 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -181,14 +181,6 @@ infer_more_targeted = {$has_param_name -> infer_msl_introduces_static = introduces a `'static` lifetime requirement infer_msl_unmet_req = because this has an unmet lifetime requirement -infer_need_type_info_in_coroutine = - type inside {$coroutine_kind -> - [async_block] `async` block - [async_closure] `async` closure - [async_fn] `async fn` body - *[coroutine] coroutine - } must be known in this context - infer_nothing = {""} diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 63e2fe47659db..8bf9d0b9d4aac 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -562,8 +562,6 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type -lint_trivial_untranslatable_diag = diagnostic with static strings only - lint_ty_qualified = usage of qualified `ty::{$ty}` .suggestion = try importing it and using it unqualified diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index ad1808b5f803d..f3076092dec10 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -12,6 +12,43 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Symbol}; use rustc_span::BytePos; +const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35; + +fn check_cfg_expected_note( + sess: &Session, + possibilities: &[Symbol], + type_: &str, + name: Option, + suffix: &str, +) -> String { + use std::fmt::Write; + + let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected { + possibilities.len() + } else { + std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES) + }; + + let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::>(); + possibilities.sort(); + + let and_more = possibilities.len().saturating_sub(n_possibilities); + let possibilities = possibilities[..n_possibilities].join("`, `"); + + let mut note = String::with_capacity(50 + possibilities.len()); + + write!(&mut note, "expected {type_}").unwrap(); + if let Some(name) = name { + write!(&mut note, " for `{name}`").unwrap(); + } + write!(&mut note, " are: {suffix}`{possibilities}`").unwrap(); + if and_more > 0 { + write!(&mut note, " and {and_more} more").unwrap(); + } + + note +} + pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: &mut Diag<'_, ()>) { match diagnostic { BuiltinLintDiagnostics::UnicodeTextFlow(span, content) => { @@ -291,16 +328,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: } } if !possibilities.is_empty() { - let mut possibilities = - possibilities.iter().map(Symbol::as_str).collect::>(); - possibilities.sort(); - let possibilities = possibilities.join("`, `"); - - // The list of expected names can be long (even by default) and - // so the diagnostic produced can take a lot of space. To avoid - // cloging the user output we only want to print that diagnostic - // once. - diag.help_once(format!("expected names are: `{possibilities}`")); + diag.help_once(check_cfg_expected_note( + sess, + &possibilities, + "names", + None, + "", + )); } } @@ -343,16 +377,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: // Show the full list if all possible values for a given name, but don't do it // for names as the possibilities could be very long if !possibilities.is_empty() { - { - let mut possibilities = - possibilities.iter().map(Symbol::as_str).collect::>(); - possibilities.sort(); - - let possibilities = possibilities.join("`, `"); - let none = if have_none_possibility { "(none), " } else { "" }; - - diag.note(format!("expected values for `{name}` are: {none}`{possibilities}`")); - } + diag.note(check_cfg_expected_note( + sess, + &possibilities, + "values", + Some(name), + if have_none_possibility { "(none), " } else { "" }, + )); if let Some((value, value_span)) = value { // Suggest the most probable if we found one diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 8b48570fbbadd..0d37c0feb0c24 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1132,7 +1132,13 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result { // Only try to recover from this specific error. if !matches!(err, libloading::Error::LoadLibraryExW { .. }) { - return Err(err.to_string()); + let err = format_dlopen_err(&err); + // We include the path of the dylib in the error ourselves, so + // if it's in the error, we strip it. + if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) { + return Err(err.to_string()); + } + return Err(err); } last_error = Some(err); diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 60cc138fd7bc2..a100e2d47bbbb 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -392,9 +392,6 @@ parse_invalid_identifier_with_leading_number = identifiers cannot start with a n parse_invalid_interpolated_expression = invalid interpolated expression -parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid - .label = invalid suffix `{$suffix}` - parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid .label = invalid suffix `{$suffix}` .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases @@ -609,7 +606,6 @@ parse_nonterminal_expected_item_keyword = expected an item keyword parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}` parse_nonterminal_expected_statement = expected a statement -parse_not_supported = not supported parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index c223b8475288b..7fc523ffe0dea 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -302,9 +302,6 @@ passes_export_name = attribute should be applied to a free function, impl method or static .label = not a free function, impl method or static -passes_expr_not_allowed_in_context = - {$expr} is not allowed in a `{$context}` - passes_extern_main = the `main` function cannot be declared in an `extern` block @@ -405,8 +402,6 @@ passes_lang_item_on_incorrect_target = `{$name}` language item must be applied to a {$expected_target} .label = attribute should be applied to a {$expected_target}, not a {$actual_target} -passes_layout = - layout error: {$layout_error} passes_layout_abi = abi: {$abi} passes_layout_align = diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 0261768d91616..c518844cc5e52 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1001,19 +1001,26 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> { /// Only call if `ctor.is_covered_by(self.head().ctor())` is true. fn pop_head_constructor( &self, + cx: &Cx, ctor: &Constructor, ctor_arity: usize, ctor_is_relevant: bool, - ) -> PatStack<'p, Cx> { + ) -> Result, Cx::Error> { // We pop the head pattern and push the new fields extracted from the arguments of // `self.head()`. let mut new_pats = self.head().specialize(ctor, ctor_arity); + if new_pats.len() != ctor_arity { + return Err(cx.bug(format_args!( + "uncaught type error: pattern {:?} has inconsistent arity (expected arity {ctor_arity})", + self.head().as_pat().unwrap() + ))); + } new_pats.extend_from_slice(&self.pats[1..]); // `ctor` is relevant for this row if it is the actual constructor of this row, or if the // row has a wildcard and `ctor` is relevant for wildcards. let ctor_is_relevant = !matches!(self.head().ctor(), Constructor::Wildcard) || ctor_is_relevant; - PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant } + Ok(PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant }) } } @@ -1083,18 +1090,19 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> { /// Only call if `ctor.is_covered_by(self.head().ctor())` is true. fn pop_head_constructor( &self, + cx: &Cx, ctor: &Constructor, ctor_arity: usize, ctor_is_relevant: bool, parent_row: usize, - ) -> MatrixRow<'p, Cx> { - MatrixRow { - pats: self.pats.pop_head_constructor(ctor, ctor_arity, ctor_is_relevant), + ) -> Result, Cx::Error> { + Ok(MatrixRow { + pats: self.pats.pop_head_constructor(cx, ctor, ctor_arity, ctor_is_relevant)?, parent_row, is_under_guard: self.is_under_guard, useful: false, intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`. - } + }) } } @@ -1217,7 +1225,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { }; for (i, row) in self.rows().enumerate() { if ctor.is_covered_by(pcx.cx, row.head().ctor())? { - let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i); + let new_row = row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?; matrix.expand_and_push(new_row); } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 1b546bf9103d8..b06d75be3902d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -17,6 +17,7 @@ use rustc_middle::dep_graph::{ use rustc_middle::query::on_disk_cache::AbsoluteBytePos; use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex}; use rustc_middle::query::Key; +use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; @@ -304,6 +305,10 @@ pub(crate) fn create_query_frame< kind: DepKind, name: &'static str, ) -> QueryStackFrame { + // If reduced queries are requested, we may be printing a query stack due + // to a panic. Avoid using `default_span` and `def_kind` in that case. + let reduce_queries = with_reduced_queries(); + // Avoid calling queries while formatting the description let description = ty::print::with_no_queries!(do_describe(tcx, key)); let description = if tcx.sess.verbose_internals() { @@ -311,7 +316,7 @@ pub(crate) fn create_query_frame< } else { description }; - let span = if kind == dep_graph::dep_kinds::def_span { + let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. None @@ -319,7 +324,7 @@ pub(crate) fn create_query_frame< Some(key.default_span(tcx)) }; let def_id = key.key_as_def_id(); - let def_kind = if kind == dep_graph::dep_kinds::def_kind { + let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { // Try to avoid infinite recursion. None } else { diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 40517407ee6a1..3d9848395a20b 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -285,9 +285,8 @@ where let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock(); match lock.get(&key) { - Some(QueryResult::Poisoned) => { - panic!("query '{}' not cached due to poisoning", query.name()) - } + // The query we waited on panicked. Continue unwinding here. + Some(QueryResult::Poisoned) => FatalError.raise(), _ => panic!( "query '{}' result must be in the cache or the query must be poisoned after a wait", query.name() diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 42c9d5e10eba1..55e1556cdf8d6 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1565,6 +1565,8 @@ options! { "set options for branch target identification and pointer authentication on AArch64"), cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED], "instrument control-flow architecture protection"), + check_cfg_all_expected: bool = (false, parse_bool, [UNTRACKED], + "show all expected values in check-cfg diagnostics (default: no)"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 9c642b98b01a1..6f5439dc01c39 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -898,19 +898,6 @@ impl Session { } pub fn should_prefer_remapped_for_codegen(&self) -> bool { - // bail out, if any of the requested crate types aren't: - // "compiled executables or libraries" - for crate_type in &self.opts.crate_types { - match crate_type { - CrateType::Executable - | CrateType::Dylib - | CrateType::Rlib - | CrateType::Staticlib - | CrateType::Cdylib => continue, - CrateType::ProcMacro => return false, - } - } - let has_split_debuginfo = match self.split_debuginfo() { SplitDebuginfo::Off => false, SplitDebuginfo::Packed => true, diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 86c7551882aab..282595169737d 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -22,11 +22,20 @@ struct OpaqueTypeCollector<'tcx> { seen: FxHashSet, span: Option, + + mode: CollectionMode, +} + +enum CollectionMode { + /// For impl trait in assoc types we only permit collecting them from + /// associated types of the same impl block. + ImplTraitInAssocTypes, + TypeAliasImplTraitTransition, } impl<'tcx> OpaqueTypeCollector<'tcx> { - fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { - Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None } + fn new(tcx: TyCtxt<'tcx>, item: LocalDefId, mode: CollectionMode) -> Self { + Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode } } fn span(&self) -> Span { @@ -251,6 +260,9 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } } ty::Adt(def, _) if def.did().is_local() => { + if let CollectionMode::ImplTraitInAssocTypes = self.mode { + return ControlFlow::Continue(()); + } if !self.seen.insert(def.did().expect_local()) { return ControlFlow::Continue(()); } @@ -275,89 +287,13 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } } -struct ImplTraitInAssocTypeCollector<'tcx>(OpaqueTypeCollector<'tcx>); - -impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for ImplTraitInAssocTypeCollector<'tcx> { - #[instrument(skip(self), ret, level = "trace")] - fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow { - let old = self.0.span; - self.0.span = Some(span); - value.visit_with(self); - self.0.span = old; - - ControlFlow::Continue(()) - } -} - -impl<'tcx> TypeVisitor> for ImplTraitInAssocTypeCollector<'tcx> { - #[instrument(skip(self), ret, level = "trace")] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - t.super_visit_with(self)?; - match t.kind() { - ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { - self.0.visit_opaque_ty(alias_ty); - } - ty::Alias(ty::Projection, alias_ty) => { - // This avoids having to do normalization of `Self::AssocTy` by only - // supporting the case of a method defining opaque types from assoc types - // in the same impl block. - let parent_trait_ref = self - .0 - .parent_trait_ref() - .expect("impl trait in assoc type collector used on non-assoc item"); - // If the trait ref of the associated item and the impl differs, - // then we can't use the impl's identity args below, so - // just skip. - if alias_ty.trait_ref(self.0.tcx) == parent_trait_ref { - let parent = self.0.parent().expect("we should have a parent here"); - - for &assoc in self.0.tcx.associated_items(parent).in_definition_order() { - trace!(?assoc); - if assoc.trait_item_def_id != Some(alias_ty.def_id) { - continue; - } - - // If the type is further specializable, then the type_of - // is not actually correct below. - if !assoc.defaultness(self.0.tcx).is_final() { - continue; - } - - let impl_args = alias_ty.args.rebase_onto( - self.0.tcx, - parent_trait_ref.def_id, - ty::GenericArgs::identity_for_item(self.0.tcx, parent), - ); - - if check_args_compatible(self.0.tcx, assoc, impl_args) { - return self - .0 - .tcx - .type_of(assoc.def_id) - .instantiate(self.0.tcx, impl_args) - .visit_with(self); - } else { - self.0.tcx.dcx().span_bug( - self.0.tcx.def_span(assoc.def_id), - "item had incorrect args", - ); - } - } - } - } - _ => trace!(kind=?t.kind()), - } - ControlFlow::Continue(()) - } -} - fn impl_trait_in_assoc_types_defined_by<'tcx>( tcx: TyCtxt<'tcx>, item: LocalDefId, ) -> &'tcx ty::List { - let mut collector = ImplTraitInAssocTypeCollector(OpaqueTypeCollector::new(tcx, item)); + let mut collector = OpaqueTypeCollector::new(tcx, item, CollectionMode::ImplTraitInAssocTypes); super::sig_types::walk_types(tcx, item, &mut collector); - tcx.mk_local_def_ids(&collector.0.opaques) + tcx.mk_local_def_ids(&collector.opaques) } fn opaque_types_defined_by<'tcx>( @@ -366,7 +302,8 @@ fn opaque_types_defined_by<'tcx>( ) -> &'tcx ty::List { let kind = tcx.def_kind(item); trace!(?kind); - let mut collector = OpaqueTypeCollector::new(tcx, item); + let mut collector = + OpaqueTypeCollector::new(tcx, item, CollectionMode::TypeAliasImplTraitTransition); super::sig_types::walk_types(tcx, item, &mut collector); match kind { DefKind::AssocFn diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 084157b97ab41..facfc9d208e42 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -944,6 +944,21 @@ impl Rc { /// is in fact equivalent to [Rc::try_unwrap]\(this).[ok][Result::ok](). /// (Note that the same kind of equivalence does **not** hold true for /// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`!) + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new(3); + /// assert_eq!(Rc::into_inner(x), Some(3)); + /// + /// let x = Rc::new(4); + /// let y = Rc::clone(&x); + /// + /// assert_eq!(Rc::into_inner(y), None); + /// assert_eq!(Rc::into_inner(x), Some(4)); + /// ``` #[inline] #[stable(feature = "rc_into_inner", since = "1.70.0")] pub fn into_inner(this: Self) -> Option { @@ -1329,6 +1344,7 @@ impl Rc { /// let x_ptr = Rc::into_raw(x); /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` + #[must_use = "losing the pointer will leak memory"] #[stable(feature = "rc_raw", since = "1.17.0")] #[rustc_never_returns_null_ptr] pub fn into_raw(this: Self) -> *const T { @@ -2970,7 +2986,7 @@ impl Weak { /// /// [`from_raw`]: Weak::from_raw /// [`as_ptr`]: Weak::as_ptr - #[must_use = "`self` will be dropped if the result is not used"] + #[must_use = "losing the pointer will leak memory"] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { let result = self.as_ptr(); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 00f47f5c6e0ed..80f0f2acc99a2 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2719,7 +2719,7 @@ impl Weak { /// /// [`from_raw`]: Weak::from_raw /// [`as_ptr`]: Weak::as_ptr - #[must_use = "`self` will be dropped if the result is not used"] + #[must_use = "losing the pointer will leak memory"] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { let result = self.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 7bd19875584a3..c0e934b3b1fcb 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1490,6 +1490,12 @@ impl Vec { /// vec.insert(4, 5); /// assert_eq!(vec, [1, 4, 2, 3, 5]); /// ``` + /// + /// # Time complexity + /// + /// Takes *O*([`Vec::len`]) time. All items after the insertion index must be + /// shifted to the right. In the worst case, all elements are shifted when + /// the insertion index is 0. #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, index: usize, element: T) { @@ -1913,6 +1919,13 @@ impl Vec { /// vec.push(3); /// assert_eq!(vec, [1, 2, 3]); /// ``` + /// + /// # Time complexity + /// + /// Takes amortized *O*(1) time. If the vector's length would exceed its + /// capacity after the push, *O*(*capacity*) time is taken to copy the + /// vector's elements to a larger allocation. This expensive operation is + /// offset by the *capacity* *O*(1) insertions it allows. #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1961,6 +1974,10 @@ impl Vec { /// } /// assert_eq!(from_iter_fallible(0..100), Ok(Vec::from_iter(0..100))); /// ``` + /// + /// # Time complexity + /// + /// Takes *O*(1) time. #[inline] #[unstable(feature = "vec_push_within_capacity", issue = "100486")] pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> { @@ -1990,6 +2007,10 @@ impl Vec { /// assert_eq!(vec.pop(), Some(3)); /// assert_eq!(vec, [1, 2]); /// ``` + /// + /// # Time complexity + /// + /// Takes *O*(1) time. #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> Option { diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index e1b7b46a1ed2f..4d73c8c3f99a9 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -633,6 +633,23 @@ pub use macros::Debug; /// [tostring]: ../../std/string/trait.ToString.html /// [tostring_function]: ../../std/string/trait.ToString.html#tymethod.to_string /// +/// # Internationalization +/// +/// Because a type can only have one `Display` implementation, it is often preferable +/// to only implement `Display` when there is a single most "obvious" way that +/// values can be formatted as text. This could mean formatting according to the +/// "invariant" culture and "undefined" locale, or it could mean that the type +/// display is designed for a specific culture/locale, such as developer logs. +/// +/// If not all values have a justifiably canonical textual format or if you want +/// to support alternative formats not covered by the standard set of possible +/// [formatting traits], the most flexible approach is display adapters: methods +/// like [`str::escape_default`] or [`Path::display`] which create a wrapper +/// implementing `Display` to output the specific display format. +/// +/// [formatting traits]: ../../std/fmt/index.html#formatting-traits +/// [`Path::display`]: ../../std/path/struct.Path.html#method.display +/// /// # Examples /// /// Implementing `Display` on a type: diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs index 67b745373f019..9803b6eab2db5 100644 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ b/src/tools/tidy/src/fluent_alphabetical.rs @@ -1,6 +1,7 @@ //! Checks that all Flunt files have messages in alphabetical order use crate::walk::{filter_dirs, walk}; +use std::collections::HashMap; use std::{fs::OpenOptions, io::Write, path::Path}; use regex::Regex; @@ -13,11 +14,27 @@ fn filter_fluent(path: &Path) -> bool { if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true } } -fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) { +fn check_alphabetic( + filename: &str, + fluent: &str, + bad: &mut bool, + all_defined_msgs: &mut HashMap, +) { let mut matches = MESSAGE.captures_iter(fluent).peekable(); while let Some(m) = matches.next() { + let name = m.get(1).unwrap(); + if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { + tidy_error!( + bad, + "{filename}: message `{}` is already defined in {}", + name.as_str(), + defined_filename, + ); + } + + all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); + if let Some(next) = matches.peek() { - let name = m.get(1).unwrap(); let next = next.get(1).unwrap(); if name.as_str() > next.as_str() { tidy_error!( @@ -34,13 +51,29 @@ run `./x.py test tidy --bless` to sort the file correctly", } } -fn sort_messages(fluent: &str) -> String { +fn sort_messages( + filename: &str, + fluent: &str, + bad: &mut bool, + all_defined_msgs: &mut HashMap, +) -> String { let mut chunks = vec![]; let mut cur = String::new(); for line in fluent.lines() { - if MESSAGE.is_match(line) { + if let Some(name) = MESSAGE.find(line) { + if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { + tidy_error!( + bad, + "{filename}: message `{}` is already defined in {}", + name.as_str(), + defined_filename, + ); + } + + all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); chunks.push(std::mem::take(&mut cur)); } + cur += line; cur.push('\n'); } @@ -53,20 +86,33 @@ fn sort_messages(fluent: &str) -> String { } pub fn check(path: &Path, bless: bool, bad: &mut bool) { + let mut all_defined_msgs = HashMap::new(); walk( path, |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)), &mut |ent, contents| { if bless { - let sorted = sort_messages(contents); + let sorted = sort_messages( + ent.path().to_str().unwrap(), + contents, + bad, + &mut all_defined_msgs, + ); if sorted != contents { let mut f = OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap(); f.write(sorted.as_bytes()).unwrap(); } } else { - check_alphabetic(ent.path().to_str().unwrap(), contents, bad); + check_alphabetic( + ent.path().to_str().unwrap(), + contents, + bad, + &mut all_defined_msgs, + ); } }, ); + + crate::fluent_used::check(path, all_defined_msgs, bad); } diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs new file mode 100644 index 0000000000000..b73e79cb38d94 --- /dev/null +++ b/src/tools/tidy/src/fluent_used.rs @@ -0,0 +1,43 @@ +//! Checks that all Fluent messages appear at least twice + +use crate::walk::{filter_dirs, walk}; +use regex::Regex; +use std::collections::HashMap; +use std::path::Path; + +lazy_static::lazy_static! { + static ref WORD: Regex = Regex::new(r"\w+").unwrap(); +} + +fn filter_used_messages( + contents: &str, + msgs_not_appeared_yet: &mut HashMap, + msgs_appeared_only_once: &mut HashMap, +) { + // we don't just check messages never appear in Rust files, + // because messages can be used as parts of other fluent messages in Fluent files, + // so we do checking messages appear only once in all Rust and Fluent files. + let mut matches = WORD.find_iter(contents); + while let Some(name) = matches.next() { + if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) { + // if one msg appears for the first time, + // remove it from `msgs_not_appeared_yet` and insert it into `msgs_appeared_only_once`. + msgs_appeared_only_once.insert(name, filename); + } else { + // if one msg appears for the second time, + // remove it from `msgs_appeared_only_once`. + msgs_appeared_only_once.remove(name.as_str()); + } + } +} + +pub fn check(path: &Path, mut all_defined_msgs: HashMap, bad: &mut bool) { + let mut msgs_appear_only_once = HashMap::new(); + walk(path, |path, _| filter_dirs(path), &mut |_, contents| { + filter_used_messages(contents, &mut all_defined_msgs, &mut msgs_appear_only_once); + }); + + for (name, filename) in msgs_appear_only_once { + tidy_error!(bad, "{filename}: message `{}` is not used", name,); + } +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 6f3ade0ab58c7..670b7eb2be995 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -65,6 +65,7 @@ pub mod ext_tool_checks; pub mod extdeps; pub mod features; pub mod fluent_alphabetical; +mod fluent_used; pub(crate) mod iter_header; pub mod mir_opt_tests; pub mod pal; diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.rs b/tests/ui/async-await/async-outside-of-await-issue-121096.rs new file mode 100644 index 0000000000000..e3999035ef91f --- /dev/null +++ b/tests/ui/async-await/async-outside-of-await-issue-121096.rs @@ -0,0 +1,9 @@ +//@ edition:2021 + +fn main() { + async { + use std::ops::Add; + let _ = 1.add(3); + }.await + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.stderr b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr new file mode 100644 index 0000000000000..b0677a83864e0 --- /dev/null +++ b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr @@ -0,0 +1,12 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/async-outside-of-await-issue-121096.rs:7:7 + | +LL | fn main() { + | ---- this is not `async` +... +LL | }.await + | ^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index ba30bc1e69b50..69156ab67635e 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -74,6 +74,8 @@ fn test_cfg_macro() { //~^ WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value + cfg!(target_feature = "zebra"); + //~^ WARNING unexpected `cfg` condition value } fn main() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 77643f227d9d0..93333e5ef2a5b 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -245,5 +245,14 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))` = note: see for more information about checking conditional configuration -warning: 26 warnings emitted +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:77:10 + | +LL | cfg!(target_feature = "zebra"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 186 more + = note: see for more information about checking conditional configuration + +warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 859a36c604c6f..fa062a3fe2eae 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -6,6 +6,7 @@ // //@ check-pass //@ compile-flags: --check-cfg=cfg() -Z unstable-options +//@ compile-flags: -Zcheck-cfg-all-expected #![feature(cfg_overflow_checks)] #![feature(cfg_relocation_model)] diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 01fc3f83f162b..86df829fe726c 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:25:5 + --> $DIR/well-known-values.rs:26:5 | LL | clippy = "_UNEXPECTED_VALUE", | ^^^^^^---------------------- @@ -11,7 +11,7 @@ LL | clippy = "_UNEXPECTED_VALUE", = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:27:5 + --> $DIR/well-known-values.rs:28:5 | LL | debug_assertions = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^---------------------- @@ -22,7 +22,7 @@ LL | debug_assertions = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:29:5 + --> $DIR/well-known-values.rs:30:5 | LL | doc = "_UNEXPECTED_VALUE", | ^^^---------------------- @@ -33,7 +33,7 @@ LL | doc = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:31:5 + --> $DIR/well-known-values.rs:32:5 | LL | doctest = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -44,7 +44,7 @@ LL | doctest = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:33:5 + --> $DIR/well-known-values.rs:34:5 | LL | miri = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -55,7 +55,7 @@ LL | miri = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:35:5 + --> $DIR/well-known-values.rs:36:5 | LL | overflow_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^---------------------- @@ -66,7 +66,7 @@ LL | overflow_checks = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:37:5 + --> $DIR/well-known-values.rs:38:5 | LL | panic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL | panic = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:39:5 + --> $DIR/well-known-values.rs:40:5 | LL | proc_macro = "_UNEXPECTED_VALUE", | ^^^^^^^^^^---------------------- @@ -86,7 +86,7 @@ LL | proc_macro = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:41:5 + --> $DIR/well-known-values.rs:42:5 | LL | relocation_model = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | relocation_model = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:43:5 + --> $DIR/well-known-values.rs:44:5 | LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | sanitize = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:45:5 + --> $DIR/well-known-values.rs:46:5 | LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | target_abi = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:47:5 + --> $DIR/well-known-values.rs:48:5 | LL | target_arch = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | target_arch = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:49:5 + --> $DIR/well-known-values.rs:50:5 | LL | target_endian = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | target_endian = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:51:5 + --> $DIR/well-known-values.rs:52:5 | LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -140,7 +140,7 @@ LL | target_env = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:53:5 + --> $DIR/well-known-values.rs:54:5 | LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | target_family = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:55:5 + --> $DIR/well-known-values.rs:56:5 | LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL | target_feature = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:57:5 + --> $DIR/well-known-values.rs:58:5 | LL | target_has_atomic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +167,7 @@ LL | target_has_atomic = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:59:5 + --> $DIR/well-known-values.rs:60:5 | LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:61:5 + --> $DIR/well-known-values.rs:62:5 | LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:63:5 + --> $DIR/well-known-values.rs:64:5 | LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -194,7 +194,7 @@ LL | target_os = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:65:5 + --> $DIR/well-known-values.rs:66:5 | LL | target_pointer_width = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,7 +203,7 @@ LL | target_pointer_width = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:67:5 + --> $DIR/well-known-values.rs:68:5 | LL | target_thread_local = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^---------------------- @@ -214,7 +214,7 @@ LL | target_thread_local = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:69:5 + --> $DIR/well-known-values.rs:70:5 | LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -223,7 +223,7 @@ LL | target_vendor = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:71:5 + --> $DIR/well-known-values.rs:72:5 | LL | test = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -234,7 +234,7 @@ LL | test = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:73:5 + --> $DIR/well-known-values.rs:74:5 | LL | unix = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -245,7 +245,7 @@ LL | unix = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:75:5 + --> $DIR/well-known-values.rs:76:5 | LL | windows = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -256,7 +256,7 @@ LL | windows = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `linuz` - --> $DIR/well-known-values.rs:81:7 + --> $DIR/well-known-values.rs:82:7 | LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | ^^^^^^^^^^^^------- diff --git a/tests/ui/codegen/duplicated-path-in-error.rs b/tests/ui/codegen/duplicated-path-in-error.rs new file mode 100644 index 0000000000000..cff20dd9bd639 --- /dev/null +++ b/tests/ui/codegen/duplicated-path-in-error.rs @@ -0,0 +1,7 @@ +//@ only-linux +//@ compile-flags: -Zcodegen-backend=/non-existing-one.so + +// This test ensures that the error of the "not found dylib" doesn't duplicate +// the path of the dylib. + +fn main() {} diff --git a/tests/ui/codegen/duplicated-path-in-error.stderr b/tests/ui/codegen/duplicated-path-in-error.stderr new file mode 100644 index 0000000000000..d0d34e2f93468 --- /dev/null +++ b/tests/ui/codegen/duplicated-path-in-error.stderr @@ -0,0 +1,2 @@ +error: couldn't load codegen backend /non-existing-one.so: cannot open shared object file: No such file or directory + diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs new file mode 100644 index 0000000000000..1278563a92c46 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs @@ -0,0 +1,28 @@ +//! This test demonstrates a bug where we accidentally +//! detected opaque types in struct fields, but only if nested +//! in projections of another opaque type. + +#![feature(impl_trait_in_assoc_type)] + +struct Bar; + +trait Trait: Sized { + type Assoc2; + type Assoc; + fn foo() -> Self::Assoc; +} + +impl Trait for Bar { + type Assoc2 = impl std::fmt::Debug; + type Assoc = impl Iterator; + fn foo() -> Self::Assoc { + vec![Foo { field: () }].into_iter() + //~^ ERROR item constrains opaque type that is not in its signature + } +} + +struct Foo { + field: ::Assoc2, +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr new file mode 100644 index 0000000000000..0570e0303c633 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr @@ -0,0 +1,15 @@ +error: item constrains opaque type that is not in its signature + --> $DIR/hidden_behind_struct_field3.rs:19:27 + | +LL | vec![Foo { field: () }].into_iter() + | ^^ + | + = note: this item must mention the opaque type in its signature in order to be able to register hidden types +note: this item must mention the opaque type in its signature in order to be able to register hidden types + --> $DIR/hidden_behind_struct_field3.rs:18:8 + | +LL | fn foo() -> Self::Assoc { + | ^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs new file mode 100644 index 0000000000000..5d15ec4cffdb9 --- /dev/null +++ b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs @@ -0,0 +1,25 @@ +type NodeId = u32; +struct Type<'a>(std::marker::PhantomData::<&'a ()>); + +type Ast<'ast> = &'ast AstStructure<'ast>; + +struct AstStructure<'ast> { +//~^ ERROR struct with unnamed fields must have `#[repr(C)]` representation + id: NodeId, + _: AstKind<'ast> +//~^ ERROR unnamed fields are not yet fully implemented [E0658] +//~^^ ERROR unnamed fields can only have struct or union types +} + +enum AstKind<'ast> { + ExprInt, + ExprLambda(Ast<'ast>), +} + +fn compute_types<'tcx,'ast>(ast: Ast<'ast>) -> Type<'tcx> +{ + match ast.kind {} +//~^ ERROR no field `kind` on type `&'ast AstStructure<'ast>` [E0609] +} + +fn main() {} diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr new file mode 100644 index 0000000000000..4ea910202de98 --- /dev/null +++ b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr @@ -0,0 +1,45 @@ +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 + | +LL | _: AstKind<'ast> + | ^ + | + = note: see issue #49804 for more information + = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: struct with unnamed fields must have `#[repr(C)]` representation + --> $DIR/unnamed-enum-field-issue-121757.rs:6:1 + | +LL | struct AstStructure<'ast> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ struct `AstStructure` defined here + | +note: unnamed field defined here + --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 + | +LL | _: AstKind<'ast> + | ^^^^^^^^^^^^^^^^ +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct AstStructure<'ast> { + | + +error: unnamed fields can only have struct or union types + --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 + | +LL | _: AstKind<'ast> + | ^^^^^^^^^^^^^^^^ + +error[E0609]: no field `kind` on type `&'ast AstStructure<'ast>` + --> $DIR/unnamed-enum-field-issue-121757.rs:21:15 + | +LL | match ast.kind {} + | ^^^^ unknown field + | + = note: available fields are: `id`, `_` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0609, E0658. +For more information about an error, try `rustc --explain E0609`.