diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs index 12b0d5ec4963b..f35aba7d4fe1e 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs @@ -47,7 +47,8 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] { fn make_file_info(source_file: &SourceFile, embed_source: bool) -> Option { let has_md5 = source_file.src_hash.kind == SourceFileHashAlgorithm::Md5; - let has_source = embed_source && source_file.src.is_some(); + let has_source = embed_source + && (source_file.src.is_some() || source_file.external_src.read().get_source().is_some()); if !has_md5 && !has_source { return None; @@ -62,6 +63,8 @@ fn make_file_info(source_file: &SourceFile, embed_source: bool) -> Option { - let file_id = self.add_source_file(&file); + let file_id = self.add_source_file(tcx, &file); let line_pos = file.lines()[line]; let col = file.relative_position(span.lo()) - line_pos; (file_id, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1) } - Err(file) => (self.add_source_file(&file), 0, 0), + Err(file) => (self.add_source_file(tcx, &file), 0, 0), } } - pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId { + pub(crate) fn add_source_file(&mut self, tcx: TyCtxt<'_>, source_file: &SourceFile) -> FileId { let cache_key = (source_file.stable_id, source_file.src_hash); *self.created_files.entry(cache_key).or_insert_with(|| { + if self.embed_source && source_file.src.is_none() { + tcx.sess.source_map().ensure_source_file_source_present(source_file); + } let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program; let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 2f5e5666ea675..9a9e8287e787f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -2,7 +2,6 @@ use std::borrow::Cow; use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; use std::path::PathBuf; -use std::sync::Arc; use std::{assert_matches, iter, ptr}; use libc::{c_longlong, c_uint}; @@ -607,8 +606,16 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi }; let hash_value = hex_encode(source_file.src_hash.hash_bytes()); - let source = - cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref()); + let mut source = None; + let external_src; + if cx.sess().opts.unstable_opts.embed_source { + source = source_file.src.as_deref().map(String::as_str); + if source.is_none() { + cx.tcx.sess.source_map().ensure_source_file_source_present(source_file); + external_src = source_file.external_src.read(); + source = external_src.get_source(); + } + } create_file(DIB(cx), &file_name, &directory, &hash_value, hash_kind, source) } @@ -626,7 +633,7 @@ fn create_file<'ll>( directory: &str, hash_value: &str, hash_kind: llvm::ChecksumKind, - source: Option<&Arc>, + source: Option<&str>, ) -> &'ll DIFile { unsafe { llvm::LLVMRustDIBuilderCreateFile( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b1927e190f033..03b7adfd3eabf 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -10,7 +10,7 @@ use std::cmp::Ordering; use std::env::VarError; use std::ffi::OsStr; use std::hash::{Hash, Hasher}; -use std::marker::{PhantomData, PointeeSized}; +use std::marker::PointeeSized; use std::ops::{Bound, Deref}; use std::sync::{Arc, OnceLock}; use std::{fmt, iter, mem}; @@ -539,36 +539,14 @@ pub struct FreeRegionInfo { /// This struct should only be created by `create_def`. #[derive(Copy, Clone)] -pub struct TyCtxtFeed<'tcx, KEY: Copy> { +pub struct TyCtxtFeed<'tcx, K: Copy> { pub tcx: TyCtxt<'tcx>, // Do not allow direct access, as downstream code must not mutate this field. - key: KEY, + key: K, } -/// Never return a `Feed` from a query. Only queries that create a `DefId` are -/// allowed to feed queries for that `DefId`. -impl !HashStable for TyCtxtFeed<'_, KEY> {} - -/// The same as `TyCtxtFeed`, but does not contain a `TyCtxt`. -/// Use this to pass around when you have a `TyCtxt` elsewhere. -/// Just an optimization to save space and not store hundreds of -/// `TyCtxtFeed` in the resolver. -#[derive(Copy, Clone)] -pub struct Feed<'tcx, KEY: Copy> { - _tcx: PhantomData>, - // Do not allow direct access, as downstream code must not mutate this field. - key: KEY, -} - -/// Never return a `Feed` from a query. Only queries that create a `DefId` are -/// allowed to feed queries for that `DefId`. -impl !HashStable for Feed<'_, KEY> {} - -impl fmt::Debug for Feed<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.key.fmt(f) - } -} +/// Only queries that create a `DefId` are allowed to feed queries for that `DefId`. +impl !HashStable for TyCtxtFeed<'_, K> {} /// Some workarounds to use cases that cannot use `create_def`. /// Do not add new ways to create `TyCtxtFeed` without consulting @@ -622,28 +600,11 @@ impl<'tcx> TyCtxt<'tcx> { } } -impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { +impl<'tcx, K: Copy> TyCtxtFeed<'tcx, K> { #[inline(always)] - pub fn key(&self) -> KEY { + pub fn key(&self) -> K { self.key } - - #[inline(always)] - pub fn downgrade(self) -> Feed<'tcx, KEY> { - Feed { _tcx: PhantomData, key: self.key } - } -} - -impl<'tcx, KEY: Copy> Feed<'tcx, KEY> { - #[inline(always)] - pub fn key(&self) -> KEY { - self.key - } - - #[inline(always)] - pub fn upgrade(self, tcx: TyCtxt<'tcx>) -> TyCtxtFeed<'tcx, KEY> { - TyCtxtFeed { tcx, key: self.key } - } } impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 914fb43147156..74cad5acfc6fa 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -83,7 +83,7 @@ pub use self::consts::{ const_lit_matches_ty, }; pub use self::context::{ - CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, + CtxtInterners, CurrentGcx, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, }; pub use self::fold::*; pub use self::instance::{Instance, InstanceKind, ReifyReason}; diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index c17e18ac664ed..89656c75b5d1f 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -76,6 +76,14 @@ const MAX_COST: u8 = 100; impl<'tcx> crate::MirPass<'tcx> for JumpThreading { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + if sess.target.is_like_gpu { + // Jump threading can duplicate calls in control-flow. + // This leads to incorrect code when done for so called "convergent" operations on GPU + // targets, similar to how inline assembly cannot be duplicated on all targets. + // Conservatively prevent this by disabling the pass. + // See also issue #137086. + return false; + } sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 5766d25bc86ce..173a92fdbf759 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -115,7 +115,7 @@ pub(crate) fn lex_token_trees<'psess, 'src>( Err(errs) => { // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch // because the delimiter mismatch is more likely to be the root cause of error - unmatched_closing_delims.extend(errs); + unmatched_closing_delims.push(errs); Err(unmatched_closing_delims) } } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index bce298118b7a7..757cd755bf65f 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -14,7 +14,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { pub(super) fn lex_token_trees( &mut self, is_delimited: bool, - ) -> Result<(Spacing, TokenStream), Vec>> { + ) -> Result<(Spacing, TokenStream), Diag<'psess>> { // Move past the opening delimiter. let open_spacing = self.bump_minimal(); @@ -35,11 +35,11 @@ impl<'psess, 'src> Lexer<'psess, 'src> { return if is_delimited { Ok((open_spacing, TokenStream::new(buf))) } else { - Err(vec![self.close_delim_err(delim)]) + Err(self.close_delim_err(delim)) }; } else if self.token.kind == token::Eof { return if is_delimited { - Err(vec![self.eof_err()]) + Err(self.eof_err()) } else { Ok((open_spacing, TokenStream::new(buf))) }; @@ -54,7 +54,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { fn lex_token_tree_open_delim( &mut self, open_delim: Delimiter, - ) -> Result>> { + ) -> Result> { // The span for beginning of the delimited section. let pre_span = self.token.span; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 1afbbef2eeaf8..4c307e8a6a3d7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -35,9 +35,10 @@ use crate::imports::{ImportData, ImportKind, OnUnknownData}; use crate::macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; use crate::ref_mut::CmCell; use crate::{ - BindingKey, Decl, DeclData, DeclKind, ExternModule, ExternPreludeEntry, Finalize, IdentKey, - LocalModule, MacroData, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, - Resolver, Segment, Used, VisResolutionError, errors, + BindingKey, Decl, DeclData, DeclKind, DelayedVisResolutionError, ExternModule, + ExternPreludeEntry, Finalize, IdentKey, LocalModule, MacroData, Module, ModuleKind, + ModuleOrUniformRoot, ParentScope, PathResult, Res, Resolver, Segment, Used, VisResolutionError, + errors, }; impl<'ra, 'tcx> Resolver<'ra, 'tcx> { @@ -237,6 +238,111 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } + pub(crate) fn try_resolve_visibility( + &mut self, + parent_scope: &ParentScope<'ra>, + vis: &ast::Visibility, + finalize: bool, + ) -> Result { + match vis.kind { + ast::VisibilityKind::Public => Ok(Visibility::Public), + ast::VisibilityKind::Inherited => { + Ok(match parent_scope.module.kind { + // Any inherited visibility resolved directly inside an enum or trait + // (i.e. variants, fields, and trait items) inherits from the visibility + // of the enum or trait. + ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _) => { + self.tcx.visibility(def_id).expect_local() + } + // Otherwise, the visibility is restricted to the nearest parent `mod` item. + _ => Visibility::Restricted( + parent_scope.module.nearest_parent_mod().expect_local(), + ), + }) + } + ast::VisibilityKind::Restricted { ref path, id, .. } => { + // For visibilities we are not ready to provide correct implementation of "uniform + // paths" right now, so on 2018 edition we only allow module-relative paths for now. + // On 2015 edition visibilities are resolved as crate-relative by default, + // so we are prepending a root segment if necessary. + let ident = path.segments.get(0).expect("empty path in visibility").ident; + let crate_root = if ident.is_path_segment_keyword() { + None + } else if ident.span.is_rust_2015() { + Some(Segment::from_ident(Ident::new( + kw::PathRoot, + path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()), + ))) + } else { + return Err(VisResolutionError::Relative2018( + ident.span, + path.as_ref().clone(), + )); + }; + let segments = crate_root + .into_iter() + .chain(path.segments.iter().map(|seg| seg.into())) + .collect::>(); + let expected_found_error = |res| { + Err(VisResolutionError::ExpectedFound( + path.span, + Segment::names_to_string(&segments), + res, + )) + }; + match self.cm().resolve_path( + &segments, + None, + parent_scope, + finalize.then(|| Finalize::new(id, path.span)), + None, + None, + ) { + PathResult::Module(ModuleOrUniformRoot::Module(module)) => { + let res = module.res().expect("visibility resolved to unnamed block"); + if module.is_normal() { + match res { + Res::Err => { + if finalize { + self.record_partial_res(id, PartialRes::new(res)); + } + Ok(Visibility::Public) + } + _ => { + let vis = Visibility::Restricted(res.def_id()); + if self.is_accessible_from(vis, parent_scope.module) { + if finalize { + self.record_partial_res(id, PartialRes::new(res)); + } + Ok(vis.expect_local()) + } else { + Err(VisResolutionError::AncestorOnly(path.span)) + } + } + } + } else { + expected_found_error(res) + } + } + PathResult::Module(..) => Err(VisResolutionError::ModuleOnly(path.span)), + PathResult::NonModule(partial_res) => { + expected_found_error(partial_res.expect_full_res()) + } + PathResult::Failed { + span, label, suggestion, message, segment_name, .. + } => Err(VisResolutionError::FailedToResolve( + span, + segment_name, + label, + suggestion, + message, + )), + PathResult::Indeterminate => Err(VisResolutionError::Indeterminate(path.span)), + } + } + } + } + pub(crate) fn build_reduced_graph_external(&self, module: ExternModule<'ra>) { let def_id = module.def_id(); let children = self.tcx.module_children(def_id); @@ -364,106 +470,15 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } fn resolve_visibility(&mut self, vis: &ast::Visibility) -> Visibility { - self.try_resolve_visibility(vis, true).unwrap_or_else(|err| { - self.r.report_vis_error(err); - Visibility::Public - }) - } - - fn try_resolve_visibility<'ast>( - &mut self, - vis: &'ast ast::Visibility, - finalize: bool, - ) -> Result> { - let parent_scope = &self.parent_scope; - match vis.kind { - ast::VisibilityKind::Public => Ok(Visibility::Public), - ast::VisibilityKind::Inherited => { - Ok(match self.parent_scope.module.kind { - // Any inherited visibility resolved directly inside an enum or trait - // (i.e. variants, fields, and trait items) inherits from the visibility - // of the enum or trait. - ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _) => { - self.r.tcx.visibility(def_id).expect_local() - } - // Otherwise, the visibility is restricted to the nearest parent `mod` item. - _ => Visibility::Restricted( - self.parent_scope.module.nearest_parent_mod().expect_local(), - ), - }) - } - ast::VisibilityKind::Restricted { ref path, id, .. } => { - // For visibilities we are not ready to provide correct implementation of "uniform - // paths" right now, so on 2018 edition we only allow module-relative paths for now. - // On 2015 edition visibilities are resolved as crate-relative by default, - // so we are prepending a root segment if necessary. - let ident = path.segments.get(0).expect("empty path in visibility").ident; - let crate_root = if ident.is_path_segment_keyword() { - None - } else if ident.span.is_rust_2015() { - Some(Segment::from_ident(Ident::new( - kw::PathRoot, - path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()), - ))) - } else { - return Err(VisResolutionError::Relative2018(ident.span, path)); - }; - - let segments = crate_root - .into_iter() - .chain(path.segments.iter().map(|seg| seg.into())) - .collect::>(); - let expected_found_error = |res| { - Err(VisResolutionError::ExpectedFound( - path.span, - Segment::names_to_string(&segments), - res, - )) - }; - match self.r.cm().resolve_path( - &segments, - None, - parent_scope, - finalize.then(|| Finalize::new(id, path.span)), - None, - None, - ) { - PathResult::Module(ModuleOrUniformRoot::Module(module)) => { - let res = module.res().expect("visibility resolved to unnamed block"); - if finalize { - self.r.record_partial_res(id, PartialRes::new(res)); - } - if module.is_normal() { - match res { - Res::Err => Ok(Visibility::Public), - _ => { - let vis = Visibility::Restricted(res.def_id()); - if self.r.is_accessible_from(vis, parent_scope.module) { - Ok(vis.expect_local()) - } else { - Err(VisResolutionError::AncestorOnly(path.span)) - } - } - } - } else { - expected_found_error(res) - } - } - PathResult::Module(..) => Err(VisResolutionError::ModuleOnly(path.span)), - PathResult::NonModule(partial_res) => { - expected_found_error(partial_res.expect_full_res()) - } - PathResult::Failed { - span, label, suggestion, message, segment_name, .. - } => Err(VisResolutionError::FailedToResolve( - span, - segment_name, - label, - suggestion, - message, - )), - PathResult::Indeterminate => Err(VisResolutionError::Indeterminate(path.span)), - } + match self.r.try_resolve_visibility(&self.parent_scope, vis, true) { + Ok(vis) => vis, + Err(error) => { + self.r.delayed_vis_resolution_errors.push(DelayedVisResolutionError { + vis: vis.clone(), + parent_scope: self.parent_scope, + error, + }); + Visibility::Public } } } @@ -906,7 +921,8 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { // correct visibilities for unnamed field placeholders specifically, so the // constructor visibility should still be determined correctly. let field_vis = self - .try_resolve_visibility(&field.vis, false) + .r + .try_resolve_visibility(&self.parent_scope, &field.vis, false) .unwrap_or(Visibility::Public); if ctor_vis.greater_than(field_vis, self.r.tcx) { ctor_vis = field_vis; @@ -1341,9 +1357,10 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { let vis = match item.kind { // Visibilities must not be resolved non-speculatively twice // and we already resolved this one as a `fn` item visibility. - ItemKind::Fn(..) => { - self.try_resolve_visibility(&item.vis, false).unwrap_or(Visibility::Public) - } + ItemKind::Fn(..) => self + .r + .try_resolve_visibility(&self.parent_scope, &item.vis, false) + .unwrap_or(Visibility::Public), _ => self.resolve_visibility(&item.vis), }; if !vis.is_public() { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index b60bfc3be4ebc..7e1dd19167899 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,4 +1,5 @@ // ignore-tidy-filelength +use std::mem; use std::ops::ControlFlow; use itertools::Itertools as _; @@ -48,10 +49,10 @@ use crate::imports::{Import, ImportKind}; use crate::late::{DiagMetadata, PatternSource, Rib}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind, - Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, LateDecl, MacroRulesScope, - Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, - ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, VisResolutionError, - errors as errs, path_names_to_string, + DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, + LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, + PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, + VisResolutionError, errors as errs, path_names_to_string, }; /// A vector of spans and replacements, a message and applicability. @@ -137,6 +138,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub(crate) fn report_errors(&mut self, krate: &Crate) { + self.report_delayed_vis_resolution_errors(); self.report_with_use_injections(krate); for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { @@ -171,16 +173,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let mut reported_spans = FxHashSet::default(); - for error in std::mem::take(&mut self.privacy_errors) { + for error in mem::take(&mut self.privacy_errors) { if reported_spans.insert(error.dedup_span) { self.report_privacy_error(&error); } } } + fn report_delayed_vis_resolution_errors(&mut self) { + for DelayedVisResolutionError { vis, parent_scope, error } in + mem::take(&mut self.delayed_vis_resolution_errors) + { + match self.try_resolve_visibility(&parent_scope, &vis, true) { + Ok(_) => self.report_vis_error(error), + Err(error) => self.report_vis_error(error), + }; + } + } + fn report_with_use_injections(&mut self, krate: &Crate) { for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in - std::mem::take(&mut self.use_injections) + mem::take(&mut self.use_injections) { let (span, found_use) = if let Some(def_id) = def_id.as_local() { UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)) @@ -1137,7 +1150,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn report_vis_error( &mut self, - vis_resolution_error: VisResolutionError<'_>, + vis_resolution_error: VisResolutionError, ) -> ErrorGuaranteed { match vis_resolution_error { VisResolutionError::Relative2018(span, path) => { @@ -1146,7 +1159,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { path_span: path.span, // intentionally converting to String, as the text would also be used as // in suggestion context - path_str: pprust::path_to_string(path), + path_str: pprust::path_to_string(&path), }) } VisResolutionError::AncestorOnly(span) => { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c733299154ab7..b15e4b1b72774 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -337,8 +337,9 @@ enum ResolutionError<'ra> { BindingInNeverPattern, } -enum VisResolutionError<'a> { - Relative2018(Span, &'a ast::Path), +#[derive(Debug)] +enum VisResolutionError { + Relative2018(Span, ast::Path), AncestorOnly(Span), FailedToResolve(Span, Symbol, String, Option, String), ExpectedFound(Span, String, Res), @@ -1004,6 +1005,13 @@ struct UseError<'a> { is_call: bool, } +#[derive(Debug)] +struct DelayedVisResolutionError<'ra> { + vis: ast::Visibility, + parent_scope: ParentScope<'ra>, + error: VisResolutionError, +} + #[derive(Clone, Copy, PartialEq, Debug)] enum AmbiguityKind { BuiltinAttr, @@ -1364,6 +1372,8 @@ pub struct Resolver<'ra, 'tcx> { issue_145575_hack_applied: bool = false, /// `use` injections are delayed for better placement and deduplication. use_injections: Vec> = Vec::new(), + /// Visibility path resolution failures are delayed until all modules are collected. + delayed_vis_resolution_errors: Vec> = Vec::new(), /// Crate-local macro expanded `macro_export` referred to by a module-relative path. macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(), diff --git a/library/stdarch/crates/core_arch/src/amdgpu/intrinsic_is_convergent.md b/library/stdarch/crates/core_arch/src/amdgpu/intrinsic_is_convergent.md new file mode 100644 index 0000000000000..1bc8899d33e0a --- /dev/null +++ b/library/stdarch/crates/core_arch/src/amdgpu/intrinsic_is_convergent.md @@ -0,0 +1,6 @@ +This intrinsic does not behave like a normal function call; it is a "[convergent]" operation and as such has non-standard control-flow effects which need special treatment by the language. +Rust currently does not properly support convergent operations. +This operation is hence provided on a best-effort basis. +Using it may result in incorrect code under some circumstances. + +[convergent]: https://llvm.org/docs/ConvergentOperations.html diff --git a/library/stdarch/crates/core_arch/src/amdgpu/mod.rs b/library/stdarch/crates/core_arch/src/amdgpu/mod.rs index 40274e4d794fd..374f582696947 100644 --- a/library/stdarch/crates/core_arch/src/amdgpu/mod.rs +++ b/library/stdarch/crates/core_arch/src/amdgpu/mod.rs @@ -244,6 +244,8 @@ pub fn wavefrontsize() -> u32 { /// Synchronize all wavefronts in a workgroup. /// /// Each wavefronts in a workgroup waits at the barrier until all wavefronts in the workgroup arrive at a barrier. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn s_barrier() { @@ -253,6 +255,8 @@ pub fn s_barrier() { /// Signal a specific barrier type. /// /// Only for non-named barriers. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn s_barrier_signal() { @@ -265,6 +269,8 @@ pub unsafe fn s_barrier_signal() { /// Provides access to the s_barrier_signal_first instruction; /// additionally ensures that the result value is valid even when /// the intrinsic is used from a wavefront that is not running in a workgroup. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn s_barrier_signal_isfirst() -> bool { @@ -274,6 +280,8 @@ pub unsafe fn s_barrier_signal_isfirst() -> bool { /// Wait for a specific barrier type. /// /// Only for non-named barriers. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn s_barrier_wait() { @@ -283,6 +291,8 @@ pub unsafe fn s_barrier_wait() { /// Get the state of a specific barrier type. /// /// The `barrier_type` argument must be uniform, otherwise behavior is undefined. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn s_get_barrier_state() -> u32 { @@ -292,6 +302,8 @@ pub unsafe fn s_get_barrier_state() -> u32 { /// A barrier for only the threads within the current wavefront. /// /// Does not result in an instruction but restricts the compiler. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_barrier() { @@ -315,6 +327,8 @@ pub fn wave_barrier() { /// - 0x0100: All DS read instructions may be scheduled across `sched_barrier`. /// - 0x0200: All DS write instructions may be scheduled across `sched_barrier`. /// - 0x0400: All Transcendental (e.g. V_EXP) instructions may be scheduled across `sched_barrier`. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn sched_barrier() { @@ -345,6 +359,8 @@ pub unsafe fn sched_barrier() { /// // 5 MFMA /// sched_group_barrier::<8, 5, 0>() /// ``` +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn sched_group_barrier() { @@ -366,6 +382,8 @@ pub fn s_sleep() { /// Stop execution of the kernel. /// /// This usually signals an error state. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn s_sethalt() -> ! { @@ -407,6 +425,8 @@ pub fn mbcnt_hi(value: u32, init: u32) -> u32 { /// Returns a bitfield (`u32` or `u64`) containing the result of its i1 argument /// in all active lanes, and zero in all inactive lanes. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn ballot(b: bool) -> u64 { @@ -419,6 +439,8 @@ pub fn ballot(b: bool) -> u64 { /// While [`ballot`] converts a `bool` to a mask, `inverse_ballot` converts a mask back to a `bool`. /// This means `inverse_ballot(ballot(b)) == b`. /// The inverse of `ballot(inverse_ballot(value)) ~= value` is not always true as inactive lanes are set to zero by `ballot`. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn inverse_ballot(value: u64) -> bool { @@ -433,6 +455,8 @@ pub fn inverse_ballot(value: u64) -> bool { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_umin(value: u32) -> u32 { @@ -447,6 +471,8 @@ pub fn wave_reduce_umin(value: u32) -> u32 { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_min(value: i32) -> i32 { @@ -462,6 +488,8 @@ pub fn wave_reduce_min(value: i32) -> i32 { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_umax(value: u32) -> u32 { @@ -476,6 +504,8 @@ pub fn wave_reduce_umax(value: u32) -> u32 { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_max(value: i32) -> i32 { @@ -491,6 +521,8 @@ pub fn wave_reduce_max(value: i32) -> i32 { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_add(value: u32) -> u32 { @@ -506,6 +538,8 @@ pub fn wave_reduce_add(value: u32) -> u32 { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_and(value: u32) -> u32 { @@ -520,6 +554,8 @@ pub fn wave_reduce_and(value: u32) -> u32 { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_or(value: u32) -> u32 { @@ -534,6 +570,8 @@ pub fn wave_reduce_or(value: u32) -> u32 { /// - 2: DPP /// /// If target does not support the DPP operations (e.g. gfx6/7), reduction will be performed using default iterative strategy. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn wave_reduce_xor(value: u32) -> u32 { @@ -544,12 +582,16 @@ pub fn wave_reduce_xor(value: u32) -> u32 { // The following intrinsics can have multiple sizes /// Get `value` from the first active lane in the wavefront. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn readfirstlane_u32(value: u32) -> u32 { llvm_readfirstlane_u32(value) } /// Get `value` from the first active lane in the wavefront. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn readfirstlane_u64(value: u64) -> u64 { @@ -559,6 +601,8 @@ pub fn readfirstlane_u64(value: u64) -> u64 { /// /// The lane argument must be uniform across the currently active threads /// of the current wavefront. Otherwise, the result is undefined. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn readlane_u32(value: u32, lane: u32) -> u32 { @@ -568,6 +612,8 @@ pub unsafe fn readlane_u32(value: u32, lane: u32) -> u32 { /// /// The lane argument must be uniform across the currently active threads /// of the current wavefront. Otherwise, the result is undefined. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn readlane_u64(value: u64, lane: u32) -> u64 { @@ -582,6 +628,8 @@ pub unsafe fn readlane_u64(value: u64, lane: u32) -> u64 { /// /// `value` is the value returned by `lane`. /// `default` is the value returned by all lanes other than `lane`. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn writelane_u32(value: u32, lane: u32, default: u32) -> u32 { @@ -596,6 +644,8 @@ pub unsafe fn writelane_u32(value: u32, lane: u32, default: u32) -> u32 { /// /// `value` is the value returned by `lane`. /// `default` is the value returned by all lanes other than `lane`. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn writelane_u64(value: u64, lane: u32, default: u64) -> u64 { @@ -605,6 +655,8 @@ pub unsafe fn writelane_u64(value: u64, lane: u32, default: u64) -> u64 { /// Stop execution of the wavefront. /// /// This usually signals the end of a successful execution. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub fn endpgm() -> ! { @@ -621,6 +673,8 @@ pub fn endpgm() -> ! { /// v_mov_b32 /// v_mov_b32 /// ``` +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn update_dpp< @@ -651,6 +705,8 @@ pub fn s_memrealtime() -> u64 { /// /// Reading from inactive lanes returns `0`. /// In case multiple values get written to the same `lane`, the value from the source lane with the higher index is taken. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn ds_permute(lane: u32, value: u32) -> u32 { @@ -661,6 +717,8 @@ pub unsafe fn ds_permute(lane: u32, value: u32) -> u32 { /// Returns the `value` given to `ds_permute` by lane `lane`. /// /// Reading from inactive lanes returns `0`. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn ds_bpermute(lane: u32, value: u32) -> u32 { @@ -680,6 +738,8 @@ pub unsafe fn perm(src0: u32, src1: u32, selector: u32) -> u32 { /// /// The third and fourth inputs must be uniform across the current wavefront. /// These are combined into a single 64-bit value representing lane selects used to swizzle within each row. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn permlane16_u32( @@ -696,6 +756,8 @@ pub unsafe fn permlane16_u32( /// /// The third and fourth inputs must be uniform across the current wavefront. /// These are combined into a single 64-bit value representing lane selects used to swizzle within each row. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn permlanex16_u32( @@ -718,6 +780,8 @@ pub fn s_get_waveid_in_workgroup() -> u32 { /// Swap `value` between upper and lower 32 lanes in a wavefront. /// /// Does nothing for wave32. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn permlane64_u32(value: u32) -> u32 { @@ -728,6 +792,8 @@ pub unsafe fn permlane64_u32(value: u32) -> u32 { /// Performs arbitrary gather-style operation within a row (16 contiguous lanes) of the second input operand. /// /// In contrast to [`permlane16_u32`], allows each lane to specify its own gather lane. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn permlane16_var( @@ -742,6 +808,8 @@ pub unsafe fn permlane16_var( /// Performs arbitrary gather-style operation across two rows (16 contiguous lanes) of the second input operand. /// /// In contrast to [`permlanex16_u32`], allows each lane to specify its own gather lane. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn permlanex16_var( @@ -766,6 +834,8 @@ pub fn wave_id() -> u32 { /// Odd rows of the first operand are swapped with even rows of the second operand (one row is 16 lanes). /// Returns a pair for the swapped registers. /// The first element of the return corresponds to the swapped element of the first argument. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn permlane16_swap( @@ -782,6 +852,8 @@ pub unsafe fn permlane16_swap( /// Rows 2 and 3 of the first operand are swapped with rows 0 and 1 of the second operand (one row is 16 lanes). /// Returns a pair for the swapped registers. /// The first element of the return corresponds to the swapped element of the first argument. +/// +#[doc = include_str!("intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_amdgpu", issue = "149988")] pub unsafe fn permlane32_swap( diff --git a/library/stdarch/crates/core_arch/src/nvptx/mod.rs b/library/stdarch/crates/core_arch/src/nvptx/mod.rs index 5471ef819801e..b63a5d01a7a22 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/mod.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/mod.rs @@ -49,6 +49,8 @@ unsafe extern "C" { } /// Synchronizes all threads in the block. +/// +#[doc = include_str!("../amdgpu/intrinsic_is_convergent.md")] #[inline] #[unstable(feature = "stdarch_nvptx", issue = "111199")] pub unsafe fn _syncthreads() -> () { diff --git a/src/doc/rustc-dev-guide/src/tests/minicore.md b/src/doc/rustc-dev-guide/src/tests/minicore.md index 5d05c2c1e0a9a..0fd7af7c60bbb 100644 --- a/src/doc/rustc-dev-guide/src/tests/minicore.md +++ b/src/doc/rustc-dev-guide/src/tests/minicore.md @@ -2,7 +2,7 @@ -[`tests/auxiliary/minicore.rs`][`minicore`] is a test auxiliary for ui/codegen/assembly test suites. +[`tests/auxiliary/minicore.rs`][`minicore`] is a test auxiliary for ui/codegen/assembly/mir-opt test suites. It provides `core` stubs for tests that need to build for cross-compiled targets but do not need/want to run. diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 0575285af7a43..17f89f1dd9a00 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -478,9 +478,12 @@ impl TestProps { fn update_add_minicore(&mut self, ln: &DirectiveLine<'_>, config: &Config) { let add_minicore = config.parse_name_directive(ln, directives::ADD_MINICORE); if add_minicore { - if !matches!(config.mode, TestMode::Ui | TestMode::Codegen | TestMode::Assembly) { + if !matches!( + config.mode, + TestMode::Ui | TestMode::Codegen | TestMode::Assembly | TestMode::MirOpt + ) { panic!( - "`add-minicore` is currently only supported for ui, codegen and assembly test modes" + "`add-minicore` is currently only supported for ui, codegen, assembly and mir-opt test modes" ); } diff --git a/tests/mir-opt/issues/issue_137086.rs b/tests/mir-opt/issues/issue_137086.rs new file mode 100644 index 0000000000000..316073df5434c --- /dev/null +++ b/tests/mir-opt/issues/issue_137086.rs @@ -0,0 +1,50 @@ +// Check that GPU targets do not run jump-threading + +//@ ignore-backends: gcc +//@ add-minicore +//@ revisions: cpu gpu +//@ compile-flags: -Z mir-opt-level=4 +//@[cpu] compile-flags: --target x86_64-unknown-linux-gnu +//@[cpu] needs-llvm-components: x86 +//@[gpu] compile-flags: --target nvptx64-nvidia-cuda +//@[gpu] needs-llvm-components: nvptx + +#![crate_type = "lib"] +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[inline(never)] +fn opaque() {} + +#[inline(never)] +fn opaque2() {} + +#[inline(never)] +fn syncthreads() {} + +pub fn function(cond: bool) { + // CHECK-LABEL: fn function + // Jump-threading duplicates syncthreads + // cpu: syncthreads() + // cpu: syncthreads() + + // Must not duplicate syncthreads + // gpu: syncthreads() + // gpu-NOT: syncthreads() + + if cond { + opaque(); + } else { + opaque2(); + } + syncthreads(); + if cond { + opaque(); + } else { + opaque2(); + } +} diff --git a/tests/ui/nll/polonius/location-insensitive-constraints-issue-70044.nll.stderr b/tests/ui/nll/polonius/location-insensitive-constraints-issue-70044.nll.stderr new file mode 100644 index 0000000000000..edb5bf5df413e --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-constraints-issue-70044.nll.stderr @@ -0,0 +1,14 @@ +error[E0502]: cannot borrow `one` as immutable because it is also borrowed as mutable + --> $DIR/location-insensitive-constraints-issue-70044.rs:22:20 + | +LL | let mut y = &mut one; + | -------- mutable borrow occurs here +... +LL | println!("{}", one); + | ^^^ immutable borrow occurs here +LL | println!("{}", zero); + | ---- mutable borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/polonius/location-insensitive-constraints-issue-70044.rs b/tests/ui/nll/polonius/location-insensitive-constraints-issue-70044.rs new file mode 100644 index 0000000000000..f59ce5170ad4e --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-constraints-issue-70044.rs @@ -0,0 +1,24 @@ +// This test is taken from https://github.com/rust-lang/rust/issues/70044. +// This test demonstrates how NLL's outlives constraints are flow-insensitive, +// and are wrongly expected to hold outside the inner scope. + +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius legacy +//@ [polonius] check-pass +//@ [polonius] compile-flags: -Z polonius=next +//@ [legacy] check-pass +//@ [legacy] compile-flags: -Z polonius=legacy + +fn main() { + let mut zero = &mut 0; + let mut one = 1; + + { + let mut _r = &mut zero; + let mut y = &mut one; + _r = &mut y; + } + + println!("{}", one); //[nll]~ ERROR: cannot borrow `one` as immutable + println!("{}", zero); +} diff --git a/tests/ui/nll/polonius/nll-problem-case-2-issue-92038.nll.stderr b/tests/ui/nll/polonius/nll-problem-case-2-issue-92038.nll.stderr new file mode 100644 index 0000000000000..62d66a900adbc --- /dev/null +++ b/tests/ui/nll/polonius/nll-problem-case-2-issue-92038.nll.stderr @@ -0,0 +1,16 @@ +error[E0499]: cannot borrow `*a` as mutable more than once at a time + --> $DIR/nll-problem-case-2-issue-92038.rs:16:26 + | +LL | fn reborrow(a: &mut u8) -> &mut u8 { + | - let's call the lifetime of this reference `'1` +LL | let b = &mut *a; + | ------- first mutable borrow occurs here +LL | if true { b } else { a } + | ---------------------^-- + | | | + | | second mutable borrow occurs here + | returning this value requires that `*a` is borrowed for `'1` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/nll-problem-case-2-issue-92038.rs b/tests/ui/nll/polonius/nll-problem-case-2-issue-92038.rs new file mode 100644 index 0000000000000..4b55e67e7e0d8 --- /dev/null +++ b/tests/ui/nll/polonius/nll-problem-case-2-issue-92038.rs @@ -0,0 +1,17 @@ +#![crate_type = "lib"] + +// This test demonstrates a shortcoming of NLL known as problem case #2 +// https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-2-conditional-control-flow +// This MCVE is copied from https://github.com/rust-lang/rust/issues/92038. + +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius legacy +//@ [polonius] check-pass +//@ [polonius] compile-flags: -Z polonius=next +//@ [legacy] check-pass +//@ [legacy] compile-flags: -Z polonius=legacy + +fn reborrow(a: &mut u8) -> &mut u8 { + let b = &mut *a; + if true { b } else { a } //[nll]~ ERROR: cannot borrow `*a` as mutable more than once at a time +} diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr index ae56e0bf78443..f380da1ca344e 100644 --- a/tests/ui/privacy/restricted/test.stderr +++ b/tests/ui/privacy/restricted/test.stderr @@ -1,3 +1,15 @@ +error[E0364]: `f` is private, and cannot be re-exported + --> $DIR/test.rs:22:24 + | +LL | pub(super) use foo::bar::f as g; + | ^^^^^^^^^^^^^^^^ + | +note: consider marking `f` as `pub` in the imported module + --> $DIR/test.rs:22:24 + | +LL | pub(super) use foo::bar::f as g; + | ^^^^^^^^^^^^^^^^ + error[E0433]: cannot find module or crate `bad` in the crate root --> $DIR/test.rs:51:12 | @@ -15,18 +27,6 @@ error[E0742]: visibilities can only be restricted to ancestor modules LL | pub(in foo) mod m2 {} | ^^^ -error[E0364]: `f` is private, and cannot be re-exported - --> $DIR/test.rs:22:24 - | -LL | pub(super) use foo::bar::f as g; - | ^^^^^^^^^^^^^^^^ - | -note: consider marking `f` as `pub` in the imported module - --> $DIR/test.rs:22:24 - | -LL | pub(super) use foo::bar::f as g; - | ^^^^^^^^^^^^^^^^ - error[E0603]: struct `Crate` is private --> $DIR/test.rs:39:25 | diff --git a/tests/ui/resolve/resolve-bad-visibility.rs b/tests/ui/resolve/resolve-bad-visibility.rs index bfc5e90c31e71..dfae5f23864a0 100644 --- a/tests/ui/resolve/resolve-bad-visibility.rs +++ b/tests/ui/resolve/resolve-bad-visibility.rs @@ -6,11 +6,9 @@ pub(in E) struct S; //~ ERROR expected module, found enum `::E` pub(in Tr) struct Z; //~ ERROR expected module, found trait `::Tr` pub(in std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules pub(in nonexistent) struct G; //~ ERROR cannot find -pub(in too_soon) struct H; //~ ERROR cannot find +pub(in too_soon) struct H; //~ ERROR visibilities can only be restricted -// Visibilities are resolved eagerly without waiting for modules becoming fully populated. -// Visibilities can only use ancestor modules legally which are always available in time, -// so the worst thing that can happen due to eager resolution is a suboptimal error message. +// The module exists, but it is not an ancestor module. mod too_soon {} fn main () {} diff --git a/tests/ui/resolve/resolve-bad-visibility.stderr b/tests/ui/resolve/resolve-bad-visibility.stderr index d9fd4400b8e0e..1965750a79b23 100644 --- a/tests/ui/resolve/resolve-bad-visibility.stderr +++ b/tests/ui/resolve/resolve-bad-visibility.stderr @@ -27,16 +27,11 @@ help: you might be missing a crate named `nonexistent`, add it to your project a LL + extern crate nonexistent; | -error[E0433]: cannot find module or crate `too_soon` in the crate root +error[E0742]: visibilities can only be restricted to ancestor modules --> $DIR/resolve-bad-visibility.rs:9:8 | LL | pub(in too_soon) struct H; - | ^^^^^^^^ use of unresolved module or unlinked crate `too_soon` - | -help: you might be missing a crate named `too_soon`, add it to your project and import it in your code - | -LL + extern crate too_soon; - | + | ^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/resolve/visibility-indeterminate.stderr b/tests/ui/resolve/visibility-indeterminate.stderr index bd6fc11b67313..d58d45ab792b4 100644 --- a/tests/ui/resolve/visibility-indeterminate.stderr +++ b/tests/ui/resolve/visibility-indeterminate.stderr @@ -1,15 +1,15 @@ -error[E0433]: cannot find `bar` in the crate root - --> $DIR/visibility-indeterminate.rs:5:10 - | -LL | pub(in ::bar) struct Baz {} - | ^^^ could not find `bar` in the list of imported crates - error: cannot find macro `foo` in this scope --> $DIR/visibility-indeterminate.rs:3:1 | LL | foo!(); | ^^^ +error[E0433]: cannot find `bar` in the crate root + --> $DIR/visibility-indeterminate.rs:5:10 + | +LL | pub(in ::bar) struct Baz {} + | ^^^ could not find `bar` in the list of imported crates + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/visibility-order-dependent.rs b/tests/ui/resolve/visibility-order-dependent.rs new file mode 100644 index 0000000000000..984e9a3aae6a2 --- /dev/null +++ b/tests/ui/resolve/visibility-order-dependent.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 +// Regression test for . + +mod foo { + pub(in crate::bar) struct Foo; + //~^ ERROR visibilities can only be restricted to ancestor modules +} + +mod bar { + pub(in crate::foo) struct Bar; + //~^ ERROR visibilities can only be restricted to ancestor modules +} + +fn main() {} diff --git a/tests/ui/resolve/visibility-order-dependent.stderr b/tests/ui/resolve/visibility-order-dependent.stderr new file mode 100644 index 0000000000000..4bc7b37c6ac95 --- /dev/null +++ b/tests/ui/resolve/visibility-order-dependent.stderr @@ -0,0 +1,15 @@ +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/visibility-order-dependent.rs:5:12 + | +LL | pub(in crate::bar) struct Foo; + | ^^^^^^^^^^ + +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/visibility-order-dependent.rs:10:12 + | +LL | pub(in crate::foo) struct Bar; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0742`. diff --git a/tests/ui/span/visibility-ty-params.stderr b/tests/ui/span/visibility-ty-params.stderr index 2fda6c70de0dd..08c1552d7fbbb 100644 --- a/tests/ui/span/visibility-ty-params.stderr +++ b/tests/ui/span/visibility-ty-params.stderr @@ -4,18 +4,18 @@ error: unexpected generic arguments in path LL | m!{ crate::S } | ^^^^ -error[E0433]: cannot find module `S` in `crate` - --> $DIR/visibility-ty-params.rs:6:12 - | -LL | m!{ crate::S } - | ^ `S` is a struct, not a module - error: unexpected generic arguments in path --> $DIR/visibility-ty-params.rs:10:17 | LL | m!{ crate::m<> } | ^^ +error[E0433]: cannot find module `S` in `crate` + --> $DIR/visibility-ty-params.rs:6:12 + | +LL | m!{ crate::S } + | ^ `S` is a struct, not a module + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/use/use-self-type.stderr b/tests/ui/use/use-self-type.stderr index 086b7a4d8222c..e1258d3509e87 100644 --- a/tests/ui/use/use-self-type.stderr +++ b/tests/ui/use/use-self-type.stderr @@ -1,15 +1,15 @@ -error[E0433]: cannot find `Self` in this scope - --> $DIR/use-self-type.rs:7:16 - | -LL | pub(in Self::f) struct Z; - | ^^^^ `Self` cannot be used in imports - error[E0432]: unresolved import `Self` --> $DIR/use-self-type.rs:6:13 | LL | use Self::f; | ^^^^ `Self` cannot be used in imports +error[E0433]: cannot find `Self` in this scope + --> $DIR/use-self-type.rs:7:16 + | +LL | pub(in Self::f) struct Z; + | ^^^^ `Self` cannot be used in imports + error: aborting due to 2 previous errors Some errors have detailed explanations: E0432, E0433.