Skip to content

Rollup of 6 pull requests #122475

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ use rustc_errors::{
markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult,
};
use rustc_feature::find_gated_cfg;
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
use rustc_interface::util::{self, get_codegen_backend};
use rustc_interface::{interface, Queries};
use rustc_lint::unerased_lint_store;
use rustc_metadata::creader::MetadataLoader;
@@ -37,6 +37,7 @@ use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType};
use rustc_session::getopts::{self, Matches};
use rustc_session::lint::{Lint, LintId};
use rustc_session::output::collect_crate_types;
use rustc_session::{config, filesearch, EarlyDiagCtxt, Session};
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::source_map::FileLoader;
22 changes: 14 additions & 8 deletions compiler/rustc_incremental/src/persist/fs.rs
Original file line number Diff line number Diff line change
@@ -110,8 +110,9 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_data_structures::{base_n, flock};
use rustc_errors::ErrorGuaranteed;
use rustc_fs_util::{link_or_copy, try_canonicalize, LinkOrCopy};
use rustc_session::config::CrateType;
use rustc_session::output::{collect_crate_types, find_crate_name};
use rustc_session::{Session, StableCrateId};
use rustc_span::Symbol;

use std::fs as std_fs;
use std::io::{self, ErrorKind};
@@ -205,11 +206,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
/// The garbage collection will take care of it.
///
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
pub(crate) fn prepare_session_directory(
sess: &Session,
crate_name: Symbol,
stable_crate_id: StableCrateId,
) -> Result<(), ErrorGuaranteed> {
pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuaranteed> {
if sess.opts.incremental.is_none() {
return Ok(());
}
@@ -219,7 +216,7 @@ pub(crate) fn prepare_session_directory(
debug!("prepare_session_directory");

// {incr-comp-dir}/{crate-name-and-disambiguator}
let crate_dir = crate_path(sess, crate_name, stable_crate_id);
let crate_dir = crate_path(sess);
debug!("crate-dir: {}", crate_dir.display());
create_dir(sess, &crate_dir, "crate")?;

@@ -604,9 +601,18 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
Ok(UNIX_EPOCH + duration)
}

fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
fn crate_path(sess: &Session) -> PathBuf {
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();

let crate_name = find_crate_name(sess, &[]);
let crate_types = collect_crate_types(sess, &[]);
let stable_crate_id = StableCrateId::new(
crate_name,
crate_types.contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);

let stable_crate_id = base_n::encode(stable_crate_id.as_u64() as u128, INT_ENCODE_BASE);

let crate_name = format!("{crate_name}-{stable_crate_id}");
12 changes: 4 additions & 8 deletions compiler/rustc_incremental/src/persist/load.rs
Original file line number Diff line number Diff line change
@@ -8,8 +8,8 @@ use rustc_middle::query::on_disk_cache::OnDiskCache;
use rustc_serialize::opaque::MemDecoder;
use rustc_serialize::Decodable;
use rustc_session::config::IncrementalStateAssertion;
use rustc_session::{Session, StableCrateId};
use rustc_span::{ErrorGuaranteed, Symbol};
use rustc_session::Session;
use rustc_span::ErrorGuaranteed;
use std::path::{Path, PathBuf};

use super::data::*;
@@ -190,13 +190,9 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache<'_>> {

/// Setups the dependency graph by loading an existing graph from disk and set up streaming of a
/// new graph to an incremental session directory.
pub fn setup_dep_graph(
sess: &Session,
crate_name: Symbol,
stable_crate_id: StableCrateId,
) -> Result<DepGraph, ErrorGuaranteed> {
pub fn setup_dep_graph(sess: &Session) -> Result<DepGraph, ErrorGuaranteed> {
// `load_dep_graph` can only be called after `prepare_session_directory`.
prepare_session_directory(sess, crate_name, stable_crate_id)?;
prepare_session_directory(sess)?;

let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));

3 changes: 0 additions & 3 deletions compiler/rustc_interface/messages.ftl
Original file line number Diff line number Diff line change
@@ -48,6 +48,3 @@ interface_rustc_error_unexpected_annotation =

interface_temps_dir_error =
failed to find or create the directory specified by `--temps-dir`

interface_unsupported_crate_type_for_target =
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
9 changes: 0 additions & 9 deletions compiler/rustc_interface/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use rustc_macros::Diagnostic;
use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol};
use rustc_target::spec::TargetTriple;

use std::io;
use std::path::Path;
@@ -90,13 +88,6 @@ pub struct FailedWritingFile<'a> {
#[diag(interface_proc_macro_crate_panic_abort)]
pub struct ProcMacroCratePanicAbort;

#[derive(Diagnostic)]
#[diag(interface_unsupported_crate_type_for_target)]
pub struct UnsupportedCrateTypeForTarget<'a> {
pub crate_type: CrateType,
pub target_triple: &'a TargetTriple,
}

#[derive(Diagnostic)]
#[diag(interface_multiple_output_types_adaption)]
pub struct MultipleOutputTypesAdaption;
6 changes: 3 additions & 3 deletions compiler/rustc_interface/src/queries.rs
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ use rustc_middle::ty::{GlobalCtxt, TyCtxt};
use rustc_serialize::opaque::FileEncodeResult;
use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::output::find_crate_name;
use rustc_session::output::{collect_crate_types, find_crate_name};
use rustc_session::Session;
use rustc_span::symbol::sym;
use std::any::Any;
@@ -128,15 +128,15 @@ impl<'tcx> Queries<'tcx> {

// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
let crate_name = find_crate_name(sess, &pre_configured_attrs);
let crate_types = util::collect_crate_types(sess, &pre_configured_attrs);
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
let stable_crate_id = StableCrateId::new(
crate_name,
crate_types.contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?;
let dep_graph = setup_dep_graph(sess)?;

let cstore = FreezeLock::new(Box::new(CStore::new(
self.compiler.codegen_backend.metadata_loader(),
68 changes: 4 additions & 64 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
@@ -7,14 +7,15 @@ use rustc_data_structures::sync;
use rustc_metadata::{load_symbol_from_dylib, DylibError};
use rustc_parse::validate_attr;
use rustc_session as session;
use rustc_session::config::{self, Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes};
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes};
use rustc_session::filesearch::sysroot_candidates;
use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
use rustc_session::{filesearch, output, Session};
use rustc_session::{filesearch, Session};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::symbol::sym;
use rustc_target::spec::Target;
use session::output::{categorize_crate_type, CRATE_TYPES};
use session::EarlyDiagCtxt;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::path::{Path, PathBuf};
@@ -399,67 +400,6 @@ pub(crate) fn check_attr_crate_type(
}
}

const CRATE_TYPES: &[(Symbol, CrateType)] = &[
(sym::rlib, CrateType::Rlib),
(sym::dylib, CrateType::Dylib),
(sym::cdylib, CrateType::Cdylib),
(sym::lib, config::default_lib_output()),
(sym::staticlib, CrateType::Staticlib),
(sym::proc_dash_macro, CrateType::ProcMacro),
(sym::bin, CrateType::Executable),
];

fn categorize_crate_type(s: Symbol) -> Option<CrateType> {
Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1)
}

pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<CrateType> {
// If we're generating a test executable, then ignore all other output
// styles at all other locations
if session.opts.test {
return vec![CrateType::Executable];
}

// Only check command line flags if present. If no types are specified by
// command line, then reuse the empty `base` Vec to hold the types that
// will be found in crate attributes.
// JUSTIFICATION: before wrapper fn is available
#[allow(rustc::bad_opt_access)]
let mut base = session.opts.crate_types.clone();
if base.is_empty() {
let attr_types = attrs.iter().filter_map(|a| {
if a.has_name(sym::crate_type)
&& let Some(s) = a.value_str()
{
categorize_crate_type(s)
} else {
None
}
});
base.extend(attr_types);
if base.is_empty() {
base.push(output::default_output_for_target(session));
} else {
base.sort();
base.dedup();
}
}

base.retain(|crate_type| {
if output::invalid_output_for_target(session, *crate_type) {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
crate_type: *crate_type,
target_triple: &session.opts.target_triple,
});
false
} else {
true
}
});

base
}

fn multiple_output_types_to_stdout(
output_types: &OutputTypes,
single_output_file_is_stdout: bool,
1 change: 1 addition & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -557,6 +557,7 @@ declare_lint! {
/// fn main() {
/// use foo::bar;
/// foo::bar();
/// bar();
/// }
/// ```
///
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -2436,8 +2436,9 @@ impl<'tcx> Ty<'tcx> {
},

// "Bound" types appear in canonical queries when the
// closure type is not yet known
Bound(..) | Param(_) | Infer(_) => None,
// closure type is not yet known, and `Placeholder` and `Param`
// may be encountered in generic `AsyncFnKindHelper` goals.
Bound(..) | Placeholder(_) | Param(_) | Infer(_) => None,

Error(_) => Some(ty::ClosureKind::Fn),

4 changes: 3 additions & 1 deletion compiler/rustc_mir_transform/src/dataflow_const_prop.rs
Original file line number Diff line number Diff line change
@@ -393,7 +393,9 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
}
}
Operand::Constant(box constant) => {
if let Ok(constant) = self.ecx.eval_mir_constant(&constant.const_, None, None) {
if let Ok(constant) =
self.ecx.eval_mir_constant(&constant.const_, Some(constant.span), None)
{
self.assign_constant(state, place, constant, &[]);
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_mir_transform/src/jump_threading.rs
Original file line number Diff line number Diff line change
@@ -416,7 +416,8 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
match rhs {
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
Operand::Constant(constant) => {
let constant = self.ecx.eval_mir_constant(&constant.const_, None, None).ok()?;
let constant =
self.ecx.eval_mir_constant(&constant.const_, Some(constant.span), None).ok()?;
self.process_constant(bb, lhs, constant, state);
}
// Transfer the conditions on the copied rhs.
7 changes: 5 additions & 2 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
@@ -825,14 +825,17 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
fn visit_constant(&mut self, constant: &mir::ConstOperand<'tcx>, location: Location) {
let const_ = self.monomorphize(constant.const_);
let param_env = ty::ParamEnv::reveal_all();
let val = match const_.eval(self.tcx, param_env, None) {
let val = match const_.eval(self.tcx, param_env, Some(constant.span)) {
Ok(v) => v,
Err(ErrorHandled::Reported(..)) => return,
Err(ErrorHandled::TooGeneric(..)) => span_bug!(
self.body.source_info(location).span,
"collection encountered polymorphic constant: {:?}",
const_
),
Err(err @ ErrorHandled::Reported(..)) => {
err.emit_note(self.tcx);
return;
}
};
collect_const_value(self.tcx, val, self.output);
MirVisitor::visit_ty(self, const_.ty(), TyContext::Location(location));
60 changes: 56 additions & 4 deletions compiler/rustc_resolve/src/check_unused.rs
Original file line number Diff line number Diff line change
@@ -23,18 +23,19 @@
// - `check_unused` finally emits the diagnostics based on the data generated
// in the last step

use crate::imports::ImportKind;
use crate::imports::{Import, ImportKind};
use crate::module_to_string;
use crate::Resolver;

use crate::NameBindingKind;
use crate::{LexicalScopeBinding, NameBindingKind};
use rustc_ast as ast;
use rustc_ast::visit::{self, Visitor};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{pluralize, MultiSpan};
use rustc_hir::def::{DefKind, Res};
use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS};
use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES};
use rustc_session::lint::builtin::{UNUSED_IMPORTS, UNUSED_QUALIFICATIONS};
use rustc_session::lint::BuiltinLintDiag;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{Span, DUMMY_SP};
@@ -514,8 +515,59 @@ impl Resolver<'_, '_> {
}
}

let mut redundant_imports = UnordSet::default();
for import in check_redundant_imports {
self.check_for_redundant_imports(import);
if self.check_for_redundant_imports(import)
&& let Some(id) = import.id()
{
redundant_imports.insert(id);
}
}

// The lint fixes for unused_import and unnecessary_qualification may conflict.
// Deleting both unused imports and unnecessary segments of an item may result
// in the item not being found.
for unn_qua in &self.potentially_unnecessary_qualifications {
if let LexicalScopeBinding::Item(name_binding) = unn_qua.binding
&& let NameBindingKind::Import { import, .. } = name_binding.kind
&& (is_unused_import(import, &unused_imports)
|| is_redundant_import(import, &redundant_imports))
{
continue;
}

self.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_QUALIFICATIONS,
unn_qua.node_id,
unn_qua.path_span,
"unnecessary qualification",
BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span },
);
}

fn is_redundant_import(
import: Import<'_>,
redundant_imports: &UnordSet<ast::NodeId>,
) -> bool {
if let Some(id) = import.id()
&& redundant_imports.contains(&id)
{
return true;
}
false
}

fn is_unused_import(
import: Import<'_>,
unused_imports: &FxIndexMap<ast::NodeId, UnusedImport>,
) -> bool {
if let Some(unused_import) = unused_imports.get(&import.root_id)
&& let Some(id) = import.id()
&& unused_import.unused.contains(&id)
{
return true;
}
false
}
}
}
11 changes: 7 additions & 4 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
@@ -1306,7 +1306,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None
}

pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) {
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) -> bool {
// This function is only called for single imports.
let ImportKind::Single {
source, target, ref source_bindings, ref target_bindings, id, ..
@@ -1317,12 +1317,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {

// Skip if the import is of the form `use source as target` and source != target.
if source != target {
return;
return false;
}

// Skip if the import was produced by a macro.
if import.parent_scope.expansion != LocalExpnId::ROOT {
return;
return false;
}

// Skip if we are inside a named module (in contrast to an anonymous
@@ -1332,7 +1332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if import.used.get() == Some(Used::Other)
|| self.effective_visibilities.is_exported(self.local_def_id(id))
{
return;
return false;
}

let mut is_redundant = true;
@@ -1375,7 +1375,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
format!("the item `{source}` is imported redundantly"),
BuiltinLintDiag::RedundantImport(redundant_spans, source),
);
return true;
}

false
}

fn resolve_glob_import(&mut self, import: Import<'a>) {
29 changes: 17 additions & 12 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
@@ -580,6 +580,15 @@ impl MaybeExported<'_> {
}
}

/// Used for recording UnnecessaryQualification.
#[derive(Debug)]
pub(crate) struct UnnecessaryQualification<'a> {
pub binding: LexicalScopeBinding<'a>,
pub node_id: NodeId,
pub path_span: Span,
pub removal_span: Span,
}

#[derive(Default)]
struct DiagMetadata<'ast> {
/// The current trait's associated items' ident, used for diagnostic suggestions.
@@ -4654,20 +4663,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let ns = if i + 1 == path.len() { ns } else { TypeNS };
let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;

(res == binding.res()).then_some(seg)
(res == binding.res()).then_some((seg, binding))
});

if let Some(unqualified) = unqualified {
self.r.lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::UNUSED_QUALIFICATIONS,
finalize.node_id,
finalize.path_span,
"unnecessary qualification",
lint::BuiltinLintDiag::UnusedQualifications {
removal_span: path[0].ident.span.until(unqualified.ident.span),
},
);
if let Some((seg, binding)) = unqualified {
self.r.potentially_unnecessary_qualifications.push(UnnecessaryQualification {
binding,
node_id: finalize.node_id,
path_span: finalize.path_span,
removal_span: path[0].ident.span.until(seg.ident.span),
});
}
}
}
7 changes: 5 additions & 2 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ use std::fmt;

use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
use imports::{Import, ImportData, ImportKind, NameResolution};
use late::{HasGenericParams, PathSource, PatternSource};
use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};

use crate::effective_visibilities::EffectiveVisibilitiesVisitor;
@@ -372,7 +372,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
/// This refers to the thing referred by a name. The difference between `Res` and `Item` is that
/// items are visible in their whole block, while `Res`es only from the place they are defined
/// forward.
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
enum LexicalScopeBinding<'a> {
Item(NameBinding<'a>),
Res(Res),
@@ -1105,6 +1105,8 @@ pub struct Resolver<'a, 'tcx> {

potentially_unused_imports: Vec<Import<'a>>,

potentially_unnecessary_qualifications: Vec<UnnecessaryQualification<'a>>,

/// Table for mapping struct IDs into struct constructor IDs,
/// it's not used during normal resolution, only for better error reporting.
/// Also includes of list of each fields visibility
@@ -1464,6 +1466,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
local_macro_def_scopes: FxHashMap::default(),
name_already_seen: FxHashMap::default(),
potentially_unused_imports: Vec::new(),
potentially_unnecessary_qualifications: Default::default(),
struct_constructors: Default::default(),
unused_macros: Default::default(),
unused_macro_rules: Default::default(),
3 changes: 3 additions & 0 deletions compiler/rustc_session/messages.ftl
Original file line number Diff line number Diff line change
@@ -111,4 +111,7 @@ session_unleashed_feature_help_unnamed = skipping check that does not even have
session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
session_unsupported_crate_type_for_target =
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
9 changes: 8 additions & 1 deletion compiler/rustc_session/src/errors.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};

use crate::parse::ParseSess;
use crate::{config::CrateType, parse::ParseSess};

pub struct FeatureGateError {
pub span: MultiSpan,
@@ -345,6 +345,13 @@ pub(crate) struct BinaryFloatLiteralNotSupported {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(session_unsupported_crate_type_for_target)]
pub struct UnsupportedCrateTypeForTarget<'a> {
pub crate_type: CrateType,
pub target_triple: &'a TargetTriple,
}

pub fn report_lit_error(
psess: &ParseSess,
err: LitError,
65 changes: 63 additions & 2 deletions compiler/rustc_session/src/output.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Related to out filenames of compilation (e.g. binaries).
use crate::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use crate::config::{self, CrateType, Input, OutFileName, OutputFilenames, OutputType};
use crate::errors::{
CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
self, CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
InvalidCharacterInCrateName, InvalidCrateNameHelp,
};
use crate::Session;
@@ -200,3 +200,64 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool

false
}

pub const CRATE_TYPES: &[(Symbol, CrateType)] = &[
(sym::rlib, CrateType::Rlib),
(sym::dylib, CrateType::Dylib),
(sym::cdylib, CrateType::Cdylib),
(sym::lib, config::default_lib_output()),
(sym::staticlib, CrateType::Staticlib),
(sym::proc_dash_macro, CrateType::ProcMacro),
(sym::bin, CrateType::Executable),
];

pub fn categorize_crate_type(s: Symbol) -> Option<CrateType> {
Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1)
}

pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<CrateType> {
// If we're generating a test executable, then ignore all other output
// styles at all other locations
if session.opts.test {
return vec![CrateType::Executable];
}

// Only check command line flags if present. If no types are specified by
// command line, then reuse the empty `base` Vec to hold the types that
// will be found in crate attributes.
// JUSTIFICATION: before wrapper fn is available
#[allow(rustc::bad_opt_access)]
let mut base = session.opts.crate_types.clone();
if base.is_empty() {
let attr_types = attrs.iter().filter_map(|a| {
if a.has_name(sym::crate_type)
&& let Some(s) = a.value_str()
{
categorize_crate_type(s)
} else {
None
}
});
base.extend(attr_types);
if base.is_empty() {
base.push(default_output_for_target(session));
} else {
base.sort();
base.dedup();
}
}

base.retain(|crate_type| {
if invalid_output_for_target(session, *crate_type) {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
crate_type: *crate_type,
target_triple: &session.opts.target_triple,
});
false
} else {
true
}
});

base
}
2 changes: 1 addition & 1 deletion compiler/rustc_smir/src/rustc_smir/builder.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {

fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
let const_ = self.monomorphize(constant.const_);
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), None) {
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), Some(constant.span)) {
Ok(v) => v,
Err(mir::interpret::ErrorHandled::Reported(..)) => return,
Err(mir::interpret::ErrorHandled::TooGeneric(..)) => {
15 changes: 7 additions & 8 deletions library/core/src/iter/range.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6
///
/// The *successor* operation moves towards values that compare greater.
/// The *predecessor* operation moves towards values that compare lesser.
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
#[unstable(feature = "step_trait", issue = "42168")]
pub trait Step: Clone + PartialOrd + Sized {
/// Returns the number of *successor* steps required to get from `start` to `end`.
///
@@ -52,15 +52,12 @@ pub trait Step: Clone + PartialOrd + Sized {
/// For any `a`, `n`, and `m`:
///
/// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, m).and_then(|x| Step::forward_checked(x, n))`
///
/// For any `a`, `n`, and `m` where `n + m` does not overflow:
///
/// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, n + m)`
/// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == try { Step::forward_checked(a, n.checked_add(m)) }`
///
/// For any `a` and `n`:
///
/// * `Step::forward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::forward_checked(&x, 1))`
/// * Corollary: `Step::forward_checked(&a, 0) == Some(a)`
/// * Corollary: `Step::forward_checked(a, 0) == Some(a)`
fn forward_checked(start: Self, count: usize) -> Option<Self>;

/// Returns the value that would be obtained by taking the *successor*
@@ -106,6 +103,7 @@ pub trait Step: Clone + PartialOrd + Sized {
/// * if there exists `b` such that `b > a`, it is safe to call `Step::forward_unchecked(a, 1)`
/// * if there exists `b`, `n` such that `steps_between(&a, &b) == Some(n)`,
/// it is safe to call `Step::forward_unchecked(a, m)` for any `m <= n`.
/// * Corollary: `Step::forward_unchecked(a, 0)` is always safe.
///
/// For any `a` and `n`, where no overflow occurs:
///
@@ -128,8 +126,8 @@ pub trait Step: Clone + PartialOrd + Sized {
///
/// For any `a` and `n`:
///
/// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(&x, 1))`
/// * Corollary: `Step::backward_checked(&a, 0) == Some(a)`
/// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(x, 1))`
/// * Corollary: `Step::backward_checked(a, 0) == Some(a)`
fn backward_checked(start: Self, count: usize) -> Option<Self>;

/// Returns the value that would be obtained by taking the *predecessor*
@@ -175,6 +173,7 @@ pub trait Step: Clone + PartialOrd + Sized {
/// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)`
/// * if there exists `b`, `n` such that `steps_between(&b, &a) == Some(n)`,
/// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`.
/// * Corollary: `Step::backward_unchecked(a, 0)` is always safe.
///
/// For any `a` and `n`, where no overflow occurs:
///
68 changes: 47 additions & 21 deletions library/std/src/os/windows/io/handle.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ use crate::fmt;
use crate::fs;
use crate::io;
use crate::marker::PhantomData;
use crate::mem::forget;
use crate::mem::{forget, ManuallyDrop};
use crate::ptr;
use crate::sys;
use crate::sys::cvt;
@@ -91,7 +91,7 @@ pub struct OwnedHandle {
#[repr(transparent)]
#[stable(feature = "io_safety", since = "1.63.0")]
#[derive(Debug)]
pub struct HandleOrNull(OwnedHandle);
pub struct HandleOrNull(RawHandle);

/// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
/// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
@@ -110,7 +110,7 @@ pub struct HandleOrNull(OwnedHandle);
#[repr(transparent)]
#[stable(feature = "io_safety", since = "1.63.0")]
#[derive(Debug)]
pub struct HandleOrInvalid(OwnedHandle);
pub struct HandleOrInvalid(RawHandle);

// The Windows [`HANDLE`] type may be transferred across and shared between
// thread boundaries (despite containing a `*mut void`, which in general isn't
@@ -163,15 +163,24 @@ impl TryFrom<HandleOrNull> for OwnedHandle {

#[inline]
fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
let owned_handle = handle_or_null.0;
if owned_handle.handle.is_null() {
// Don't call `CloseHandle`; it'd be harmless, except that it could
// overwrite the `GetLastError` error.
forget(owned_handle);

Err(NullHandleError(()))
let handle_or_null = ManuallyDrop::new(handle_or_null);
if handle_or_null.is_valid() {
// SAFETY: The handle is not null.
Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_null.0) })
} else {
Ok(owned_handle)
Err(NullHandleError(()))
}
}
}

#[stable(feature = "io_safety", since = "1.63.0")]
impl Drop for HandleOrNull {
#[inline]
fn drop(&mut self) {
if self.is_valid() {
unsafe {
let _ = sys::c::CloseHandle(self.0);
}
}
}
}
@@ -232,15 +241,24 @@ impl TryFrom<HandleOrInvalid> for OwnedHandle {

#[inline]
fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
let owned_handle = handle_or_invalid.0;
if owned_handle.handle == sys::c::INVALID_HANDLE_VALUE {
// Don't call `CloseHandle`; it'd be harmless, except that it could
// overwrite the `GetLastError` error.
forget(owned_handle);

Err(InvalidHandleError(()))
let handle_or_invalid = ManuallyDrop::new(handle_or_invalid);
if handle_or_invalid.is_valid() {
// SAFETY: The handle is not invalid.
Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_invalid.0) })
} else {
Ok(owned_handle)
Err(InvalidHandleError(()))
}
}
}

#[stable(feature = "io_safety", since = "1.63.0")]
impl Drop for HandleOrInvalid {
#[inline]
fn drop(&mut self) {
if self.is_valid() {
unsafe {
let _ = sys::c::CloseHandle(self.0);
}
}
}
}
@@ -333,7 +351,11 @@ impl HandleOrNull {
#[stable(feature = "io_safety", since = "1.63.0")]
#[inline]
pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self(OwnedHandle::from_raw_handle(handle))
Self(handle)
}

fn is_valid(&self) -> bool {
!self.0.is_null()
}
}

@@ -356,7 +378,11 @@ impl HandleOrInvalid {
#[stable(feature = "io_safety", since = "1.63.0")]
#[inline]
pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self(OwnedHandle::from_raw_handle(handle))
Self(handle)
}

fn is_valid(&self) -> bool {
self.0 != sys::c::INVALID_HANDLE_VALUE
}
}

6 changes: 6 additions & 0 deletions tests/ui/consts/assoc_const_generic_impl.stderr
Original file line number Diff line number Diff line change
@@ -4,6 +4,12 @@ error[E0080]: evaluation of `<u32 as ZeroSized>::I_AM_ZERO_SIZED` failed
LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4

note: erroneous constant encountered
--> $DIR/assoc_const_generic_impl.rs:11:9
|
LL | Self::I_AM_ZERO_SIZED;
| ^^^^^^^^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn <u32 as ZeroSized>::requires_zero_size`
--> $DIR/assoc_const_generic_impl.rs:18:5
|
Original file line number Diff line number Diff line change
@@ -4,6 +4,12 @@ error[E0080]: evaluation of `PrintName::<()>::VOID` failed
LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
| ^^^^^ index out of bounds: the length is 0 but the index is 0

note: erroneous constant encountered
--> $DIR/index-out-of-bounds-never-type.rs:16:13
|
LL | let _ = PrintName::<T>::VOID;
| ^^^^^^^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn f::<()>`
--> $DIR/index-out-of-bounds-never-type.rs:20:5
|
46 changes: 46 additions & 0 deletions tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr
Original file line number Diff line number Diff line change
@@ -10,6 +10,52 @@ note: erroneous constant encountered
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:5
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:5
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:5
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:5
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:6
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:6
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0080`.
14 changes: 14 additions & 0 deletions tests/ui/consts/const-eval/issue-50814-2.normal.stderr
Original file line number Diff line number Diff line change
@@ -10,6 +10,20 @@ note: erroneous constant encountered
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:5
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-50814-2.rs:20:6
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: the above error was encountered while instantiating `fn foo::<()>`
--> $DIR/issue-50814-2.rs:32:22
|
14 changes: 14 additions & 0 deletions tests/ui/consts/const-eval/issue-50814.stderr
Original file line number Diff line number Diff line change
@@ -26,6 +26,20 @@ LL | &Sum::<U8, U8>::MAX
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: erroneous constant encountered
--> $DIR/issue-50814.rs:21:5
|
LL | &Sum::<U8, U8>::MAX
| ^^^^^^^^^^^^^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-50814.rs:21:6
|
LL | &Sum::<U8, U8>::MAX
| ^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: the above error was encountered while instantiating `fn foo::<i32>`
--> $DIR/issue-50814.rs:26:5
|
8 changes: 8 additions & 0 deletions tests/ui/consts/const-eval/issue-85155.stderr
Original file line number Diff line number Diff line change
@@ -4,6 +4,14 @@ error[E0080]: evaluation of `post_monomorphization_error::ValidateConstImm::<2,
LL | let _ = 1 / ((IMM >= MIN && IMM <= MAX) as usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to divide `1_usize` by zero

note: erroneous constant encountered
--> $DIR/auxiliary/post_monomorphization_error.rs:19:5
|
LL | static_assert_imm1!(IMM1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this note originates in the macro `static_assert_imm1` (in Nightly builds, run with -Z macro-backtrace for more info)

note: the above error was encountered while instantiating `fn post_monomorphization_error::stdarch_intrinsic::<2>`
--> $DIR/issue-85155.rs:19:5
|
6 changes: 6 additions & 0 deletions tests/ui/consts/const-eval/unused-broken-const-late.stderr
Original file line number Diff line number Diff line change
@@ -6,6 +6,12 @@ LL | const VOID: () = panic!();
|
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant encountered
--> $DIR/unused-broken-const-late.rs:15:17
|
LL | let _ = PrintName::<T>::VOID;
| ^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0080`.
20 changes: 20 additions & 0 deletions tests/ui/inline-const/const-expr-generic-err.stderr
Original file line number Diff line number Diff line change
@@ -6,6 +6,12 @@ LL | const { assert!(std::mem::size_of::<T>() == 0); }
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant encountered
--> $DIR/const-expr-generic-err.rs:5:5
|
LL | const { assert!(std::mem::size_of::<T>() == 0); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn foo::<i32>`
--> $DIR/const-expr-generic-err.rs:13:5
|
@@ -18,6 +24,20 @@ error[E0080]: evaluation of `bar::<0>::{constant#0}` failed
LL | const { N - 1 }
| ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow

note: erroneous constant encountered
--> $DIR/const-expr-generic-err.rs:9:5
|
LL | const { N - 1 }
| ^^^^^^^^^^^^^^^

note: erroneous constant encountered
--> $DIR/const-expr-generic-err.rs:9:5
|
LL | const { N - 1 }
| ^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

note: the above error was encountered while instantiating `fn bar::<0>`
--> $DIR/const-expr-generic-err.rs:14:5
|
6 changes: 6 additions & 0 deletions tests/ui/inline-const/required-const.stderr
Original file line number Diff line number Diff line change
@@ -6,6 +6,12 @@ LL | const { panic!() }
|
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant encountered
--> $DIR/required-const.rs:7:9
|
LL | const { panic!() }
| ^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0080`.
7 changes: 5 additions & 2 deletions tests/ui/lint/lint-qualification.fixed
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//@ run-rustfix
#![deny(unused_qualifications)]
#![deny(unused_imports)]
#![allow(deprecated, dead_code)]

mod foo {
@@ -21,8 +22,10 @@ fn main() {
//~^ ERROR: unnecessary qualification
//~| ERROR: unnecessary qualification

use std::fmt;
let _: fmt::Result = Ok(()); //~ ERROR: unnecessary qualification

//~^ ERROR: unused import: `std::fmt`
let _: std::fmt::Result = Ok(());
// don't report unnecessary qualification because fix(#122373) for issue #121331

let _ = <bool as Default>::default(); // issue #121999
//~^ ERROR: unnecessary qualification
5 changes: 4 additions & 1 deletion tests/ui/lint/lint-qualification.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//@ run-rustfix
#![deny(unused_qualifications)]
#![deny(unused_imports)]
#![allow(deprecated, dead_code)]

mod foo {
@@ -22,7 +23,9 @@ fn main() {
//~| ERROR: unnecessary qualification

use std::fmt;
let _: std::fmt::Result = Ok(()); //~ ERROR: unnecessary qualification
//~^ ERROR: unused import: `std::fmt`
let _: std::fmt::Result = Ok(());
// don't report unnecessary qualification because fix(#122373) for issue #121331

let _ = <bool as ::std::default::Default>::default(); // issue #121999
//~^ ERROR: unnecessary qualification
30 changes: 15 additions & 15 deletions tests/ui/lint/lint-qualification.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: unnecessary qualification
--> $DIR/lint-qualification.rs:11:5
--> $DIR/lint-qualification.rs:12:5
|
LL | foo::bar();
| ^^^^^^^^
@@ -16,7 +16,7 @@ LL + bar();
|

error: unnecessary qualification
--> $DIR/lint-qualification.rs:12:5
--> $DIR/lint-qualification.rs:13:5
|
LL | crate::foo::bar();
| ^^^^^^^^^^^^^^^
@@ -28,7 +28,7 @@ LL + bar();
|

error: unnecessary qualification
--> $DIR/lint-qualification.rs:17:13
--> $DIR/lint-qualification.rs:18:13
|
LL | let _ = std::string::String::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL + let _ = String::new();
|

error: unnecessary qualification
--> $DIR/lint-qualification.rs:18:13
--> $DIR/lint-qualification.rs:19:13
|
LL | let _ = ::std::env::current_dir();
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,7 +52,7 @@ LL + let _ = std::env::current_dir();
|

error: unnecessary qualification
--> $DIR/lint-qualification.rs:20:12
--> $DIR/lint-qualification.rs:21:12
|
LL | let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
| ^^^^^^^^^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL + let _: Vec<String> = std::vec::Vec::<String>::new();
|

error: unnecessary qualification
--> $DIR/lint-qualification.rs:20:36
--> $DIR/lint-qualification.rs:21:36
|
LL | let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -75,20 +75,20 @@ LL - let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
LL + let _: std::vec::Vec<String> = Vec::<String>::new();
|

error: unnecessary qualification
--> $DIR/lint-qualification.rs:25:12
|
LL | let _: std::fmt::Result = Ok(());
| ^^^^^^^^^^^^^^^^
error: unused import: `std::fmt`
--> $DIR/lint-qualification.rs:25:9
|
help: remove the unnecessary path segments
LL | use std::fmt;
| ^^^^^^^^
|
LL - let _: std::fmt::Result = Ok(());
LL + let _: fmt::Result = Ok(());
note: the lint level is defined here
--> $DIR/lint-qualification.rs:3:9
|
LL | #![deny(unused_imports)]
| ^^^^^^^^^^^^^^

error: unnecessary qualification
--> $DIR/lint-qualification.rs:27:13
--> $DIR/lint-qualification.rs:30:13
|
LL | let _ = <bool as ::std::default::Default>::default(); // issue #121999
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//@ run-rustfix
//@ edition:2021
#![deny(unused_qualifications)]
#![deny(unused_imports)]
#![feature(coroutines, coroutine_trait)]

use std::ops::{
Coroutine,
CoroutineState::{self},
//~^ ERROR unused import: `*`
};
use std::pin::Pin;

#[allow(dead_code)]
fn finish<T>(mut amt: usize, mut t: T) -> T::Return
where T: Coroutine<(), Yield = ()> + Unpin,
{
loop {
match Pin::new(&mut t).resume(()) {
CoroutineState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
CoroutineState::Complete(ret) => {
assert_eq!(amt, 0);
return ret
}
}
}
}


mod foo {
pub fn bar() {}
}

pub fn main() {

use foo::bar;
bar();
//~^ ERROR unnecessary qualification
bar();

// The item `use std::string::String` is imported redundantly.
// Suppress `unused_imports` reporting, otherwise the fixed file will report an error
#[allow(unused_imports)]
use std::string::String;
let s = String::new();
let y = std::string::String::new();
// unnecessary qualification
println!("{} {}", s, y);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//@ run-rustfix
//@ edition:2021
#![deny(unused_qualifications)]
#![deny(unused_imports)]
#![feature(coroutines, coroutine_trait)]

use std::ops::{
Coroutine,
CoroutineState::{self, *},
//~^ ERROR unused import: `*`
};
use std::pin::Pin;

#[allow(dead_code)]
fn finish<T>(mut amt: usize, mut t: T) -> T::Return
where T: Coroutine<(), Yield = ()> + Unpin,
{
loop {
match Pin::new(&mut t).resume(()) {
CoroutineState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
CoroutineState::Complete(ret) => {
assert_eq!(amt, 0);
return ret
}
}
}
}


mod foo {
pub fn bar() {}
}

pub fn main() {

use foo::bar;
foo::bar();
//~^ ERROR unnecessary qualification
bar();

// The item `use std::string::String` is imported redundantly.
// Suppress `unused_imports` reporting, otherwise the fixed file will report an error
#[allow(unused_imports)]
use std::string::String;
let s = String::new();
let y = std::string::String::new();
// unnecessary qualification
println!("{} {}", s, y);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
error: unused import: `*`
--> $DIR/lint-unnecessary-qualification-issue-121331.rs:9:28
|
LL | CoroutineState::{self, *},
| ^
|
note: the lint level is defined here
--> $DIR/lint-unnecessary-qualification-issue-121331.rs:4:9
|
LL | #![deny(unused_imports)]
| ^^^^^^^^^^^^^^

error: unnecessary qualification
--> $DIR/lint-unnecessary-qualification-issue-121331.rs:37:5
|
LL | foo::bar();
| ^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-unnecessary-qualification-issue-121331.rs:3:9
|
LL | #![deny(unused_qualifications)]
| ^^^^^^^^^^^^^^^^^^^^^
help: remove the unnecessary path segments
|
LL - foo::bar();
LL + bar();
|

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
@@ -18,6 +18,16 @@ impl Index<str> for A {
}
}

// This is used to make `use std::ops::Index;` not unused_import.
// details in fix(#122373) for issue #121331
pub struct C;
impl Index<str> for C {
type Output = ();
fn index(&self, _: str) -> &Self::Output {
&()
}
}

mod inner {
pub trait Trait<T> {}
}
@@ -29,4 +39,5 @@ use inner::Trait;
impl Trait<u8> for () {}
//~^ ERROR unnecessary qualification

impl Trait<A> for A {}
fn main() {}
Original file line number Diff line number Diff line change
@@ -18,6 +18,16 @@ impl ops::Index<str> for A {
}
}

// This is used to make `use std::ops::Index;` not unused_import.
// details in fix(#122373) for issue #121331
pub struct C;
impl Index<str> for C {
type Output = ();
fn index(&self, _: str) -> &Self::Output {
&()
}
}

mod inner {
pub trait Trait<T> {}
}
@@ -29,4 +39,5 @@ use inner::Trait;
impl inner::Trait<u8> for () {}
//~^ ERROR unnecessary qualification

impl Trait<A> for A {}
fn main() {}
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ LL + impl Index<str> for A {
|

error: unnecessary qualification
--> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:29:6
--> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:39:6
|
LL | impl inner::Trait<u8> for () {}
| ^^^^^^^^^^^^^^^^
2 changes: 2 additions & 0 deletions tests/ui/resolve/unused-qualifications-suggestion.fixed
Original file line number Diff line number Diff line change
@@ -16,8 +16,10 @@ fn main() {
use foo::bar;
bar();
//~^ ERROR unnecessary qualification
bar();

use baz::qux::quux;
quux();
//~^ ERROR unnecessary qualification
quux();
}
2 changes: 2 additions & 0 deletions tests/ui/resolve/unused-qualifications-suggestion.rs
Original file line number Diff line number Diff line change
@@ -16,8 +16,10 @@ fn main() {
use foo::bar;
foo::bar();
//~^ ERROR unnecessary qualification
bar();

use baz::qux::quux;
baz::qux::quux();
//~^ ERROR unnecessary qualification
quux();
}
2 changes: 1 addition & 1 deletion tests/ui/resolve/unused-qualifications-suggestion.stderr
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ LL + bar();
|

error: unnecessary qualification
--> $DIR/unused-qualifications-suggestion.rs:21:5
--> $DIR/unused-qualifications-suggestion.rs:22:5
|
LL | baz::qux::quux();
| ^^^^^^^^^^^^^^