Skip to content

Commit 3db2c3b

Browse files
committed
Auto merge of rust-lang#119630 - matthiaskrgr:rollup-oymvjkn, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#118680 (Add support for shell argfiles) - rust-lang#119151 (Hide foreign `#[doc(hidden)]` paths in import suggestions) - rust-lang#119350 (Imply outlives-bounds on lazy type aliases) - rust-lang#119354 (Make `negative_bounds` internal & fix some of its issues) - rust-lang#119506 (Use `resolutions(()).effective_visiblities` to avoid cycle errors in `report_object_error`) - rust-lang#119554 (Fix scoping for let chains in match guards) - rust-lang#119563 (Check yield terminator's resume type in borrowck) - rust-lang#119589 (cstore: Remove unnecessary locking from `CrateMetadata`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 11035f9 + b4a7f1e commit 3db2c3b

File tree

98 files changed

+1374
-626
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1374
-626
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3738,6 +3738,7 @@ dependencies = [
37383738
"rustc_trait_selection",
37393739
"rustc_ty_utils",
37403740
"serde_json",
3741+
"shlex",
37413742
"time",
37423743
"tracing",
37433744
"windows",

compiler/rustc_ast_lowering/src/expr.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -546,20 +546,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
546546

547547
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
548548
let pat = self.lower_pat(&arm.pat);
549-
let guard = arm.guard.as_ref().map(|cond| {
550-
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind {
551-
hir::Guard::IfLet(self.arena.alloc(hir::Let {
552-
hir_id: self.next_id(),
553-
span: self.lower_span(*span),
554-
pat: self.lower_pat(pat),
555-
ty: None,
556-
init: self.lower_expr(scrutinee),
557-
is_recovered: *is_recovered,
558-
}))
559-
} else {
560-
hir::Guard::If(self.lower_expr(cond))
561-
}
562-
});
549+
let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond));
563550
let hir_id = self.next_id();
564551
let span = self.lower_span(arm.span);
565552
self.lower_attrs(hir_id, &arm.attrs);

compiler/rustc_ast_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ ast_passes_module_nonascii = trying to load file for module `{$name}` with non-a
188188
ast_passes_negative_bound_not_supported =
189189
negative bounds are not supported
190190
191+
ast_passes_negative_bound_with_parenthetical_notation =
192+
parenthetical notation may not be used for negative bounds
193+
191194
ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
192195
.outer = outer `impl Trait`
193196
.inner = nested `impl Trait` here

compiler/rustc_ast_passes/src/ast_validation.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -1312,13 +1312,24 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13121312
if let GenericBound::Trait(trait_ref, modifiers) = bound
13131313
&& let BoundPolarity::Negative(_) = modifiers.polarity
13141314
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
1315-
&& let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref()
13161315
{
1317-
for arg in &args.args {
1318-
if let ast::AngleBracketedArg::Constraint(constraint) = arg {
1319-
self.dcx()
1320-
.emit_err(errors::ConstraintOnNegativeBound { span: constraint.span });
1316+
match segment.args.as_deref() {
1317+
Some(ast::GenericArgs::AngleBracketed(args)) => {
1318+
for arg in &args.args {
1319+
if let ast::AngleBracketedArg::Constraint(constraint) = arg {
1320+
self.dcx().emit_err(errors::ConstraintOnNegativeBound {
1321+
span: constraint.span,
1322+
});
1323+
}
1324+
}
1325+
}
1326+
// The lowered form of parenthesized generic args contains a type binding.
1327+
Some(ast::GenericArgs::Parenthesized(args)) => {
1328+
self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation {
1329+
span: args.span,
1330+
});
13211331
}
1332+
None => {}
13221333
}
13231334
}
13241335

compiler/rustc_ast_passes/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,13 @@ pub struct ConstraintOnNegativeBound {
763763
pub span: Span,
764764
}
765765

766+
#[derive(Diagnostic)]
767+
#[diag(ast_passes_negative_bound_with_parenthetical_notation)]
768+
pub struct NegativeBoundWithParentheticalNotation {
769+
#[primary_span]
770+
pub span: Span,
771+
}
772+
766773
#[derive(Diagnostic)]
767774
#[diag(ast_passes_invalid_unnamed_field_ty)]
768775
pub struct InvalidUnnamedFieldTy {

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3590,7 +3590,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
35903590
));
35913591
} else if let Some(guard) = &arm.guard {
35923592
self.errors.push((
3593-
arm.pat.span.to(guard.body().span),
3593+
arm.pat.span.to(guard.span),
35943594
format!(
35953595
"if this pattern and condition are matched, {} is not \
35963596
initialized",

compiler/rustc_borrowck/src/type_check/input_output.rs

+12-21
Original file line numberDiff line numberDiff line change
@@ -94,31 +94,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
9494
);
9595
}
9696

97-
debug!(
98-
"equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
99-
body.yield_ty(),
100-
universal_regions.yield_ty
101-
);
102-
103-
// We will not have a universal_regions.yield_ty if we yield (by accident)
104-
// outside of a coroutine and return an `impl Trait`, so emit a span_delayed_bug
105-
// because we don't want to panic in an assert here if we've already got errors.
106-
if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
107-
self.tcx().dcx().span_delayed_bug(
108-
body.span,
109-
format!(
110-
"Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
111-
body.yield_ty(),
112-
universal_regions.yield_ty,
113-
),
97+
if let Some(mir_yield_ty) = body.yield_ty() {
98+
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
99+
self.equate_normalized_input_or_output(
100+
universal_regions.yield_ty.unwrap(),
101+
mir_yield_ty,
102+
yield_span,
114103
);
115104
}
116105

117-
if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
118-
(body.yield_ty(), universal_regions.yield_ty)
119-
{
106+
if let Some(mir_resume_ty) = body.resume_ty() {
120107
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
121-
self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
108+
self.equate_normalized_input_or_output(
109+
universal_regions.resume_ty.unwrap(),
110+
mir_resume_ty,
111+
yield_span,
112+
);
122113
}
123114

124115
// Return types are a bit more complex. They may contain opaque `impl Trait` types.

compiler/rustc_borrowck/src/type_check/liveness/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> {
183183
match ty_context {
184184
TyContext::ReturnTy(SourceInfo { span, .. })
185185
| TyContext::YieldTy(SourceInfo { span, .. })
186+
| TyContext::ResumeTy(SourceInfo { span, .. })
186187
| TyContext::UserTy(span)
187188
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
188189
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);

compiler/rustc_borrowck/src/type_check/mod.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -1450,13 +1450,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14501450
}
14511451
}
14521452
}
1453-
TerminatorKind::Yield { value, .. } => {
1453+
TerminatorKind::Yield { value, resume_arg, .. } => {
14541454
self.check_operand(value, term_location);
14551455

1456-
let value_ty = value.ty(body, tcx);
14571456
match body.yield_ty() {
14581457
None => span_mirbug!(self, term, "yield in non-coroutine"),
14591458
Some(ty) => {
1459+
let value_ty = value.ty(body, tcx);
14601460
if let Err(terr) = self.sub_types(
14611461
value_ty,
14621462
ty,
@@ -1474,6 +1474,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14741474
}
14751475
}
14761476
}
1477+
1478+
match body.resume_ty() {
1479+
None => span_mirbug!(self, term, "yield in non-coroutine"),
1480+
Some(ty) => {
1481+
let resume_ty = resume_arg.ty(body, tcx);
1482+
if let Err(terr) = self.sub_types(
1483+
ty,
1484+
resume_ty.ty,
1485+
term_location.to_locations(),
1486+
ConstraintCategory::Yield,
1487+
) {
1488+
span_mirbug!(
1489+
self,
1490+
term,
1491+
"type of resume place is {:?}, but the resume type is {:?}: {:?}",
1492+
resume_ty,
1493+
ty,
1494+
terr
1495+
);
1496+
}
1497+
}
1498+
}
14771499
}
14781500
}
14791501
}

compiler/rustc_borrowck/src/universal_regions.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ pub struct UniversalRegions<'tcx> {
7676
pub unnormalized_input_tys: &'tcx [Ty<'tcx>],
7777

7878
pub yield_ty: Option<Ty<'tcx>>,
79+
80+
pub resume_ty: Option<Ty<'tcx>>,
7981
}
8082

8183
/// The "defining type" for this MIR. The key feature of the "defining
@@ -525,9 +527,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
525527
debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
526528
debug!("build: local regions = {}..{}", first_local_index, num_universals);
527529

528-
let yield_ty = match defining_ty {
529-
DefiningTy::Coroutine(_, args) => Some(args.as_coroutine().yield_ty()),
530-
_ => None,
530+
let (resume_ty, yield_ty) = match defining_ty {
531+
DefiningTy::Coroutine(_, args) => {
532+
let tys = args.as_coroutine();
533+
(Some(tys.resume_ty()), Some(tys.yield_ty()))
534+
}
535+
_ => (None, None),
531536
};
532537

533538
UniversalRegions {
@@ -541,6 +546,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
541546
unnormalized_output_ty: *unnormalized_output_ty,
542547
unnormalized_input_tys,
543548
yield_ty,
549+
resume_ty,
544550
}
545551
}
546552

compiler/rustc_driver_impl/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ rustc_target = { path = "../rustc_target" }
5050
rustc_trait_selection = { path = "../rustc_trait_selection" }
5151
rustc_ty_utils = { path = "../rustc_ty_utils" }
5252
serde_json = "1.0.59"
53+
shlex = "1.0"
5354
time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] }
5455
tracing = { version = "0.1.35" }
5556
# tidy-alphabetical-end

compiler/rustc_driver_impl/src/args.rs

+91-16
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,113 @@ use std::io;
55

66
use rustc_session::EarlyDiagCtxt;
77

8-
fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
9-
if let Some(path) = arg.strip_prefix('@') {
10-
let file = match fs::read_to_string(path) {
11-
Ok(file) => file,
12-
Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
13-
return Err(Error::Utf8Error(Some(path.to_string())));
8+
/// Expands argfiles in command line arguments.
9+
#[derive(Default)]
10+
struct Expander {
11+
shell_argfiles: bool,
12+
next_is_unstable_option: bool,
13+
expanded: Vec<String>,
14+
}
15+
16+
impl Expander {
17+
/// Handles the next argument. If the argument is an argfile, it is expanded
18+
/// inline.
19+
fn arg(&mut self, arg: &str) -> Result<(), Error> {
20+
if let Some(argfile) = arg.strip_prefix('@') {
21+
match argfile.split_once(':') {
22+
Some(("shell", path)) if self.shell_argfiles => {
23+
shlex::split(&Self::read_file(path)?)
24+
.ok_or_else(|| Error::ShellParseError(path.to_string()))?
25+
.into_iter()
26+
.for_each(|arg| self.push(arg));
27+
}
28+
_ => {
29+
let contents = Self::read_file(argfile)?;
30+
contents.lines().for_each(|arg| self.push(arg.to_string()));
31+
}
32+
}
33+
} else {
34+
self.push(arg.to_string());
35+
}
36+
37+
Ok(())
38+
}
39+
40+
/// Adds a command line argument verbatim with no argfile expansion.
41+
fn push(&mut self, arg: String) {
42+
// Unfortunately, we have to do some eager argparsing to handle unstable
43+
// options which change the behavior of argfile arguments.
44+
//
45+
// Normally, all of the argfile arguments (e.g. `@args.txt`) are
46+
// expanded into our arguments list *and then* the whole list of
47+
// arguments are passed on to be parsed. However, argfile parsing
48+
// options like `-Zshell_argfiles` need to change the behavior of that
49+
// argument expansion. So we have to do a little parsing on our own here
50+
// instead of leaning on the existing logic.
51+
//
52+
// All we care about are unstable options, so we parse those out and
53+
// look for any that affect how we expand argfiles. This argument
54+
// inspection is very conservative; we only change behavior when we see
55+
// exactly the options we're looking for and everything gets passed
56+
// through.
57+
58+
if self.next_is_unstable_option {
59+
self.inspect_unstable_option(&arg);
60+
self.next_is_unstable_option = false;
61+
} else if let Some(unstable_option) = arg.strip_prefix("-Z") {
62+
if unstable_option.is_empty() {
63+
self.next_is_unstable_option = true;
64+
} else {
65+
self.inspect_unstable_option(unstable_option);
66+
}
67+
}
68+
69+
self.expanded.push(arg);
70+
}
71+
72+
/// Consumes the `Expander`, returning the expanded arguments.
73+
fn finish(self) -> Vec<String> {
74+
self.expanded
75+
}
76+
77+
/// Parses any relevant unstable flags specified on the command line.
78+
fn inspect_unstable_option(&mut self, option: &str) {
79+
match option {
80+
"shell-argfiles" => self.shell_argfiles = true,
81+
_ => (),
82+
}
83+
}
84+
85+
/// Reads the contents of a file as UTF-8.
86+
fn read_file(path: &str) -> Result<String, Error> {
87+
fs::read_to_string(path).map_err(|e| {
88+
if e.kind() == io::ErrorKind::InvalidData {
89+
Error::Utf8Error(Some(path.to_string()))
90+
} else {
91+
Error::IOError(path.to_string(), e)
1492
}
15-
Err(err) => return Err(Error::IOError(path.to_string(), err)),
16-
};
17-
Ok(file.lines().map(ToString::to_string).collect())
18-
} else {
19-
Ok(vec![arg])
93+
})
2094
}
2195
}
2296

2397
/// **Note:** This function doesn't interpret argument 0 in any special way.
2498
/// If this function is intended to be used with command line arguments,
2599
/// `argv[0]` must be removed prior to calling it manually.
26100
pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<String> {
27-
let mut args = Vec::new();
101+
let mut expander = Expander::default();
28102
for arg in at_args {
29-
match arg_expand(arg.clone()) {
30-
Ok(arg) => args.extend(arg),
31-
Err(err) => early_dcx.early_fatal(format!("Failed to load argument file: {err}")),
103+
if let Err(err) = expander.arg(arg) {
104+
early_dcx.early_fatal(format!("Failed to load argument file: {err}"));
32105
}
33106
}
34-
args
107+
expander.finish()
35108
}
36109

37110
#[derive(Debug)]
38111
pub enum Error {
39112
Utf8Error(Option<String>),
40113
IOError(String, io::Error),
114+
ShellParseError(String),
41115
}
42116

43117
impl fmt::Display for Error {
@@ -46,6 +120,7 @@ impl fmt::Display for Error {
46120
Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
47121
Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
48122
Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
123+
Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"),
49124
}
50125
}
51126
}

compiler/rustc_feature/src/unstable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ declare_features! (
210210
/// Allows the `multiple_supertrait_upcastable` lint.
211211
(unstable, multiple_supertrait_upcastable, "1.69.0", None),
212212
/// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
213-
(incomplete, negative_bounds, "1.71.0", None),
213+
(internal, negative_bounds, "1.71.0", None),
214214
/// Allows using `#[omit_gdb_pretty_printer_section]`.
215215
(internal, omit_gdb_pretty_printer_section, "1.5.0", None),
216216
/// Allows using `#[prelude_import]` on glob `use` items.

0 commit comments

Comments
 (0)