Skip to content

Commit

Permalink
Auto merge of rust-lang#99165 - matthiaskrgr:rollup-rqpelfa, r=matthi…
Browse files Browse the repository at this point in the history
…askrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#97210 (Support `-A`, `-W`, `-D` and `-F` when running `./x.py clippy`)
 - rust-lang#99055 (Fix rustdoc help options)
 - rust-lang#99075 (Fix duplicated type annotation suggestion)
 - rust-lang#99124 (Fix sized check ICE in asm check)
 - rust-lang#99142 (fix(doctest): treat fatal parse errors as incomplete attributes)
 - rust-lang#99145 (Don't rerun the build script for the compiler each time on non-windows platforms)
 - rust-lang#99146 (Do not error during method probe on `Sized` predicates for types that aren't the method receiver)
 - rust-lang#99161 (compiletest: trim edition before passing as flag)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 12, 2022
2 parents 8a33254 + c05e277 commit b3f4c31
Show file tree
Hide file tree
Showing 31 changed files with 516 additions and 103 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ fn main() {
let target_env = env::var("CARGO_CFG_TARGET_ENV");
if Ok("windows") == target_os.as_deref() && Ok("msvc") == target_env.as_deref() {
set_windows_exe_options();
} else {
// Avoid rerunning the build script every time.
println!("cargo:rerun-if-changed=build.rs");
}
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,14 @@ impl Diagnostic {
self
}

/// Clear any existing suggestions.
pub fn clear_suggestions(&mut self) -> &mut Self {
if let Ok(suggestions) = &mut self.suggestions {
suggestions.clear();
}
self
}

/// Helper for pushing to `self.suggestions`, if available (not disable).
fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
if let Ok(suggestions) = &mut self.suggestions {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_errors/src/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
forward!(pub fn set_is_lint(&mut self,) -> &mut Self);

forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
forward!(pub fn clear_suggestions(&mut self,) -> &mut Self);

forward!(pub fn multipart_suggestion(
&mut self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2094,6 +2094,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
// |
// = note: cannot satisfy `_: Tt`

// Clear any more general suggestions in favor of our specific one
err.clear_suggestions();

err.span_suggestion_verbose(
span.shrink_to_hi(),
&format!(
Expand Down
34 changes: 13 additions & 21 deletions compiler/rustc_typeck/src/check/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_index::vec::Idx;
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
use rustc_middle::ty::{self, Article, FloatTy, InferTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy};
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy};
use rustc_session::lint;
use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_target::abi::{Pointer, VariantIdx};
Expand Down Expand Up @@ -99,8 +99,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.emit();
}

// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
if ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env) {
// Type still may have region variables, but `Sized` does not depend
// on those, so just erase them before querying.
if self.tcx.erase_regions(ty).is_sized(self.tcx.at(DUMMY_SP), self.param_env) {
return true;
}
if let ty::Foreign(..) = ty.kind() {
Expand Down Expand Up @@ -128,30 +131,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
64 => InlineAsmType::I64,
_ => unreachable!(),
};

// Expect types to be fully resolved, no const or type variables.
if ty.has_infer_types_or_consts() {
assert!(self.is_tainted_by_errors());
return None;
}

let asm_ty = match *ty.kind() {
// `!` is allowed for input but not for output (issue #87802)
ty::Never if is_input => return None,
ty::Error(_) => return None,
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
// Somewhat of a hack: fallback in the presence of errors does not actually
// fall back to i32, but to ty::Error. For integer inference variables this
// means that they don't get any fallback and stay as `{integer}`.
// Since compilation can't succeed anyway, it's fine to use this to avoid printing
// "cannot use value of type `{integer}`", even though that would absolutely
// work due due i32 fallback if the current function had no other errors.
ty::Infer(InferTy::IntVar(_)) => {
assert!(self.is_tainted_by_errors());
Some(InlineAsmType::I32)
}
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
ty::Infer(InferTy::FloatVar(_)) => {
assert!(self.is_tainted_by_errors());
Some(InlineAsmType::F32)
}
ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
ty::FnPtr(_) => Some(asm_ty_isize),
Expand Down Expand Up @@ -191,6 +187,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None,
}
}
ty::Infer(_) => unreachable!(),
_ => None,
};
let Some(asm_ty) = asm_ty else {
Expand All @@ -204,11 +201,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
};

if ty.has_infer_types_or_consts() {
assert!(self.is_tainted_by_errors());
return None;
}

// Check that the type implements Copy. The only case where this can
// possibly fail is for SIMD types which don't #[derive(Copy)].
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, DUMMY_SP) {
Expand Down
26 changes: 15 additions & 11 deletions compiler/rustc_typeck/src/check/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,25 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs);

debug!("all_substs={:?}", all_substs);
debug!("rcvr_substs={rcvr_substs:?}, all_substs={all_substs:?}");

// Create the final signature for the method, replacing late-bound regions.
let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_substs);

// If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
// something which derefs to `Self` actually implements the trait and the caller
// wanted to make a static dispatch on it but forgot to import the trait.
// See test `src/test/ui/issue-35976.rs`.
//
// In that case, we'll error anyway, but we'll also re-run the search with all traits
// in scope, and if we find another method which can be used, we'll output an
// appropriate hint suggesting to import the trait.
let filler_substs = rcvr_substs
.extend_to(self.tcx, pick.item.def_id, |def, _| self.tcx.mk_param_from_def(def));
let illegal_sized_bound = self.predicates_require_illegal_sized_bound(
&self.tcx.predicates_of(pick.item.def_id).instantiate(self.tcx, filler_substs),
);

// Unify the (adjusted) self type with what the method expects.
//
// SUBTLE: if we want good error messages, because of "guessing" while matching
Expand All @@ -106,16 +120,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// Make sure nobody calls `drop()` explicitly.
self.enforce_illegal_method_limitations(&pick);

// If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
// something which derefs to `Self` actually implements the trait and the caller
// wanted to make a static dispatch on it but forgot to import the trait.
// See test `src/test/ui/issue-35976.rs`.
//
// In that case, we'll error anyway, but we'll also re-run the search with all traits
// in scope, and if we find another method which can be used, we'll output an
// appropriate hint suggesting to import the trait.
let illegal_sized_bound = self.predicates_require_illegal_sized_bound(&method_predicates);

// Add any trait/regions obligations specified on the method's type parameters.
// We won't add these if we encountered an illegal sized bound, so that we can use
// a custom error in that case.
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_typeck/src/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use rustc_hir::def_id::DefId;
use rustc_infer::infer::{self, InferOk};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable};
use rustc_middle::ty::{DefIdTree, GenericParamDefKind};
use rustc_span::symbol::Ident;
use rustc_span::Span;
use rustc_trait_selection::traits;
Expand Down Expand Up @@ -221,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

// We probe again, taking all traits into account (not only those in scope).
let candidates = match self.lookup_probe(
let mut candidates = match self.lookup_probe(
span,
segment.ident,
self_ty,
Expand All @@ -243,6 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.collect(),
_ => Vec::new(),
};
candidates.retain(|candidate| *candidate != self.tcx.parent(result.callee.def_id));

return Err(IllegalSizedBound(candidates, needs_mut, span));
}
Expand Down
18 changes: 16 additions & 2 deletions src/bootstrap/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
arr.iter().copied().map(String::from)
}

if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
if let Subcommand::Clippy {
fix,
clippy_lint_allow,
clippy_lint_deny,
clippy_lint_warn,
clippy_lint_forbid,
..
} = &builder.config.cmd
{
// disable the most spammy clippy lints
let ignored_lints = vec![
"many_single_char_names", // there are a lot in stdarch
Expand All @@ -32,7 +40,7 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
"wrong_self_convention",
];
let mut args = vec![];
if fix {
if *fix {
#[rustfmt::skip]
args.extend(strings(&[
"--fix", "-Zunstable-options",
Expand All @@ -44,6 +52,12 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
}
args.extend(strings(&["--", "--cap-lints", "warn"]));
args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
let mut clippy_lint_levels: Vec<String> = Vec::new();
clippy_lint_allow.iter().for_each(|v| clippy_lint_levels.push(format!("-A{}", v)));
clippy_lint_deny.iter().for_each(|v| clippy_lint_levels.push(format!("-D{}", v)));
clippy_lint_warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v)));
clippy_lint_forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v)));
args.extend(clippy_lint_levels);
args
} else {
vec![]
Expand Down
17 changes: 16 additions & 1 deletion src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ pub enum Subcommand {
Clippy {
fix: bool,
paths: Vec<PathBuf>,
clippy_lint_allow: Vec<String>,
clippy_lint_deny: Vec<String>,
clippy_lint_warn: Vec<String>,
clippy_lint_forbid: Vec<String>,
},
Fix {
paths: Vec<PathBuf>,
Expand Down Expand Up @@ -246,6 +250,10 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "PROFILE");
opts.optflag("", "llvm-profile-generate", "generate PGO profile with llvm built for rustc");
opts.optopt("", "llvm-profile-use", "use PGO profile for llvm build", "PROFILE");
opts.optmulti("A", "", "allow certain clippy lints", "OPT");
opts.optmulti("D", "", "deny certain clippy lints", "OPT");
opts.optmulti("W", "", "warn about certain clippy lints", "OPT");
opts.optmulti("F", "", "forbid certain clippy lints", "OPT");

// We can't use getopt to parse the options until we have completed specifying which
// options are valid, but under the current implementation, some options are conditional on
Expand Down Expand Up @@ -544,7 +552,14 @@ Arguments:
}
Subcommand::Check { paths }
}
Kind::Clippy => Subcommand::Clippy { paths, fix: matches.opt_present("fix") },
Kind::Clippy => Subcommand::Clippy {
paths,
fix: matches.opt_present("fix"),
clippy_lint_allow: matches.opt_strs("A"),
clippy_lint_warn: matches.opt_strs("W"),
clippy_lint_deny: matches.opt_strs("D"),
clippy_lint_forbid: matches.opt_strs("F"),
},
Kind::Fix => Subcommand::Fix { paths },
Kind::Test => Subcommand::Test {
paths,
Expand Down
22 changes: 11 additions & 11 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,17 @@ impl Options {
return Err(0);
}

let z_flags = matches.opt_strs("Z");
if z_flags.iter().any(|x| *x == "help") {
print_flag_list("-Z", config::DB_OPTIONS);
return Err(0);
}
let c_flags = matches.opt_strs("C");
if c_flags.iter().any(|x| *x == "help") {
print_flag_list("-C", config::CG_OPTIONS);
return Err(0);
}

let color = config::parse_color(matches);
let config::JsonConfig { json_rendered, json_unused_externs, .. } =
config::parse_json(matches);
Expand All @@ -343,17 +354,6 @@ impl Options {
// check for deprecated options
check_deprecated_options(matches, &diag);

let z_flags = matches.opt_strs("Z");
if z_flags.iter().any(|x| *x == "help") {
print_flag_list("-Z", config::DB_OPTIONS);
return Err(0);
}
let c_flags = matches.opt_strs("C");
if c_flags.iter().any(|x| *x == "help") {
print_flag_list("-C", config::CG_OPTIONS);
return Err(0);
}

if matches.opt_strs("passes") == ["list"] {
println!("Available passes for running rustdoc:");
for pass in passes::PASSES {
Expand Down
73 changes: 50 additions & 23 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,31 +726,58 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
// Empty content so nothing to check in here...
return true;
}
rustc_span::create_session_if_not_set_then(edition, |_| {
let filename = FileName::anon_source_code(source);
let sess = ParseSess::with_silent_emitter(None);
let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source.to_owned())
{
Ok(p) => p,
Err(_) => {
debug!("Cannot build a parser to check mod attr so skipping...");
return true;
rustc_driver::catch_fatal_errors(|| {
rustc_span::create_session_if_not_set_then(edition, |_| {
use rustc_errors::emitter::EmitterWriter;
use rustc_errors::Handler;
use rustc_span::source_map::FilePathMapping;

let filename = FileName::anon_source_code(source);
// Any errors in parsing should also appear when the doctest is compiled for real, so just
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fallback_bundle =
rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);

let emitter = EmitterWriter::new(
box io::sink(),
None,
None,
fallback_bundle,
false,
false,
false,
None,
false,
);

let handler = Handler::with_emitter(false, None, box emitter);
let sess = ParseSess::with_span_handler(handler, sm);
let mut parser =
match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
Ok(p) => p,
Err(_) => {
debug!("Cannot build a parser to check mod attr so skipping...");
return true;
}
};
// If a parsing error happened, it's very likely that the attribute is incomplete.
if let Err(e) = parser.parse_attribute(InnerAttrPolicy::Permitted) {
e.cancel();
return false;
}
};
// If a parsing error happened, it's very likely that the attribute is incomplete.
if parser.parse_attribute(InnerAttrPolicy::Permitted).is_err() {
return false;
}
// We now check if there is an unclosed delimiter for the attribute. To do so, we look at
// the `unclosed_delims` and see if the opening square bracket was closed.
parser
.unclosed_delims()
.get(0)
.map(|unclosed| {
unclosed.unclosed_span.map(|s| s.lo()).unwrap_or(BytePos(0)) != BytePos(2)
})
.unwrap_or(true)
// We now check if there is an unclosed delimiter for the attribute. To do so, we look at
// the `unclosed_delims` and see if the opening square bracket was closed.
parser
.unclosed_delims()
.get(0)
.map(|unclosed| {
unclosed.unclosed_span.map(|s| s.lo()).unwrap_or(BytePos(0)) != BytePos(2)
})
.unwrap_or(true)
})
})
.unwrap_or(false)
}

fn partition_source(s: &str, edition: Edition) -> (String, String, String) {
Expand Down
4 changes: 4 additions & 0 deletions src/test/rustdoc-ui/c-help.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// check-pass
// compile-flags: -Chelp

pub struct Foo;
Loading

0 comments on commit b3f4c31

Please sign in to comment.