Auto merge of #105328 - matthiaskrgr:rollup-qnfksmq, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #104912 (PartialEq: PERs are homogeneous) - #104952 (Streamline the user experience for `x.py setup`) - #104953 (Ensure required submodules at the same time as updating existing submodules) - #105180 (Use proper HirId for async track_caller attribute check) - #105222 (std update libc version and freebsd image build dependencies) - #105223 (suggest parenthesis around ExprWithBlock BinOp ExprWithBlock) - #105230 (Skip recording resolution for duplicated generic params.) - #105301 (update Miri) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8e440b0376
@ -2085,9 +2085,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.135"
|
version = "0.2.138"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-std-workspace-core",
|
"rustc-std-workspace-core",
|
||||||
]
|
]
|
||||||
|
@ -147,6 +147,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
),
|
),
|
||||||
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
|
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
|
||||||
*capture_clause,
|
*capture_clause,
|
||||||
|
None,
|
||||||
*closure_node_id,
|
*closure_node_id,
|
||||||
None,
|
None,
|
||||||
e.span,
|
e.span,
|
||||||
@ -584,6 +585,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
pub(super) fn make_async_expr(
|
pub(super) fn make_async_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
|
outer_hir_id: Option<hir::HirId>,
|
||||||
closure_node_id: NodeId,
|
closure_node_id: NodeId,
|
||||||
ret_ty: Option<hir::FnRetTy<'hir>>,
|
ret_ty: Option<hir::FnRetTy<'hir>>,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -651,18 +653,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
hir::ExprKind::Closure(c)
|
hir::ExprKind::Closure(c)
|
||||||
};
|
};
|
||||||
let parent_has_track_caller = self
|
|
||||||
.attrs
|
|
||||||
.values()
|
|
||||||
.find(|attrs| attrs.into_iter().find(|attr| attr.has_name(sym::track_caller)).is_some())
|
|
||||||
.is_some();
|
|
||||||
let unstable_span =
|
|
||||||
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
|
||||||
|
|
||||||
let hir_id = if parent_has_track_caller {
|
let track_caller = outer_hir_id
|
||||||
let generator_hir_id = self.lower_node_id(closure_node_id);
|
.and_then(|id| self.attrs.get(&id.local_id))
|
||||||
|
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
|
||||||
|
|
||||||
|
let hir_id = self.lower_node_id(closure_node_id);
|
||||||
|
if track_caller {
|
||||||
|
let unstable_span = self.mark_span_with_reason(
|
||||||
|
DesugaringKind::Async,
|
||||||
|
span,
|
||||||
|
self.allow_gen_future.clone(),
|
||||||
|
);
|
||||||
self.lower_attrs(
|
self.lower_attrs(
|
||||||
generator_hir_id,
|
hir_id,
|
||||||
&[Attribute {
|
&[Attribute {
|
||||||
kind: AttrKind::Normal(ptr::P(NormalAttr {
|
kind: AttrKind::Normal(ptr::P(NormalAttr {
|
||||||
item: AttrItem {
|
item: AttrItem {
|
||||||
@ -677,10 +681,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
span: unstable_span,
|
span: unstable_span,
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
generator_hir_id
|
}
|
||||||
} else {
|
|
||||||
self.lower_node_id(closure_node_id)
|
|
||||||
};
|
|
||||||
|
|
||||||
let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
|
let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
|
||||||
|
|
||||||
@ -1019,6 +1020,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
let async_body = this.make_async_expr(
|
let async_body = this.make_async_expr(
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
// FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
|
||||||
|
// can be applied on async closures as well.
|
||||||
|
None,
|
||||||
inner_closure_id,
|
inner_closure_id,
|
||||||
async_ret_ty,
|
async_ret_ty,
|
||||||
body.span,
|
body.span,
|
||||||
|
@ -253,8 +253,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// only cares about the input argument patterns in the function
|
// only cares about the input argument patterns in the function
|
||||||
// declaration (decl), not the return types.
|
// declaration (decl), not the return types.
|
||||||
let asyncness = header.asyncness;
|
let asyncness = header.asyncness;
|
||||||
let body_id =
|
let body_id = this.lower_maybe_async_body(
|
||||||
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
|
span,
|
||||||
|
hir_id,
|
||||||
|
&decl,
|
||||||
|
asyncness,
|
||||||
|
body.as_deref(),
|
||||||
|
);
|
||||||
|
|
||||||
let mut itctx = ImplTraitContext::Universal;
|
let mut itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
|
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
|
||||||
@ -701,6 +706,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
||||||
let hir_id = self.lower_node_id(i.id);
|
let hir_id = self.lower_node_id(i.id);
|
||||||
|
self.lower_attrs(hir_id, &i.attrs);
|
||||||
let trait_item_def_id = hir_id.expect_owner();
|
let trait_item_def_id = hir_id.expect_owner();
|
||||||
|
|
||||||
let (generics, kind, has_default) = match &i.kind {
|
let (generics, kind, has_default) = match &i.kind {
|
||||||
@ -724,7 +730,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
||||||
let asyncness = sig.header.asyncness;
|
let asyncness = sig.header.asyncness;
|
||||||
let body_id =
|
let body_id =
|
||||||
self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
|
self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(&body));
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) = self.lower_method_sig(
|
||||||
generics,
|
generics,
|
||||||
sig,
|
sig,
|
||||||
@ -759,7 +765,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.lower_attrs(hir_id, &i.attrs);
|
|
||||||
let item = hir::TraitItem {
|
let item = hir::TraitItem {
|
||||||
owner_id: trait_item_def_id,
|
owner_id: trait_item_def_id,
|
||||||
ident: self.lower_ident(i.ident),
|
ident: self.lower_ident(i.ident),
|
||||||
@ -798,6 +803,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// Since `default impl` is not yet implemented, this is always true in impls.
|
// Since `default impl` is not yet implemented, this is always true in impls.
|
||||||
let has_value = true;
|
let has_value = true;
|
||||||
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
||||||
|
let hir_id = self.lower_node_id(i.id);
|
||||||
|
self.lower_attrs(hir_id, &i.attrs);
|
||||||
|
|
||||||
let (generics, kind) = match &i.kind {
|
let (generics, kind) = match &i.kind {
|
||||||
AssocItemKind::Const(_, ty, expr) => {
|
AssocItemKind::Const(_, ty, expr) => {
|
||||||
@ -810,8 +817,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
||||||
self.current_item = Some(i.span);
|
self.current_item = Some(i.span);
|
||||||
let asyncness = sig.header.asyncness;
|
let asyncness = sig.header.asyncness;
|
||||||
let body_id =
|
let body_id = self.lower_maybe_async_body(
|
||||||
self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref());
|
i.span,
|
||||||
|
hir_id,
|
||||||
|
&sig.decl,
|
||||||
|
asyncness,
|
||||||
|
body.as_deref(),
|
||||||
|
);
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) = self.lower_method_sig(
|
||||||
generics,
|
generics,
|
||||||
sig,
|
sig,
|
||||||
@ -844,8 +856,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let hir_id = self.lower_node_id(i.id);
|
|
||||||
self.lower_attrs(hir_id, &i.attrs);
|
|
||||||
let item = hir::ImplItem {
|
let item = hir::ImplItem {
|
||||||
owner_id: hir_id.expect_owner(),
|
owner_id: hir_id.expect_owner(),
|
||||||
ident: self.lower_ident(i.ident),
|
ident: self.lower_ident(i.ident),
|
||||||
@ -978,6 +988,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
fn lower_maybe_async_body(
|
fn lower_maybe_async_body(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
fn_id: hir::HirId,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
asyncness: Async,
|
asyncness: Async,
|
||||||
body: Option<&Block>,
|
body: Option<&Block>,
|
||||||
@ -1128,6 +1139,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
let async_expr = this.make_async_expr(
|
let async_expr = this.make_async_expr(
|
||||||
CaptureBy::Value,
|
CaptureBy::Value,
|
||||||
|
Some(fn_id),
|
||||||
closure_id,
|
closure_id,
|
||||||
None,
|
None,
|
||||||
body.span,
|
body.span,
|
||||||
|
@ -32,11 +32,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
|
pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
|
||||||
|
// This suggestion is incorrect for
|
||||||
|
// fn foo() -> bool { match () { () => true } || match () { () => true } }
|
||||||
err.span_suggestion_short(
|
err.span_suggestion_short(
|
||||||
span.shrink_to_hi(),
|
span.shrink_to_hi(),
|
||||||
"consider using a semicolon here",
|
"consider using a semicolon here",
|
||||||
";",
|
";",
|
||||||
Applicability::MachineApplicable,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,20 +390,11 @@ impl<'a> Parser<'a> {
|
|||||||
// want to keep their span info to improve diagnostics in these cases in a later stage.
|
// want to keep their span info to improve diagnostics in these cases in a later stage.
|
||||||
(true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
|
(true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
|
||||||
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
|
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
|
||||||
(true, Some(AssocOp::Add)) // `{ 42 } + 42
|
(true, Some(AssocOp::Add)) | // `{ 42 } + 42` (unary plus)
|
||||||
// If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
|
(true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
|
||||||
// `if x { a } else { b } && if y { c } else { d }`
|
(true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure)
|
||||||
if !self.look_ahead(1, |t| t.is_used_keyword()) => {
|
(true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42`
|
||||||
// These cases are ambiguous and can't be identified in the parser alone.
|
=> {
|
||||||
let sp = self.sess.source_map().start_point(self.token.span);
|
|
||||||
self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
(true, Some(AssocOp::LAnd)) |
|
|
||||||
(true, Some(AssocOp::LOr)) |
|
|
||||||
(true, Some(AssocOp::BitOr)) => {
|
|
||||||
// `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
|
|
||||||
// above due to #74233.
|
|
||||||
// These cases are ambiguous and can't be identified in the parser alone.
|
// These cases are ambiguous and can't be identified in the parser alone.
|
||||||
//
|
//
|
||||||
// Bitwise AND is left out because guessing intent is hard. We can make
|
// Bitwise AND is left out because guessing intent is hard. We can make
|
||||||
|
@ -2360,8 +2360,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
if let GenericParamKind::Lifetime = param.kind {
|
if let GenericParamKind::Lifetime = param.kind {
|
||||||
// Record lifetime res, so lowering knows there is something fishy.
|
// Record lifetime res, so lowering knows there is something fishy.
|
||||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
entry.insert(param.ident.span);
|
entry.insert(param.ident.span);
|
||||||
|
@ -29,8 +29,7 @@ use crate::marker::StructuralPartialEq;
|
|||||||
|
|
||||||
use self::Ordering::*;
|
use self::Ordering::*;
|
||||||
|
|
||||||
/// Trait for equality comparisons which are [partial equivalence
|
/// Trait for equality comparisons.
|
||||||
/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
|
|
||||||
///
|
///
|
||||||
/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
|
/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
|
||||||
/// We use the easier-to-read infix notation in the remainder of this documentation.
|
/// We use the easier-to-read infix notation in the remainder of this documentation.
|
||||||
@ -38,6 +37,8 @@ use self::Ordering::*;
|
|||||||
/// This trait allows for partial equality, for types that do not have a full
|
/// This trait allows for partial equality, for types that do not have a full
|
||||||
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
|
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
|
||||||
/// so floating point types implement `PartialEq` but not [`trait@Eq`].
|
/// so floating point types implement `PartialEq` but not [`trait@Eq`].
|
||||||
|
/// Formally speaking, when `Rhs == Self`, this trait corresponds to a [partial equivalence
|
||||||
|
/// relation](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
|
||||||
///
|
///
|
||||||
/// Implementations must ensure that `eq` and `ne` are consistent with each other:
|
/// Implementations must ensure that `eq` and `ne` are consistent with each other:
|
||||||
///
|
///
|
||||||
|
@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
|
|||||||
panic_unwind = { path = "../panic_unwind", optional = true }
|
panic_unwind = { path = "../panic_unwind", optional = true }
|
||||||
panic_abort = { path = "../panic_abort" }
|
panic_abort = { path = "../panic_abort" }
|
||||||
core = { path = "../core" }
|
core = { path = "../core" }
|
||||||
libc = { version = "0.2.135", default-features = false, features = ['rustc-dep-of-std'] }
|
libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
|
||||||
compiler_builtins = { version = "0.1.82" }
|
compiler_builtins = { version = "0.1.82" }
|
||||||
profiler_builtins = { path = "../profiler_builtins", optional = true }
|
profiler_builtins = { path = "../profiler_builtins", optional = true }
|
||||||
unwind = { path = "../unwind" }
|
unwind = { path = "../unwind" }
|
||||||
|
@ -143,7 +143,7 @@ pub enum Subcommand {
|
|||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
},
|
},
|
||||||
Setup {
|
Setup {
|
||||||
profile: Profile,
|
profile: Option<Profile>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,14 +628,15 @@ Arguments:
|
|||||||
|path| format!("{} is not a valid UTF8 string", path.to_string_lossy())
|
|path| format!("{} is not a valid UTF8 string", path.to_string_lossy())
|
||||||
));
|
));
|
||||||
|
|
||||||
profile_string.parse().unwrap_or_else(|err| {
|
let profile = profile_string.parse().unwrap_or_else(|err| {
|
||||||
eprintln!("error: {}", err);
|
eprintln!("error: {}", err);
|
||||||
eprintln!("help: the available profiles are:");
|
eprintln!("help: the available profiles are:");
|
||||||
eprint!("{}", Profile::all_for_help("- "));
|
eprint!("{}", Profile::all_for_help("- "));
|
||||||
crate::detail_exit(1);
|
crate::detail_exit(1);
|
||||||
})
|
});
|
||||||
|
Some(profile)
|
||||||
} else {
|
} else {
|
||||||
t!(crate::setup::interactive_path())
|
None
|
||||||
};
|
};
|
||||||
Subcommand::Setup { profile }
|
Subcommand::Setup { profile }
|
||||||
}
|
}
|
||||||
|
@ -542,16 +542,6 @@ impl Build {
|
|||||||
metrics: metrics::BuildMetrics::init(),
|
metrics: metrics::BuildMetrics::init(),
|
||||||
};
|
};
|
||||||
|
|
||||||
build.verbose("finding compilers");
|
|
||||||
cc_detect::find(&mut build);
|
|
||||||
// When running `setup`, the profile is about to change, so any requirements we have now may
|
|
||||||
// be different on the next invocation. Don't check for them until the next time x.py is
|
|
||||||
// run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
|
|
||||||
if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
|
|
||||||
build.verbose("running sanity check");
|
|
||||||
sanity::check(&mut build);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If local-rust is the same major.minor as the current version, then force a
|
// If local-rust is the same major.minor as the current version, then force a
|
||||||
// local-rebuild
|
// local-rebuild
|
||||||
let local_version_verbose =
|
let local_version_verbose =
|
||||||
@ -567,16 +557,34 @@ impl Build {
|
|||||||
build.local_rebuild = true;
|
build.local_rebuild = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we update these before gathering metadata so we don't get an error about missing
|
build.verbose("finding compilers");
|
||||||
// Cargo.toml files.
|
cc_detect::find(&mut build);
|
||||||
let rust_submodules =
|
// When running `setup`, the profile is about to change, so any requirements we have now may
|
||||||
["src/tools/rust-installer", "src/tools/cargo", "library/backtrace", "library/stdarch"];
|
// be different on the next invocation. Don't check for them until the next time x.py is
|
||||||
for s in rust_submodules {
|
// run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
|
||||||
build.update_submodule(Path::new(s));
|
//
|
||||||
}
|
// Similarly, for `setup` we don't actually need submodules or cargo metadata.
|
||||||
|
if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
|
||||||
|
build.verbose("running sanity check");
|
||||||
|
sanity::check(&mut build);
|
||||||
|
|
||||||
build.verbose("learning about cargo");
|
// Make sure we update these before gathering metadata so we don't get an error about missing
|
||||||
metadata::build(&mut build);
|
// Cargo.toml files.
|
||||||
|
let rust_submodules = [
|
||||||
|
"src/tools/rust-installer",
|
||||||
|
"src/tools/cargo",
|
||||||
|
"library/backtrace",
|
||||||
|
"library/stdarch",
|
||||||
|
];
|
||||||
|
for s in rust_submodules {
|
||||||
|
build.update_submodule(Path::new(s));
|
||||||
|
}
|
||||||
|
// Now, update all existing submodules.
|
||||||
|
build.update_existing_submodules();
|
||||||
|
|
||||||
|
build.verbose("learning about cargo");
|
||||||
|
metadata::build(&mut build);
|
||||||
|
}
|
||||||
|
|
||||||
build
|
build
|
||||||
}
|
}
|
||||||
@ -668,7 +676,7 @@ impl Build {
|
|||||||
|
|
||||||
/// If any submodule has been initialized already, sync it unconditionally.
|
/// If any submodule has been initialized already, sync it unconditionally.
|
||||||
/// This avoids contributors checking in a submodule change by accident.
|
/// This avoids contributors checking in a submodule change by accident.
|
||||||
pub fn maybe_update_submodules(&self) {
|
pub fn update_existing_submodules(&self) {
|
||||||
// Avoid running git when there isn't a git checkout.
|
// Avoid running git when there isn't a git checkout.
|
||||||
if !self.config.submodules(&self.rust_info()) {
|
if !self.config.submodules(&self.rust_info()) {
|
||||||
return;
|
return;
|
||||||
@ -697,8 +705,6 @@ impl Build {
|
|||||||
job::setup(self);
|
job::setup(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.maybe_update_submodules();
|
|
||||||
|
|
||||||
if let Subcommand::Format { check, paths } = &self.config.cmd {
|
if let Subcommand::Format { check, paths } = &self.config.cmd {
|
||||||
return format::format(&builder::Builder::new(&self), *check, &paths);
|
return format::format(&builder::Builder::new(&self), *check, &paths);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
|
use crate::Config;
|
||||||
use crate::{t, VERSION};
|
use crate::{t, VERSION};
|
||||||
use crate::{Config, TargetSelection};
|
|
||||||
use std::env::consts::EXE_SUFFIX;
|
use std::env::consts::EXE_SUFFIX;
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
|
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{
|
use std::{fmt, fs, io};
|
||||||
env, fmt, fs,
|
|
||||||
io::{self, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum Profile {
|
pub enum Profile {
|
||||||
@ -81,10 +79,53 @@ impl fmt::Display for Profile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(config: &Config, profile: Profile) {
|
pub fn setup(config: &Config, profile: Option<Profile>) {
|
||||||
let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
|
let profile = profile.unwrap_or_else(|| t!(interactive_path()));
|
||||||
|
let stage_path =
|
||||||
|
["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
|
||||||
|
|
||||||
|
if !rustup_installed() && profile != Profile::User {
|
||||||
|
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
|
||||||
|
} else if stage_dir_exists(&stage_path[..]) {
|
||||||
|
attempt_toolchain_link(&stage_path[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let suggestions = match profile {
|
||||||
|
Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
|
||||||
|
Profile::Tools => &[
|
||||||
|
"check",
|
||||||
|
"build",
|
||||||
|
"test src/test/rustdoc*",
|
||||||
|
"test src/tools/clippy",
|
||||||
|
"test src/tools/miri",
|
||||||
|
"test src/tools/rustfmt",
|
||||||
|
],
|
||||||
|
Profile::Library => &["check", "build", "test library/std", "doc"],
|
||||||
|
Profile::User => &["dist", "build"],
|
||||||
|
};
|
||||||
|
|
||||||
|
t!(install_git_hook_maybe(&config));
|
||||||
|
|
||||||
|
println!();
|
||||||
|
|
||||||
|
println!("To get started, try one of the following commands:");
|
||||||
|
for cmd in suggestions {
|
||||||
|
println!("- `x.py {}`", cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile != Profile::User {
|
||||||
|
println!(
|
||||||
|
"For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
|
||||||
|
setup_config_toml(path, profile, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
|
eprintln!();
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
|
"error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
|
||||||
path.display()
|
path.display()
|
||||||
@ -107,49 +148,6 @@ pub fn setup(config: &Config, profile: Profile) {
|
|||||||
|
|
||||||
let include_path = profile.include_path(&config.src);
|
let include_path = profile.include_path(&config.src);
|
||||||
println!("`x.py` will now use the configuration at {}", include_path.display());
|
println!("`x.py` will now use the configuration at {}", include_path.display());
|
||||||
|
|
||||||
let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
|
|
||||||
let stage_path =
|
|
||||||
["build", build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
|
|
||||||
|
|
||||||
println!();
|
|
||||||
|
|
||||||
if !rustup_installed() && profile != Profile::User {
|
|
||||||
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
|
|
||||||
} else if stage_dir_exists(&stage_path[..]) {
|
|
||||||
attempt_toolchain_link(&stage_path[..]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let suggestions = match profile {
|
|
||||||
Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
|
|
||||||
Profile::Tools => &[
|
|
||||||
"check",
|
|
||||||
"build",
|
|
||||||
"test src/test/rustdoc*",
|
|
||||||
"test src/tools/clippy",
|
|
||||||
"test src/tools/miri",
|
|
||||||
"test src/tools/rustfmt",
|
|
||||||
],
|
|
||||||
Profile::Library => &["check", "build", "test library/std", "doc"],
|
|
||||||
Profile::User => &["dist", "build"],
|
|
||||||
};
|
|
||||||
|
|
||||||
println!();
|
|
||||||
|
|
||||||
t!(install_git_hook_maybe(&config));
|
|
||||||
|
|
||||||
println!();
|
|
||||||
|
|
||||||
println!("To get started, try one of the following commands:");
|
|
||||||
for cmd in suggestions {
|
|
||||||
println!("- `x.py {}`", cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if profile != Profile::User {
|
|
||||||
println!(
|
|
||||||
"For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rustup_installed() -> bool {
|
fn rustup_installed() -> bool {
|
||||||
@ -303,7 +301,18 @@ pub fn interactive_path() -> io::Result<Profile> {
|
|||||||
|
|
||||||
// install a git hook to automatically run tidy --bless, if they want
|
// install a git hook to automatically run tidy --bless, if they want
|
||||||
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
|
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
|
||||||
|
let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
|
||||||
|
assert!(output.status.success(), "failed to run `git`");
|
||||||
|
PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
|
||||||
|
}));
|
||||||
|
let dst = git.join("hooks").join("pre-push");
|
||||||
|
if dst.exists() {
|
||||||
|
// The git hook has already been set up, or the user already has a custom hook.
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
|
println!();
|
||||||
println!(
|
println!(
|
||||||
"Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
|
"Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
|
||||||
If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
|
If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
|
||||||
@ -329,12 +338,6 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
|
|||||||
|
|
||||||
if should_install {
|
if should_install {
|
||||||
let src = config.src.join("src").join("etc").join("pre-push.sh");
|
let src = config.src.join("src").join("etc").join("pre-push.sh");
|
||||||
let git =
|
|
||||||
t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
|
|
||||||
assert!(output.status.success(), "failed to run `git`");
|
|
||||||
PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
|
|
||||||
}));
|
|
||||||
let dst = git.join("hooks").join("pre-push");
|
|
||||||
match fs::hard_link(src, &dst) {
|
match fs::hard_link(src, &dst) {
|
||||||
Err(e) => eprintln!(
|
Err(e) => eprintln!(
|
||||||
"error: could not create hook {}: do you already have the git hook installed?\n{}",
|
"error: could not create hook {}: do you already have the git hook installed?\n{}",
|
||||||
|
@ -53,7 +53,7 @@ files_to_extract=(
|
|||||||
for lib in c cxxrt gcc_s m thr util; do
|
for lib in c cxxrt gcc_s m thr util; do
|
||||||
files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
|
files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
|
||||||
done
|
done
|
||||||
for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do
|
for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm memstat; do
|
||||||
files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
|
files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
|
||||||
done
|
done
|
||||||
|
|
||||||
|
11
src/test/ui/async-await/track-caller/issue-105134.rs
Normal file
11
src/test/ui/async-await/track-caller/issue-105134.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// check-pass
|
||||||
|
// edition:2021
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn f() {
|
||||||
|
let _ = async {};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
f();
|
||||||
|
}
|
@ -54,6 +54,19 @@ async fn foo_track_caller() {
|
|||||||
bar_track_caller().await
|
bar_track_caller().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
#[track_caller]
|
||||||
|
async fn bar_assoc() {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn foo_assoc() {
|
||||||
|
Foo::bar_assoc().await
|
||||||
|
}
|
||||||
|
|
||||||
fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
|
fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
|
||||||
let loc = Arc::new(Mutex::new(None));
|
let loc = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
@ -73,4 +86,5 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
|
|||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(panicked_at(|| block_on(foo())), 41);
|
assert_eq!(panicked_at(|| block_on(foo())), 41);
|
||||||
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
|
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
|
||||||
|
assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
|
||||||
}
|
}
|
||||||
|
4
src/test/ui/const-generics/defaults/self-referential.rs
Normal file
4
src/test/ui/const-generics/defaults/self-referential.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
trait Foo<const M: u8, const M: u8 = M> {}
|
||||||
|
//~^ ERROR the name `M` is already used for a generic parameter in this item's generic parameters
|
||||||
|
impl Foo<2> for () {}
|
||||||
|
fn main() {}
|
11
src/test/ui/const-generics/defaults/self-referential.stderr
Normal file
11
src/test/ui/const-generics/defaults/self-referential.stderr
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
error[E0403]: the name `M` is already used for a generic parameter in this item's generic parameters
|
||||||
|
--> $DIR/self-referential.rs:1:30
|
||||||
|
|
|
||||||
|
LL | trait Foo<const M: u8, const M: u8 = M> {}
|
||||||
|
| - ^ already used
|
||||||
|
| |
|
||||||
|
| first use of `M`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0403`.
|
@ -55,10 +55,10 @@ LL | impl<T,T> Qux<T,T> for Option<T> {}
|
|||||||
| first use of `T`
|
| first use of `T`
|
||||||
|
|
||||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||||
--> $DIR/duplicate-type-parameter.rs:24:6
|
--> $DIR/duplicate-type-parameter.rs:24:8
|
||||||
|
|
|
|
||||||
LL | impl<T,T> Qux<T,T> for Option<T> {}
|
LL | impl<T,T> Qux<T,T> for Option<T> {}
|
||||||
| ^ unconstrained type parameter
|
| ^ unconstrained type parameter
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
|
|||||||
{ foo(); } || { true } //~ ERROR E0308
|
{ foo(); } || { true } //~ ERROR E0308
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/105179
|
||||||
|
fn r#match() -> i32 {
|
||||||
|
(match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/102171
|
||||||
|
fn r#unsafe() -> i32 {
|
||||||
|
(unsafe { 1 }) + unsafe { 1 } //~ ERROR expected expression, found `+`
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
|
|||||||
{ foo() } || { true } //~ ERROR E0308
|
{ foo() } || { true } //~ ERROR E0308
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/105179
|
||||||
|
fn r#match() -> i32 {
|
||||||
|
match () { () => 1 } + match () { () => 1 } //~ ERROR expected expression, found `+`
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/102171
|
||||||
|
fn r#unsafe() -> i32 {
|
||||||
|
unsafe { 1 } + unsafe { 1 } //~ ERROR expected expression, found `+`
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -55,6 +55,28 @@ help: parentheses are required to parse this as an expression
|
|||||||
LL | ({ true }) | { true }
|
LL | ({ true }) | { true }
|
||||||
| + +
|
| + +
|
||||||
|
|
||||||
|
error: expected expression, found `+`
|
||||||
|
--> $DIR/expr-as-stmt.rs:69:26
|
||||||
|
|
|
||||||
|
LL | match () { () => 1 } + match () { () => 1 }
|
||||||
|
| ^ expected expression
|
||||||
|
|
|
||||||
|
help: parentheses are required to parse this as an expression
|
||||||
|
|
|
||||||
|
LL | (match () { () => 1 }) + match () { () => 1 }
|
||||||
|
| + +
|
||||||
|
|
||||||
|
error: expected expression, found `+`
|
||||||
|
--> $DIR/expr-as-stmt.rs:75:18
|
||||||
|
|
|
||||||
|
LL | unsafe { 1 } + unsafe { 1 }
|
||||||
|
| ^ expected expression
|
||||||
|
|
|
||||||
|
help: parentheses are required to parse this as an expression
|
||||||
|
|
|
||||||
|
LL | (unsafe { 1 }) + unsafe { 1 }
|
||||||
|
| + +
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/expr-as-stmt.rs:64:7
|
--> $DIR/expr-as-stmt.rs:64:7
|
||||||
|
|
|
|
||||||
@ -201,7 +223,26 @@ help: parentheses are required to parse this as an expression
|
|||||||
LL | ({ true }) || { true }
|
LL | ({ true }) || { true }
|
||||||
| + +
|
| + +
|
||||||
|
|
||||||
error: aborting due to 18 previous errors
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/expr-as-stmt.rs:69:5
|
||||||
|
|
|
||||||
|
LL | match () { () => 1 } + match () { () => 1 }
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here
|
||||||
|
| |
|
||||||
|
| expected `()`, found integer
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/expr-as-stmt.rs:75:14
|
||||||
|
|
|
||||||
|
LL | unsafe { 1 } + unsafe { 1 }
|
||||||
|
| ^ expected `()`, found integer
|
||||||
|
|
|
||||||
|
help: you might have meant to return this value
|
||||||
|
|
|
||||||
|
LL | unsafe { return 1; } + unsafe { 1 }
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
|
error: aborting due to 22 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0308, E0600, E0614.
|
Some errors have detailed explanations: E0308, E0600, E0614.
|
||||||
For more information about an error, try `rustc --explain E0308`.
|
For more information about an error, try `rustc --explain E0308`.
|
||||||
|
@ -1 +1 @@
|
|||||||
cef44f53034eac46be3a0e3eec7b2b3d4ef5140b
|
203c8765ea33c65d888febe0e8219c4bb11b0d89
|
||||||
|
@ -45,7 +45,9 @@ pub struct Stacks {
|
|||||||
/// new pointer.
|
/// new pointer.
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
enum RefKind {
|
enum RefKind {
|
||||||
/// `&mut` and `Box`.
|
/// `Box`.
|
||||||
|
Box,
|
||||||
|
/// `&mut`.
|
||||||
Unique { two_phase: bool },
|
Unique { two_phase: bool },
|
||||||
/// `&` with or without interior mutability.
|
/// `&` with or without interior mutability.
|
||||||
Shared,
|
Shared,
|
||||||
@ -56,6 +58,7 @@ enum RefKind {
|
|||||||
impl fmt::Display for RefKind {
|
impl fmt::Display for RefKind {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
RefKind::Box => write!(f, "Box"),
|
||||||
RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
|
RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
|
||||||
RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
|
RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
|
||||||
RefKind::Shared => write!(f, "shared reference"),
|
RefKind::Shared => write!(f, "shared reference"),
|
||||||
@ -654,15 +657,17 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||||||
let (perm, access) = match kind {
|
let (perm, access) = match kind {
|
||||||
RefKind::Unique { two_phase } => {
|
RefKind::Unique { two_phase } => {
|
||||||
// Permission is Unique only if the type is `Unpin` and this is not twophase
|
// Permission is Unique only if the type is `Unpin` and this is not twophase
|
||||||
let perm = if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
|
if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
|
||||||
Permission::Unique
|
(Permission::Unique, Some(AccessKind::Write))
|
||||||
} else {
|
} else {
|
||||||
Permission::SharedReadWrite
|
// FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
|
||||||
};
|
// should do fake accesses here. But then we run into
|
||||||
// We do an access for all full borrows, even if `!Unpin`.
|
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
|
||||||
let access = if !two_phase { Some(AccessKind::Write) } else { None };
|
// we don't do that.
|
||||||
(perm, access)
|
(Permission::SharedReadWrite, None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
|
||||||
RefKind::Raw { mutable: true } => {
|
RefKind::Raw { mutable: true } => {
|
||||||
// Creating a raw ptr does not count as an access
|
// Creating a raw ptr does not count as an access
|
||||||
(Permission::SharedReadWrite, None)
|
(Permission::SharedReadWrite, None)
|
||||||
@ -853,7 +858,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Boxes get a weak protectors, since they may be deallocated.
|
// Boxes get a weak protectors, since they may be deallocated.
|
||||||
self.retag_place(
|
self.retag_place(
|
||||||
place,
|
place,
|
||||||
RefKind::Unique { two_phase: false },
|
RefKind::Box,
|
||||||
self.retag_cause,
|
self.retag_cause,
|
||||||
/*protector*/
|
/*protector*/
|
||||||
(self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
|
(self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
//! Reborrowing a `&mut !Unpin` must still act like a (fake) read.
|
|
||||||
use std::marker::PhantomPinned;
|
|
||||||
|
|
||||||
struct NotUnpin(i32, PhantomPinned);
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
unsafe {
|
|
||||||
let mut x = NotUnpin(0, PhantomPinned);
|
|
||||||
// Mutable borrow of `Unpin` field (with lifetime laundering)
|
|
||||||
let fieldref = &mut *(&mut x.0 as *mut i32);
|
|
||||||
// Mutable reborrow of the entire `x`, which is `!Unpin` but should
|
|
||||||
// still count as a read since we would add `dereferenceable`.
|
|
||||||
let _xref = &mut x;
|
|
||||||
// That read should have invalidated `fieldref`.
|
|
||||||
*fieldref = 0; //~ ERROR: /write access .* tag does not exist in the borrow stack/
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
|
|
||||||
--> $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
|
|
||||||
|
|
|
||||||
LL | *fieldref = 0;
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
| |
|
|
||||||
| attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
|
|
||||||
| this error occurs as part of an access at ALLOC[0x0..0x4]
|
|
||||||
|
|
|
||||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
|
||||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
|
||||||
help: <TAG> was created by a Unique retag at offsets [0x0..0x4]
|
|
||||||
--> $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
|
|
||||||
|
|
|
||||||
LL | let fieldref = &mut *(&mut x.0 as *mut i32);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
help: <TAG> was later invalidated at offsets [0x0..0x4] by a SharedReadWrite retag
|
|
||||||
--> $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
|
|
||||||
|
|
|
||||||
LL | let _xref = &mut x;
|
|
||||||
| ^^^^^^
|
|
||||||
= note: BACKTRACE:
|
|
||||||
= note: inside `main` at $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
|
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
|||||||
|
#![feature(pin_macro)]
|
||||||
|
|
||||||
|
use std::future::*;
|
||||||
|
use std::marker::PhantomPinned;
|
||||||
|
use std::pin::*;
|
||||||
|
use std::ptr;
|
||||||
|
use std::task::*;
|
||||||
|
|
||||||
|
struct Delay {
|
||||||
|
delay: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Delay {
|
||||||
|
fn new(delay: usize) -> Self {
|
||||||
|
Delay { delay }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Future for Delay {
|
||||||
|
type Output = ();
|
||||||
|
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
|
||||||
|
if self.delay > 0 {
|
||||||
|
self.delay -= 1;
|
||||||
|
Poll::Pending
|
||||||
|
} else {
|
||||||
|
Poll::Ready(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn do_stuff() {
|
||||||
|
(&mut Delay::new(1)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same thing implemented by hand
|
||||||
|
struct DoStuff {
|
||||||
|
state: usize,
|
||||||
|
delay: Delay,
|
||||||
|
delay_ref: *mut Delay,
|
||||||
|
_marker: PhantomPinned,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DoStuff {
|
||||||
|
fn new() -> Self {
|
||||||
|
DoStuff {
|
||||||
|
state: 0,
|
||||||
|
delay: Delay::new(1),
|
||||||
|
delay_ref: ptr::null_mut(),
|
||||||
|
_marker: PhantomPinned,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Future for DoStuff {
|
||||||
|
type Output = ();
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
||||||
|
unsafe {
|
||||||
|
let this = self.get_unchecked_mut();
|
||||||
|
match this.state {
|
||||||
|
0 => {
|
||||||
|
// Set up self-ref.
|
||||||
|
this.delay_ref = &mut this.delay;
|
||||||
|
// Move to next state.
|
||||||
|
this.state = 1;
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
let delay = &mut *this.delay_ref;
|
||||||
|
Pin::new_unchecked(delay).poll(cx)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
struct MyWaker;
|
||||||
|
impl Wake for MyWaker {
|
||||||
|
fn wake(self: Arc<Self>) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let waker = Waker::from(Arc::new(MyWaker));
|
||||||
|
let mut context = Context::from_waker(&waker);
|
||||||
|
|
||||||
|
let mut pinned = pin!(fut);
|
||||||
|
loop {
|
||||||
|
match pinned.as_mut().poll(&mut context) {
|
||||||
|
Poll::Pending => continue,
|
||||||
|
Poll::Ready(v) => return v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
run_fut(do_stuff());
|
||||||
|
run_fut(DoStuff::new());
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user