diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d3aacaa15a8c5..d1a2ddbdb3477 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -3,10 +3,11 @@ use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin}; use rustc_index::{IndexSlice, IndexVec}; +use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; @@ -527,7 +528,22 @@ impl<'hir> LoweringContext<'_, 'hir> { } UseTreeKind::Glob => { let res = self.expect_full_res(id); - let res = smallvec![self.lower_res(res)]; + let res = self.lower_res(res); + // Put the result in the appropriate namespace. + let res = match res { + Res::Def(DefKind::Mod | DefKind::Trait, _) => { + PerNS { type_ns: Some(res), value_ns: None, macro_ns: None } + } + Res::Def(DefKind::Enum, _) => { + PerNS { type_ns: None, value_ns: Some(res), macro_ns: None } + } + Res::Err => { + // Propagate the error to all namespaces, just to be sure. + let err = Some(Res::Err); + PerNS { type_ns: err, value_ns: err, macro_ns: err } + } + _ => span_bug!(path.span, "bad glob res {:?}", res), + }; let path = Path { segments, span: path.span, tokens: None }; let path = self.lower_use_path(res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Glob) @@ -601,7 +617,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } else { // For non-empty lists we can just drop all the data, the prefix is already // present in HIR as a part of nested imports. - self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span }) + self.arena.alloc(hir::UsePath { res: PerNS::default(), segments: &[], span }) }; hir::ItemKind::Use(path, hir::UseKind::ListStem) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 422e79ca82ffd..f41627e479ff2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -64,7 +64,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; -use smallvec::{SmallVec, smallvec}; +use smallvec::SmallVec; use thin_vec::ThinVec; use tracing::{debug, instrument, trace}; @@ -705,14 +705,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } - fn lower_import_res(&mut self, id: NodeId, span: Span) -> SmallVec<[Res; 3]> { - let res = self.resolver.get_import_res(id).present_items(); - let res: SmallVec<_> = res.map(|res| self.lower_res(res)).collect(); - if res.is_empty() { + fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS> { + let per_ns = self.resolver.get_import_res(id); + let per_ns = per_ns.map(|res| res.map(|res| self.lower_res(res))); + if per_ns.is_empty() { + // Propagate the error to all namespaces, just to be sure. self.dcx().span_delayed_bug(span, "no resolution for an import"); - return smallvec![Res::Err]; + let err = Some(Res::Err); + return PerNS { type_ns: err, value_ns: err, macro_ns: err }; } - res + per_ns } fn make_lang_item_qpath( diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 5cda64ce7b4ba..c80ef275c801a 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,13 +1,13 @@ use std::sync::Arc; use rustc_ast::{self as ast, *}; -use rustc_hir::def::{DefKind, PartialRes, Res}; +use rustc_hir::def::{DefKind, PartialRes, PerNS, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, GenericArg}; use rustc_middle::{span_bug, ty}; use rustc_session::parse::add_feature_diagnostics; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym}; -use smallvec::{SmallVec, smallvec}; +use smallvec::smallvec; use tracing::{debug, instrument}; use super::errors::{ @@ -226,11 +226,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { pub(crate) fn lower_use_path( &mut self, - res: SmallVec<[Res; 3]>, + res: PerNS>, p: &Path, param_mode: ParamMode, ) -> &'hir hir::UsePath<'hir> { - assert!((1..=3).contains(&res.len())); + assert!(!res.is_empty()); self.arena.alloc(hir::UsePath { res, segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 56cc432758511..a5c9bad3ac2db 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -840,14 +840,22 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } else { bug!("not an upvar") }; - err.span_label( - *span, - format!( - "calling `{}` requires mutable binding due to {}", - self.describe_place(the_place_err).unwrap(), - reason - ), - ); + // sometimes we deliberately don't store the name of a place when coming from a macro in + // another crate. We generally want to limit those diagnostics a little, to hide + // implementation details (such as those from pin!() or format!()). In that case show a + // slightly different error message, or none at all if something else happened. In other + // cases the message is likely not useful. + if let Some(place_name) = self.describe_place(the_place_err) { + err.span_label( + *span, + format!("calling `{place_name}` requires mutable binding due to {reason}"), + ); + } else if span.from_expansion() { + err.span_label( + *span, + format!("a call in this macro requires a mutable binding due to {reason}",), + ); + } } } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 88c0d223fd39a..b0dff635a9bdb 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -8,7 +8,6 @@ macro_rules! arena_types { [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_hir::Attribute, [] owner_info: rustc_hir::OwnerInfo<'tcx>, - [] use_path: rustc_hir::UsePath<'tcx>, [] lit: rustc_hir::Lit, [] macro_def: rustc_ast::MacroDef, ]); diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 507c94aca8b9a..98ec1ccd6bad6 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -584,7 +584,7 @@ impl ToStableHashKey for Namespace { } /// Just a helper ‒ separate structure for each namespace. -#[derive(Copy, Clone, Default, Debug)] +#[derive(Copy, Clone, Default, Debug, HashStable_Generic)] pub struct PerNS { pub value_ns: T, pub type_ns: T, @@ -596,10 +596,16 @@ impl PerNS { PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) } } + /// Note: Do you really want to use this? Often you know which namespace a + /// name will belong in, and you can consider just that namespace directly, + /// rather than iterating through all of them. pub fn into_iter(self) -> IntoIter { [self.value_ns, self.type_ns, self.macro_ns].into_iter() } + /// Note: Do you really want to use this? Often you know which namespace a + /// name will belong in, and you can consider just that namespace directly, + /// rather than iterating through all of them. pub fn iter(&self) -> IntoIter<&T, 3> { [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter() } @@ -634,6 +640,10 @@ impl PerNS> { } /// Returns an iterator over the items which are `Some`. + /// + /// Note: Do you really want to use this? Often you know which namespace a + /// name will belong in, and you can consider just that namespace directly, + /// rather than iterating through all of them. pub fn present_items(self) -> impl Iterator { [self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten() } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b4fcc16c09c85..4f05e1c816c3d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -30,7 +30,7 @@ use thin_vec::ThinVec; use tracing::debug; use crate::LangItem; -use crate::def::{CtorKind, DefKind, Res}; +use crate::def::{CtorKind, DefKind, PerNS, Res}; use crate::def_id::{DefId, LocalDefIdMap}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; use crate::intravisit::{FnKind, VisitorExt}; @@ -347,7 +347,7 @@ pub struct Path<'hir, R = Res> { } /// Up to three resolutions for type, value and macro namespaces. -pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>; +pub type UsePath<'hir> = Path<'hir, PerNS>>; impl Path<'_> { pub fn is_global(&self) -> bool { @@ -2370,6 +2370,10 @@ impl Expr<'_> { // Lang item paths cannot currently be local variables or statics. ExprKind::Path(QPath::LangItem(..)) => false, + // Suppress errors for bad expressions. + ExprKind::Err(_guar) + | ExprKind::Let(&LetExpr { recovered: ast::Recovered::Yes(_guar), .. }) => true, + // Partially qualified paths in expressions can only legally // refer to associated items which are always rvalues. ExprKind::Path(QPath::TypeRelative(..)) @@ -2401,8 +2405,7 @@ impl Expr<'_> { | ExprKind::Binary(..) | ExprKind::Yield(..) | ExprKind::Cast(..) - | ExprKind::DropTemps(..) - | ExprKind::Err(_) => false, + | ExprKind::DropTemps(..) => false, } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1fd44e44b9ce0..b6ebd61301c0b 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1148,7 +1148,7 @@ pub fn walk_use<'v, V: Visitor<'v>>( hir_id: HirId, ) -> V::Result { let UsePath { segments, ref res, span } = *path; - for &res in res { + for res in res.present_items() { try_visit!(visitor.visit_path(&Path { segments, res, span }, hir_id)); } V::Result::output() diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 1d4be24ea9fa0..1805a674d68db 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -328,16 +328,19 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return }; - let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id); + let is_mod_inherent = |res: Res| { + res.opt_def_id() + .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id)) + }; // Path segments except for the final. - if let Some(seg) = - path.segments.iter().find(|seg| seg.res.opt_def_id().is_some_and(is_mod_inherent)) - { + if let Some(seg) = path.segments.iter().find(|seg| is_mod_inherent(seg.res)) { cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage); } // Final path resolutions, like `use rustc_type_ir::inherent` - else if path.res.iter().any(|res| res.opt_def_id().is_some_and(is_mod_inherent)) { + else if let Some(type_ns) = path.res.type_ns + && is_mod_inherent(type_ns) + { cx.emit_span_lint( USAGE_OF_TYPE_IR_INHERENT, path.segments.last().unwrap().ident.span, @@ -346,13 +349,12 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr { } let (lo, hi, snippet) = match path.segments { - [.., penultimate, segment] - if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) => - { + [.., penultimate, segment] if is_mod_inherent(penultimate.res) => { (segment.ident.span, item.kind.ident().unwrap().span, "*") } [.., segment] - if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent) + if let Some(type_ns) = path.res.type_ns + && is_mod_inherent(type_ns) && let rustc_hir::UseKind::Single(ident) = kind => { let (lo, snippet) = diff --git a/compiler/rustc_lint/src/unqualified_local_imports.rs b/compiler/rustc_lint/src/unqualified_local_imports.rs index 50c5119285f7c..0076cae3cff3c 100644 --- a/compiler/rustc_lint/src/unqualified_local_imports.rs +++ b/compiler/rustc_lint/src/unqualified_local_imports.rs @@ -1,4 +1,3 @@ -use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::kw; @@ -47,17 +46,15 @@ declare_lint_pass!(UnqualifiedLocalImports => [UNQUALIFIED_LOCAL_IMPORTS]); impl<'tcx> LateLintPass<'tcx> for UnqualifiedLocalImports { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { let hir::ItemKind::Use(path, _kind) = item.kind else { return }; - // `path` has three resolutions for the type, module, value namespaces. - // Check if any of them qualifies: local crate, and not a macro. - // (Macros can't be imported any other way so we don't complain about them.) - let is_local_import = |res: &Res| { - matches!( - res, - hir::def::Res::Def(def_kind, def_id) - if def_id.is_local() && !matches!(def_kind, DefKind::Macro(_)), - ) - }; - if !path.res.iter().any(is_local_import) { + // Check the type and value namespace resolutions for a local crate. + let is_local_import = matches!( + path.res.type_ns, + Some(hir::def::Res::Def(_, def_id)) if def_id.is_local() + ) || matches!( + path.res.value_ns, + Some(hir::def::Res::Def(_, def_id)) if def_id.is_local() + ); + if !is_local_import { return; } // So this does refer to something local. Let's check whether it starts with `self`, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 78583a402fe9a..245bd866030c1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1047,26 +1047,21 @@ fn find_fallback_pattern_typo<'tcx>( let hir::ItemKind::Use(path, _) = item.kind else { continue; }; - for res in &path.res { - if let Res::Def(DefKind::Const, id) = res - && infcx.can_eq(param_env, ty, cx.tcx.type_of(id).instantiate_identity()) - { - if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) { - // The original const is accessible, suggest using it directly. - let item_name = cx.tcx.item_name(*id); - accessible.push(item_name); - accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id))); - } else if cx - .tcx - .visibility(item.owner_id) - .is_accessible_from(parent, cx.tcx) - { - // The const is accessible only through the re-export, point at - // the `use`. - let ident = item.kind.ident().unwrap(); - imported.push(ident.name); - imported_spans.push(ident.span); - } + if let Some(value_ns) = path.res.value_ns + && let Res::Def(DefKind::Const, id) = value_ns + && infcx.can_eq(param_env, ty, cx.tcx.type_of(id).instantiate_identity()) + { + if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) { + // The original const is accessible, suggest using it directly. + let item_name = cx.tcx.item_name(id); + accessible.push(item_name); + accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id))); + } else if cx.tcx.visibility(item.owner_id).is_accessible_from(parent, cx.tcx) { + // The const is accessible only through the re-export, point at + // the `use`. + let ident = item.kind.ident().unwrap(); + imported.push(ident.name); + imported_spans.push(ident.span); } } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 211e2a92f73d8..c15d7d6f732c9 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -1,6 +1,7 @@ use std::{fmt, iter, mem}; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_index::Idx; use rustc_middle::mir::*; @@ -254,8 +255,19 @@ where // impl_item_refs may be empty if drop fn is not implemented in 'impl AsyncDrop for ...' // (#140974). // Such code will report error, so just generate sync drop here and return - let Some(drop_fn_def_id) = - tcx.associated_item_def_ids(drop_trait).into_iter().nth(0).copied() + let Some(drop_fn_def_id) = tcx + .associated_item_def_ids(drop_trait) + .first() + .and_then(|def_id| { + if tcx.def_kind(def_id) == DefKind::AssocFn + && tcx.check_args_compatible(*def_id, trait_args) + { + Some(def_id) + } else { + None + } + }) + .copied() else { tcx.dcx().span_delayed_bug( self.elaborator.body().span, diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index 2bb698689bee2..b9a3849f32fec 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -132,7 +132,7 @@ impl<'tcx> Visitor<'tcx> for ExportableItemCollector<'tcx> { self.add_exportable(def_id); } hir::ItemKind::Use(path, _) => { - for res in &path.res { + for res in path.res.present_items() { // Only local items are exportable. if let Some(res_id) = res.opt_def_id() && let Some(res_id) = res_id.as_local() diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index e0b2adb3fc953..9b824572b66ee 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -118,9 +118,10 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { ast::UseTreeKind::Simple(Some(ident)) => { if ident.name == kw::Underscore && !self.r.import_res_map.get(&id).is_some_and(|per_ns| { - per_ns.iter().filter_map(|res| res.as_ref()).any(|res| { - matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) - }) + matches!( + per_ns.type_ns, + Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) + ) }) { self.unused_import(self.base_id).add(id); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 744e99c86e1a6..23ede3cdbad8c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4898,11 +4898,28 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_expr(e, Some(expr)); } - ExprKind::Let(ref pat, ref scrutinee, _, _) => { + ExprKind::Let(ref pat, ref scrutinee, _, Recovered::No) => { self.visit_expr(scrutinee); self.resolve_pattern_top(pat, PatternSource::Let); } + ExprKind::Let(ref pat, ref scrutinee, _, Recovered::Yes(_)) => { + self.visit_expr(scrutinee); + // This is basically a tweaked, inlined `resolve_pattern_top`. + let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; + self.resolve_pattern(pat, PatternSource::Let, &mut bindings); + // We still collect the bindings in this `let` expression which is in + // an invalid position (and therefore shouldn't declare variables into + // its parent scope). To avoid unnecessary errors though, we do just + // reassign the resolutions to `Res::Err`. + for (_, bindings) in &mut bindings { + for (_, binding) in bindings { + *binding = Res::Err; + } + } + self.apply_pattern_bindings(bindings); + } + ExprKind::If(ref cond, ref then, ref opt_else) => { self.with_rib(ValueNS, RibKind::Normal, |this| { let old = this.diag_metadata.in_if_condition.replace(cond); diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 7d519384e373c..02bb81792931e 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -84,7 +84,7 @@ use crate::ptr; /// use std::mem::ManuallyDrop; /// /// pub struct BadOption { -/// // Invariant: Has been dropped iff `is_some` is false. +/// // Invariant: Has been dropped if `is_some` is false. /// value: ManuallyDrop, /// is_some: bool, /// } diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 324b5451873bf..a5c3a6c46a433 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -159,8 +159,11 @@ impl OnceLock { /// Gets the mutable reference to the underlying value. /// - /// Returns `None` if the cell is uninitialized, or being initialized. - /// This method never blocks. + /// Returns `None` if the cell is uninitialized. + /// + /// This method never blocks. Since it borrows the `OnceLock` mutably, + /// it is statically guaranteed that no active borrows to the `OnceLock` + /// exist, including from other threads. #[inline] #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_mut(&mut self) -> Option<&mut T> { @@ -315,7 +318,9 @@ impl OnceLock { /// Gets the mutable reference of the contents of the cell, initializing /// it to `f()` if the cell was uninitialized. /// - /// This method never blocks. + /// This method never blocks. Since it borrows the `OnceLock` mutably, + /// it is statically guaranteed that no active borrows to the `OnceLock` + /// exist, including from other threads. /// /// # Panics /// @@ -405,7 +410,9 @@ impl OnceLock { /// it to `f()` if the cell was uninitialized. If the cell was uninitialized /// and `f()` failed, an error is returned. /// - /// This method never blocks. + /// This method never blocks. Since it borrows the `OnceLock` mutably, + /// it is statically guaranteed that no active borrows to the `OnceLock` + /// exist, including from other threads. /// /// # Panics /// @@ -469,7 +476,8 @@ impl OnceLock { /// /// Has no effect and returns `None` if the `OnceLock` was uninitialized. /// - /// Safety is guaranteed by requiring a mutable reference. + /// Since this method borrows the `OnceLock` mutably, it is statically guaranteed that + /// no active borrows to the `OnceLock` exist, including from other threads. /// /// # Examples /// diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7e8e087c3a20e..e8cf25b190621 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1606,7 +1606,7 @@ fn first_non_private<'tcx>( && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id) && let hir::ItemKind::Use(path, hir::UseKind::Single(_)) = item.kind { - for res in &path.res { + for res in path.res.present_items() { if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { continue; } @@ -3014,7 +3014,7 @@ fn clean_use_statement<'tcx>( ) -> Vec { let mut items = Vec::new(); let hir::UsePath { segments, ref res, span } = *path; - for &res in res { + for res in res.present_items() { let path = hir::Path { segments, res, span }; items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names)); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 254549e72c649..5b52e785b8f59 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} hir::ItemKind::Use(path, kind) => { - for &res in &path.res { + for res in path.res.present_items() { // Struct and variant constructors and proc macro stubs always show up alongside // their definitions, we've already processed them so just discard these. if should_ignore_res(res) { diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs index d0b2f0c8407ff..821bb25d2ceca 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs @@ -106,8 +106,8 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]); impl<'tcx> LateLintPass<'tcx> for DisallowedTypes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { - for res in &path.res { - self.check_res_emit(cx, res, item.span); + if let Some(res) = path.res.type_ns { + self.check_res_emit(cx, &res, item.span); } } } diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index 01b49403cac85..b3c63f022d353 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -51,7 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { // so lint on the `use` statement directly. if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind && !item.span.in_external_macro(cx.sess().source_map()) - && let Some(def_id) = path.res[0].opt_def_id() + // use `present_items` because it could be in either type_ns or value_ns + && let Some(res) = path.res.present_items().next() + && let Some(def_id) = res.opt_def_id() && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) { let module = if is_integer_module(cx, def_id) { diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 98ad1f6a160d8..c1a26c5a9c73d 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -100,10 +100,7 @@ impl LateLintPass<'_> for MacroUseImports { && let hir_id = item.hir_id() && let attrs = cx.tcx.hir_attrs(hir_id) && let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use)) - && let Some(id) = path.res.iter().find_map(|res| match res { - Res::Def(DefKind::Mod, id) => Some(id), - _ => None, - }) + && let Some(Res::Def(DefKind::Mod, id)) = path.res.type_ns && !id.is_local() { for kid in cx.tcx.module_children(id) { diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 00ea9bba0d194..99f01c8001a55 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -131,8 +131,9 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { // If however the identifier is different, this means it is an alias (`use foo::bar as baz`). In // this case, we need to emit the warning for `baz`. if let Some(imported_item_path) = usenode - && let Some(Res::Def(_, imported_item_defid)) = imported_item_path.res.first() - && cx.tcx.item_name(*imported_item_defid).as_str() == str + // use `present_items` because it could be in any of type_ns, value_ns, macro_ns + && let Some(Res::Def(_, imported_item_defid)) = imported_item_path.res.value_ns + && cx.tcx.item_name(imported_item_defid).as_str() == str { return; } diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index a1e621cc9f6b5..eeea6dfd5f4be 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -72,7 +72,8 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]); impl LateLintPass<'_> for ImportRename { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { - for &res in &path.res { + // use `present_items` because it could be in any of type_ns, value_ns, macro_ns + for res in path.res.present_items() { if let Res::Def(_, id) = res && let Some(name) = self.renames.get(&id) // Remove semicolon since it is not present for nested imports diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 7b381fac5f118..3828aff4164e8 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::HasSession; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind}; +use rustc_hir::{Item, ItemKind, UseKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::impl_lint_pass; @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()) && !cx.effective_visibilities.is_exported(item.owner_id.def_id) && self.is_exported.last() == Some(&false) - && is_not_macro_export(item) + && !is_ignorable_export(item) && !item.span.in_external_macro(cx.sess().source_map()) { let span = item @@ -86,18 +86,17 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { } } -fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool { - if let ItemKind::Use(path, _) = item.kind { - if path - .res - .iter() - .all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _))) - { - return false; +// We ignore macro exports. And `ListStem` uses, which aren't interesting. +fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool { + if let ItemKind::Use(path, kind) = item.kind { + let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(MacroKind::Bang), _))) + || kind == UseKind::ListStem; + if ignore { + return true; } } else if let ItemKind::Macro(..) = item.kind { - return false; + return true; } - true + false } diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs index 14ac65cf4dfe1..610cec7b8c8de 100644 --- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs +++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { // Ignore imports that already use Underscore && ident.name != kw::Underscore // Only check traits - && let Some(Res::Def(DefKind::Trait, _)) = path.res.first() + && let Some(Res::Def(DefKind::Trait, _)) = path.res.type_ns && cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id) // Only check this import if it is visible to its module only (no pub, pub(crate), ...) && let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id) diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 45a5dbabeb4ef..467811c586bf9 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -169,8 +169,8 @@ impl LateLintPass<'_> for WildcardImports { format!("{import_source_snippet}::{imports_string}") }; - // Glob imports always have a single resolution. - let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res[0] { + // Glob imports always have a single resolution. Enums are in the value namespace. + let (lint, message) = if let Some(Res::Def(DefKind::Enum, _)) = use_path.res.value_ns { (ENUM_GLOB_USE, "usage of wildcard import for enum variants") } else { (WILDCARD_IMPORTS, "usage of wildcard import") diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 9d7f3086b05fa..f37a609497eb7 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -306,10 +306,13 @@ fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, n let item = tcx.hir_item(item_id); if let ItemKind::Use(path, UseKind::Single(ident)) = item.kind { if ident.name == name { - path.res - .iter() - .find(|res| ns.matches(res.ns())) - .and_then(Res::opt_def_id) + let opt_def_id = |ns: Option| ns.and_then(|res| res.opt_def_id()); + match ns { + PathNS::Type => opt_def_id(path.res.type_ns), + PathNS::Value => opt_def_id(path.res.value_ns), + PathNS::Macro => opt_def_id(path.res.macro_ns), + PathNS::Arbitrary => unreachable!(), + } } else { None } diff --git a/tests/crashes/140484.rs b/tests/crashes/140484.rs deleted file mode 100644 index 92ec19843982d..0000000000000 --- a/tests/crashes/140484.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: #140484 -//@edition:2024 -#![feature(async_drop)] -use std::future::AsyncDrop; -struct a; -impl Drop for a { - fn b() {} -} -impl AsyncDrop for a { - type c; -} -async fn bar() { - a; -} diff --git a/tests/crashes/140500.rs b/tests/crashes/140500.rs deleted file mode 100644 index ee5b93ab82132..0000000000000 --- a/tests/crashes/140500.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: #140500 - -#![feature(async_drop)] -use std::future::AsyncDrop; -struct a; -impl Drop for a { - fn b() {} -} -impl AsyncDrop for a { - fn c(d: impl Sized) {} -} -async fn bar() { - a; -} diff --git a/tests/ui/allocator/auxiliary/helper.rs b/tests/ui/allocator/auxiliary/helper.rs index c638546a9475f..4267b901ca07f 100644 --- a/tests/ui/allocator/auxiliary/helper.rs +++ b/tests/ui/allocator/auxiliary/helper.rs @@ -6,6 +6,6 @@ extern crate alloc; use alloc::fmt; -pub fn work_with(p: &fmt::Debug) { +pub fn work_with(p: &dyn fmt::Debug) { drop(p); } diff --git a/tests/ui/async-await/async-drop/type-parameter.rs b/tests/ui/async-await/async-drop/type-parameter.rs new file mode 100644 index 0000000000000..dde5f9f8e6444 --- /dev/null +++ b/tests/ui/async-await/async-drop/type-parameter.rs @@ -0,0 +1,16 @@ +//@ edition: 2024 +// ex-ice: #140500 +#![crate_type = "lib"] +#![feature(async_drop)] +#![expect(incomplete_features)] +use std::future::AsyncDrop; +struct A; +impl Drop for A { + fn drop(&mut self) {} +} +impl AsyncDrop for A { + fn drop(_wrong: impl Sized) {} //~ ERROR: method `drop` has a `self: Pin<&mut Self>` declaration in the trait, but not in the impl +} +async fn bar() { + A; +} diff --git a/tests/ui/async-await/async-drop/type-parameter.stderr b/tests/ui/async-await/async-drop/type-parameter.stderr new file mode 100644 index 0000000000000..841576b839e68 --- /dev/null +++ b/tests/ui/async-await/async-drop/type-parameter.stderr @@ -0,0 +1,11 @@ +error[E0186]: method `drop` has a `self: Pin<&mut Self>` declaration in the trait, but not in the impl + --> $DIR/type-parameter.rs:12:5 + | +LL | fn drop(_wrong: impl Sized) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `self: Pin<&mut Self>` in impl + | + = note: `drop` from trait: `fn(Pin<&mut Self>) -> impl Future` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0186`. diff --git a/tests/ui/async-await/async-drop/unexpected-sort.rs b/tests/ui/async-await/async-drop/unexpected-sort.rs new file mode 100644 index 0000000000000..659e21eb24119 --- /dev/null +++ b/tests/ui/async-await/async-drop/unexpected-sort.rs @@ -0,0 +1,18 @@ +// Ex-ice: #140484 +//@ edition: 2024 +#![crate_type = "lib"] +#![allow(incomplete_features)] +#![allow(non_camel_case_types)] +#![feature(async_drop)] +use std::future::AsyncDrop; +struct a; +impl Drop for a { //~ ERROR: not all trait items implemented, missing: `drop` + fn b() {} //~ ERROR: method `b` is not a member of trait `Drop` +} +impl AsyncDrop for a { //~ ERROR: not all trait items implemented, missing: `drop` + type c = (); + //~^ ERROR: type `c` is not a member of trait `AsyncDrop` +} +async fn bar() { + a; +} diff --git a/tests/ui/async-await/async-drop/unexpected-sort.stderr b/tests/ui/async-await/async-drop/unexpected-sort.stderr new file mode 100644 index 0000000000000..a6e4f9fd57307 --- /dev/null +++ b/tests/ui/async-await/async-drop/unexpected-sort.stderr @@ -0,0 +1,32 @@ +error[E0407]: method `b` is not a member of trait `Drop` + --> $DIR/unexpected-sort.rs:10:5 + | +LL | fn b() {} + | ^^^^^^^^^ not a member of trait `Drop` + +error[E0437]: type `c` is not a member of trait `AsyncDrop` + --> $DIR/unexpected-sort.rs:13:5 + | +LL | type c = (); + | ^^^^^^^^^^^^ not a member of trait `AsyncDrop` + +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/unexpected-sort.rs:9:1 + | +LL | impl Drop for a { + | ^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `fn drop(&mut self) { todo!() }` + +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/unexpected-sort.rs:12:1 + | +LL | impl AsyncDrop for a { + | ^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `async fn drop(self: Pin<&mut Self>) { todo!() }` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0046, E0407, E0437. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/coercion/retslot-cast.rs b/tests/ui/coercion/retslot-cast.rs index ae500cb15dfdd..a87ac35a8e1e0 100644 --- a/tests/ui/coercion/retslot-cast.rs +++ b/tests/ui/coercion/retslot-cast.rs @@ -1,7 +1,7 @@ #![allow(warnings)] -pub fn fail(x: Option<&(Iterator+Send)>) - -> Option<&Iterator> { +pub fn fail(x: Option<&(dyn Iterator+Send)>) + -> Option<&dyn Iterator> { // This call used to trigger an LLVM assertion because the return // slot had type "Option<&Iterator>"* instead of // "Option<&(Iterator+Send)>"* -- but this now yields a @@ -13,8 +13,8 @@ pub fn fail(x: Option<&(Iterator+Send)>) inner(x) //~ ERROR mismatched types } -pub fn inner(x: Option<&(Iterator+Send)>) - -> Option<&(Iterator+Send)> { +pub fn inner(x: Option<&(dyn Iterator+Send)>) + -> Option<&(dyn Iterator+Send)> { x } diff --git a/tests/ui/coercion/retslot-cast.stderr b/tests/ui/coercion/retslot-cast.stderr index dac21a7f25b2b..a5242c13edd1b 100644 --- a/tests/ui/coercion/retslot-cast.stderr +++ b/tests/ui/coercion/retslot-cast.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types --> $DIR/retslot-cast.rs:13:5 | -LL | -> Option<&Iterator> { - | -------------------------- expected `Option<&dyn Iterator>` because of return type +LL | -> Option<&dyn Iterator> { + | ------------------------------ expected `Option<&dyn Iterator>` because of return type ... LL | inner(x) | ^^^^^^^^ expected trait `Iterator`, found trait `Iterator + Send` diff --git a/tests/ui/coroutine/auxiliary/xcrate.rs b/tests/ui/coroutine/auxiliary/xcrate.rs index 52f188135bd1b..524eaafc75299 100644 --- a/tests/ui/coroutine/auxiliary/xcrate.rs +++ b/tests/ui/coroutine/auxiliary/xcrate.rs @@ -12,7 +12,7 @@ pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> { } } -pub fn bar(t: T) -> Box + Unpin> { +pub fn bar(t: T) -> Box + Unpin> { Box::new( #[coroutine] || { diff --git a/tests/ui/deprecation/deprecation-lint.rs b/tests/ui/deprecation/deprecation-lint.rs index dc11a4d56a2d6..5eda38732c8c9 100644 --- a/tests/ui/deprecation/deprecation-lint.rs +++ b/tests/ui/deprecation/deprecation-lint.rs @@ -71,7 +71,7 @@ mod cross_crate { ::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text } - fn test_method_object(foo: &Trait) { + fn test_method_object(foo: &dyn Trait) { foo.trait_deprecated(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated` foo.trait_deprecated_text(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text } @@ -299,7 +299,7 @@ mod this_crate { ::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text } - fn test_method_object(foo: &Trait) { + fn test_method_object(foo: &dyn Trait) { foo.trait_deprecated(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated` foo.trait_deprecated_text(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text } diff --git a/tests/ui/destructuring-assignment/bad-let-in-destructure.rs b/tests/ui/destructuring-assignment/bad-let-in-destructure.rs new file mode 100644 index 0000000000000..70a0403fc38cb --- /dev/null +++ b/tests/ui/destructuring-assignment/bad-let-in-destructure.rs @@ -0,0 +1,13 @@ +// Regression test for . + +fn main() { + // The following expression gets desugared into something like: + // ``` + // let (lhs,) = x; (let x = 1) = lhs; + // ``` + // This used to ICE since we haven't yet declared the type for `x` when + // checking the first desugared statement, whose RHS resolved to `x` since + // in the AST, the `let` expression was visited first. + (let x = 1,) = x; + //~^ ERROR expected expression, found `let` statement +} diff --git a/tests/ui/destructuring-assignment/bad-let-in-destructure.stderr b/tests/ui/destructuring-assignment/bad-let-in-destructure.stderr new file mode 100644 index 0000000000000..622d714ba2fd4 --- /dev/null +++ b/tests/ui/destructuring-assignment/bad-let-in-destructure.stderr @@ -0,0 +1,10 @@ +error: expected expression, found `let` statement + --> $DIR/bad-let-in-destructure.rs:11:4 + | +LL | (let x = 1,) = x; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: aborting due to 1 previous error + diff --git a/tests/ui/did_you_mean/E0178.rs b/tests/ui/did_you_mean/E0178.rs index 095df640c38f2..cdaddac35a357 100644 --- a/tests/ui/did_you_mean/E0178.rs +++ b/tests/ui/did_you_mean/E0178.rs @@ -1,3 +1,4 @@ +//@ edition:2015 #![allow(bare_trait_objects)] trait Foo {} diff --git a/tests/ui/did_you_mean/E0178.stderr b/tests/ui/did_you_mean/E0178.stderr index 36e4dbdf7c45d..7b69f860381ea 100644 --- a/tests/ui/did_you_mean/E0178.stderr +++ b/tests/ui/did_you_mean/E0178.stderr @@ -1,5 +1,5 @@ error[E0178]: expected a path on the left-hand side of `+` - --> $DIR/E0178.rs:6:8 + --> $DIR/E0178.rs:7:8 | LL | w: &'a Foo + Copy, | ^^^^^^^ @@ -10,7 +10,7 @@ LL | w: &'a (Foo + Copy), | + + error[E0178]: expected a path on the left-hand side of `+` - --> $DIR/E0178.rs:7:8 + --> $DIR/E0178.rs:8:8 | LL | x: &'a Foo + 'a, | ^^^^^^^ @@ -21,7 +21,7 @@ LL | x: &'a (Foo + 'a), | + + error[E0178]: expected a path on the left-hand side of `+` - --> $DIR/E0178.rs:8:8 + --> $DIR/E0178.rs:9:8 | LL | y: &'a mut Foo + 'a, | ^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | y: &'a mut (Foo + 'a), | + + error[E0178]: expected a path on the left-hand side of `+` - --> $DIR/E0178.rs:9:8 + --> $DIR/E0178.rs:10:8 | LL | z: fn() -> Foo + 'a, | ^^^^^^^^^^^----- diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs index b7470864a30db..eff431f4665f9 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs @@ -1,3 +1,4 @@ +//@ edition: 2015 #![allow(bare_trait_objects)] fn main() { diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 57dbc79a0fda2..b051d181ad80a 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -1,5 +1,5 @@ error[E0178]: expected a path on the left-hand side of `+` - --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12 + --> $DIR/trait-object-reference-without-parens-suggestion.rs:5:12 | LL | let _: &Copy + 'static; | ^^^^^ @@ -10,7 +10,7 @@ LL | let _: &(Copy + 'static); | + + error[E0178]: expected a path on the left-hand side of `+` - --> $DIR/trait-object-reference-without-parens-suggestion.rs:6:12 + --> $DIR/trait-object-reference-without-parens-suggestion.rs:7:12 | LL | let _: &'static Copy + 'static; | ^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | let _: &'static (Copy + 'static); | + + error[E0038]: the trait `Copy` is not dyn compatible - --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:13 + --> $DIR/trait-object-reference-without-parens-suggestion.rs:5:13 | LL | let _: &Copy + 'static; | ^^^^ `Copy` is not dyn compatible @@ -31,7 +31,7 @@ LL | let _: &Copy + 'static; for more information, visit error[E0038]: the trait `Copy` is not dyn compatible - --> $DIR/trait-object-reference-without-parens-suggestion.rs:6:21 + --> $DIR/trait-object-reference-without-parens-suggestion.rs:7:21 | LL | let _: &'static Copy + 'static; | ^^^^ `Copy` is not dyn compatible diff --git a/tests/ui/dyn-drop/dyn-drop.rs b/tests/ui/dyn-drop/dyn-drop.rs index e1668a3f188d5..f336949d2cb74 100644 --- a/tests/ui/dyn-drop/dyn-drop.rs +++ b/tests/ui/dyn-drop/dyn-drop.rs @@ -1,8 +1,7 @@ #![deny(dyn_drop)] -#![allow(bare_trait_objects)] fn foo(_: Box) {} //~ ERROR fn bar(_: &dyn Drop) {} //~ERROR -fn baz(_: *mut Drop) {} //~ ERROR +fn baz(_: *mut dyn Drop) {} //~ ERROR struct Foo { _x: Box //~ ERROR } diff --git a/tests/ui/dyn-drop/dyn-drop.stderr b/tests/ui/dyn-drop/dyn-drop.stderr index 1b1dbc4d12d4c..8210d8a4c48f9 100644 --- a/tests/ui/dyn-drop/dyn-drop.stderr +++ b/tests/ui/dyn-drop/dyn-drop.stderr @@ -1,5 +1,5 @@ error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped - --> $DIR/dyn-drop.rs:3:19 + --> $DIR/dyn-drop.rs:2:19 | LL | fn foo(_: Box) {} | ^^^^ @@ -11,25 +11,25 @@ LL | #![deny(dyn_drop)] | ^^^^^^^^ error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped - --> $DIR/dyn-drop.rs:4:16 + --> $DIR/dyn-drop.rs:3:16 | LL | fn bar(_: &dyn Drop) {} | ^^^^ error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped - --> $DIR/dyn-drop.rs:5:16 + --> $DIR/dyn-drop.rs:4:20 | -LL | fn baz(_: *mut Drop) {} - | ^^^^ +LL | fn baz(_: *mut dyn Drop) {} + | ^^^^ error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped - --> $DIR/dyn-drop.rs:7:15 + --> $DIR/dyn-drop.rs:6:15 | LL | _x: Box | ^^^^ error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped - --> $DIR/dyn-drop.rs:14:16 + --> $DIR/dyn-drop.rs:13:16 | LL | type T = dyn Drop; | ^^^^ diff --git a/tests/ui/editions/async-block-2015.rs b/tests/ui/editions/async-block-2015.rs index a079b4aad911e..21549f059de26 100644 --- a/tests/ui/editions/async-block-2015.rs +++ b/tests/ui/editions/async-block-2015.rs @@ -1,3 +1,4 @@ +//@ edition:2015 async fn foo() { //~^ ERROR `async fn` is not permitted in Rust 2015 //~| NOTE to use `async fn`, switch to Rust 2018 or later diff --git a/tests/ui/editions/async-block-2015.stderr b/tests/ui/editions/async-block-2015.stderr index 574bcacc1cfa7..139df1758cc43 100644 --- a/tests/ui/editions/async-block-2015.stderr +++ b/tests/ui/editions/async-block-2015.stderr @@ -1,5 +1,5 @@ error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/async-block-2015.rs:1:1 + --> $DIR/async-block-2015.rs:2:1 | LL | async fn foo() { | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -8,7 +8,7 @@ LL | async fn foo() { = note: for more on editions, read https://doc.rust-lang.org/edition-guide error: expected identifier, found keyword `let` - --> $DIR/async-block-2015.rs:11:9 + --> $DIR/async-block-2015.rs:12:9 | LL | let y = async { | ----- `async` blocks are only allowed in Rust 2018 or later @@ -19,7 +19,7 @@ LL | let x = 42; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error: expected identifier, found `42` - --> $DIR/async-block-2015.rs:19:9 + --> $DIR/async-block-2015.rs:20:9 | LL | let z = async { | ----- `async` blocks are only allowed in Rust 2018 or later @@ -30,7 +30,7 @@ LL | 42 = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0422]: cannot find struct, variant or union type `async` in this scope - --> $DIR/async-block-2015.rs:7:13 + --> $DIR/async-block-2015.rs:8:13 | LL | let x = async {}; | ^^^^^ `async` blocks are only allowed in Rust 2018 or later diff --git a/tests/ui/ergonomic-clones/async/edition-2015.rs b/tests/ui/ergonomic-clones/async/edition-2015.rs index d3b2071b9f91f..7883124942902 100644 --- a/tests/ui/ergonomic-clones/async/edition-2015.rs +++ b/tests/ui/ergonomic-clones/async/edition-2015.rs @@ -1,3 +1,4 @@ +//@ edition:2015 #![feature(ergonomic_clones)] #![allow(incomplete_features)] diff --git a/tests/ui/ergonomic-clones/async/edition-2015.stderr b/tests/ui/ergonomic-clones/async/edition-2015.stderr index b218e6b242e19..8de90f4bfd3c9 100644 --- a/tests/ui/ergonomic-clones/async/edition-2015.stderr +++ b/tests/ui/ergonomic-clones/async/edition-2015.stderr @@ -1,5 +1,5 @@ error: `async use` blocks are only allowed in Rust 2018 or later - --> $DIR/edition-2015.rs:5:5 + --> $DIR/edition-2015.rs:6:5 | LL | async use {}; | ^^^^^^^^^ diff --git a/tests/ui/error-codes/E0657.rs b/tests/ui/error-codes/E0657.rs index 212c1d9e581a2..f046788153d58 100644 --- a/tests/ui/error-codes/E0657.rs +++ b/tests/ui/error-codes/E0657.rs @@ -7,7 +7,7 @@ impl<'a> Lt<'a> for () {} impl Id for T {} fn free_fn_capture_hrtb_in_impl_trait() - -> Box Id>> + -> Box Id>> //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type { Box::new(()) @@ -16,7 +16,7 @@ fn free_fn_capture_hrtb_in_impl_trait() struct Foo; impl Foo { fn impl_fn_capture_hrtb_in_impl_trait() - -> Box Id>> + -> Box Id>> //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type { Box::new(()) diff --git a/tests/ui/error-codes/E0657.stderr b/tests/ui/error-codes/E0657.stderr index c539007cdcf19..c9dfc9eb9069d 100644 --- a/tests/ui/error-codes/E0657.stderr +++ b/tests/ui/error-codes/E0657.stderr @@ -1,26 +1,26 @@ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type - --> $DIR/E0657.rs:10:31 + --> $DIR/E0657.rs:10:35 | -LL | -> Box Id>> - | ^^ +LL | -> Box Id>> + | ^^ | note: lifetime declared here - --> $DIR/E0657.rs:10:16 + --> $DIR/E0657.rs:10:20 | -LL | -> Box Id>> - | ^^ +LL | -> Box Id>> + | ^^ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type - --> $DIR/E0657.rs:19:35 + --> $DIR/E0657.rs:19:39 | -LL | -> Box Id>> - | ^^ +LL | -> Box Id>> + | ^^ | note: lifetime declared here - --> $DIR/E0657.rs:19:20 + --> $DIR/E0657.rs:19:24 | -LL | -> Box Id>> - | ^^ +LL | -> Box Id>> + | ^^ error: aborting due to 2 previous errors diff --git a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs index 69a4c13530bd3..d6bb64662270e 100644 --- a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs +++ b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs @@ -1,3 +1,4 @@ +//@ edition:2015 trait MyIterator : Iterator {} fn main() { diff --git a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr index 24f00cfa6be91..7f3022c29233e 100644 --- a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr +++ b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr @@ -1,5 +1,5 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/dynless-turbofish-e0191-issue-91997.rs:4:13 + --> $DIR/dynless-turbofish-e0191-issue-91997.rs:5:13 | LL | let _ = MyIterator::next; | ^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | let _ = ::next; | ++++ + error[E0191]: the value of the associated type `Item` in `Iterator` must be specified - --> $DIR/dynless-turbofish-e0191-issue-91997.rs:4:13 + --> $DIR/dynless-turbofish-e0191-issue-91997.rs:5:13 | LL | let _ = MyIterator::next; | ^^^^^^^^^^ help: specify the associated type: `MyIterator::` diff --git a/tests/ui/expr/scope.rs b/tests/ui/expr/scope.rs index 3a1c8b87da8fa..b059e43de9ee2 100644 --- a/tests/ui/expr/scope.rs +++ b/tests/ui/expr/scope.rs @@ -1,3 +1,4 @@ +//@ edition:2015 //@ run-pass // Regression test for issue #762 diff --git a/tests/ui/imports/import-glob-crate.rs b/tests/ui/imports/import-glob-crate.rs index 0a2ca6ef2c315..ee0679318766b 100644 --- a/tests/ui/imports/import-glob-crate.rs +++ b/tests/ui/imports/import-glob-crate.rs @@ -1,3 +1,4 @@ +//@ edition: 2015 //@ run-pass use std::mem::*; diff --git a/tests/ui/intrinsics/non-integer-atomic.rs b/tests/ui/intrinsics/non-integer-atomic.rs index dd129e5594510..5464bf747faed 100644 --- a/tests/ui/intrinsics/non-integer-atomic.rs +++ b/tests/ui/intrinsics/non-integer-atomic.rs @@ -8,7 +8,7 @@ use std::intrinsics::{self, AtomicOrdering}; #[derive(Copy, Clone)] pub struct Foo(i64); -pub type Bar = &'static Fn(); +pub type Bar = &'static dyn Fn(); pub type Quux = [u8; 100]; pub unsafe fn test_bool_load(p: &mut bool, v: bool) { diff --git a/tests/ui/macros/auxiliary/borrowck-error-in-macro.rs b/tests/ui/macros/auxiliary/borrowck-error-in-macro.rs new file mode 100644 index 0000000000000..2d5f2bda2edfe --- /dev/null +++ b/tests/ui/macros/auxiliary/borrowck-error-in-macro.rs @@ -0,0 +1,10 @@ +#[macro_export] +macro_rules! ice { + () => { + fn main() { + let d = &mut 0; + let c = || *d += 1; + c(); + } + }; +} diff --git a/tests/ui/macros/borrowck-error-in-macro.rs b/tests/ui/macros/borrowck-error-in-macro.rs new file mode 100644 index 0000000000000..fe75188efd203 --- /dev/null +++ b/tests/ui/macros/borrowck-error-in-macro.rs @@ -0,0 +1,8 @@ +//@ aux-build: borrowck-error-in-macro.rs +//@ error-pattern: a call in this macro requires a mutable binding due to mutable borrow of `d` +//FIXME: remove error-pattern (see #141896) + +extern crate borrowck_error_in_macro as a; + +a::ice! {} +//~^ ERROR cannot borrow value as mutable, as it is not declared as mutable diff --git a/tests/ui/macros/borrowck-error-in-macro.stderr b/tests/ui/macros/borrowck-error-in-macro.stderr new file mode 100644 index 0000000000000..ec0302ee287ec --- /dev/null +++ b/tests/ui/macros/borrowck-error-in-macro.stderr @@ -0,0 +1,19 @@ +error[E0596]: cannot borrow value as mutable, as it is not declared as mutable + --> $DIR/borrowck-error-in-macro.rs:7:1 + | +LL | a::ice! {} + | ^^^^^^^^^^ + | | + | cannot borrow as mutable + | a call in this macro requires a mutable binding due to mutable borrow of `d` + | + = note: this error originates in the macro `a::ice` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider changing this to be mutable + --> $DIR/auxiliary/borrowck-error-in-macro.rs:6:17 + | +LL | let mut c = || *d += 1; + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0596`.