Auto merge of #123497 - GuillaumeGomez:rollup-usqb4q9, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - #122334 (Vendor rustc_codegen_gcc) - #122894 (Move check for error in impl header outside of reporting) - #123149 (Port argument-non-c-like-enum to Rust) - #123311 (Match ergonomics: implement "`&`pat everywhere") - #123350 (Actually use the inferred `ClosureKind` from signature inference in coroutine-closures) - #123474 (Port `run-make/issue-7349` to a codegen test) - #123489 (handle rustc args properly in bootstrap) - #123496 (ping on wf changes, remove fixme) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1921968cc5
@ -79,16 +79,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecaa4c3da2d74c1a991b4faff75d49ab1d0522d9a99d8e2614b3b04d226417ce"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "406a66fba005f1a02661f2f9443e5693dd3a667b7c58e70aa4ccc4c8b50b4758"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -22,7 +22,7 @@ master = ["gccjit/master"]
|
||||
default = ["master"]
|
||||
|
||||
[dependencies]
|
||||
gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
|
||||
gccjit = "2.0"
|
||||
|
||||
# Local copy.
|
||||
#gccjit = { path = "../gccjit.rs" }
|
||||
|
@ -567,6 +567,8 @@ declare_features! (
|
||||
(unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
|
||||
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
|
||||
(unstable, raw_ref_op, "1.41.0", Some(64490)),
|
||||
/// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references.
|
||||
(incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)),
|
||||
/// Allows using the `#[register_tool]` attribute.
|
||||
(unstable, register_tool, "1.41.0", Some(66079)),
|
||||
/// Allows the `#[repr(i128)]` attribute for enums.
|
||||
|
@ -227,11 +227,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
});
|
||||
let closure_kind_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
});
|
||||
|
||||
let closure_kind_ty = match expected_kind {
|
||||
Some(kind) => Ty::from_closure_kind(tcx, kind),
|
||||
|
||||
// Create a type variable (for now) to represent the closure kind.
|
||||
// It will be unified during the upvar inference phase (`upvar.rs`)
|
||||
None => self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
}),
|
||||
};
|
||||
|
||||
let coroutine_captures_by_ref_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
@ -262,10 +269,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
},
|
||||
);
|
||||
|
||||
let coroutine_kind_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
});
|
||||
let coroutine_kind_ty = match expected_kind {
|
||||
Some(kind) => Ty::from_coroutine_closure_kind(tcx, kind),
|
||||
|
||||
// Create a type variable (for now) to represent the closure kind.
|
||||
// It will be unified during the upvar inference phase (`upvar.rs`)
|
||||
None => self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
}),
|
||||
};
|
||||
|
||||
let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
|
@ -130,7 +130,14 @@ enum AdjustMode {
|
||||
/// Peel off all immediate reference types.
|
||||
Peel,
|
||||
/// Reset binding mode to the initial mode.
|
||||
/// Used for destructuring assignment, where we don't want any match ergonomics.
|
||||
Reset,
|
||||
/// Produced by ref patterns.
|
||||
/// Reset the binding mode to the initial mode,
|
||||
/// and if the old biding mode was by-reference
|
||||
/// with mutability matching the pattern,
|
||||
/// mark the pattern as having consumed this reference.
|
||||
ResetAndConsumeRef(Mutability),
|
||||
/// Pass on the input binding mode and expected type.
|
||||
Pass,
|
||||
}
|
||||
@ -174,7 +181,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
_ => None,
|
||||
};
|
||||
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
|
||||
let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
|
||||
let (expected, def_bm, ref_pattern_already_consumed) =
|
||||
self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
|
||||
let pat_info = PatInfo {
|
||||
binding_mode: def_bm,
|
||||
top_info: ti,
|
||||
@ -211,7 +219,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
|
||||
PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
|
||||
PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
|
||||
PatKind::Ref(inner, mutbl) => self.check_pat_ref(
|
||||
pat,
|
||||
inner,
|
||||
mutbl,
|
||||
expected,
|
||||
pat_info,
|
||||
ref_pattern_already_consumed,
|
||||
),
|
||||
PatKind::Slice(before, slice, after) => {
|
||||
self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
|
||||
}
|
||||
@ -264,17 +279,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
/// Compute the new expected type and default binding mode from the old ones
|
||||
/// as well as the pattern form we are currently checking.
|
||||
///
|
||||
/// Last entry is only relevant for ref patterns (`&` and `&mut`);
|
||||
/// if `true`, then the ref pattern consumed a match ergonomics inserted reference
|
||||
/// and so does no need to match against a reference in the scrutinee type.
|
||||
fn calc_default_binding_mode(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingAnnotation,
|
||||
adjust_mode: AdjustMode,
|
||||
) -> (Ty<'tcx>, BindingAnnotation) {
|
||||
) -> (Ty<'tcx>, BindingAnnotation, bool) {
|
||||
match adjust_mode {
|
||||
AdjustMode::Pass => (expected, def_bm),
|
||||
AdjustMode::Reset => (expected, INITIAL_BM),
|
||||
AdjustMode::Peel => self.peel_off_references(pat, expected, def_bm),
|
||||
AdjustMode::Pass => (expected, def_bm, false),
|
||||
AdjustMode::Reset => (expected, INITIAL_BM, false),
|
||||
AdjustMode::ResetAndConsumeRef(mutbl) => {
|
||||
(expected, INITIAL_BM, def_bm.0 == ByRef::Yes(mutbl))
|
||||
}
|
||||
AdjustMode::Peel => {
|
||||
let peeled = self.peel_off_references(pat, expected, def_bm);
|
||||
(peeled.0, peeled.1, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,7 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// ```
|
||||
//
|
||||
// See issue #46688.
|
||||
PatKind::Ref(..) => AdjustMode::Reset,
|
||||
PatKind::Ref(_, mutbl) => AdjustMode::ResetAndConsumeRef(*mutbl),
|
||||
// A `_` pattern works with any expected type, so there's no need to do anything.
|
||||
PatKind::Wild
|
||||
// A malformed pattern doesn't have an expected type, so let's just accept any type.
|
||||
@ -840,8 +865,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
|
||||
&& let ty::Dynamic(..) = mt.ty.kind()
|
||||
{
|
||||
// This is "x = SomeTrait" being reduced from
|
||||
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
|
||||
// This is "x = dyn SomeTrait" being reduced from
|
||||
// "let &x = &dyn SomeTrait" or "let box x = Box<dyn SomeTrait>", an error.
|
||||
let type_str = self.ty_to_string(expected);
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
@ -2036,6 +2061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
mutbl: Mutability,
|
||||
expected: Ty<'tcx>,
|
||||
pat_info: PatInfo<'tcx, '_>,
|
||||
consumed_inherited_ref: bool,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let expected = self.shallow_resolve(expected);
|
||||
@ -2051,26 +2077,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
match *expected.kind() {
|
||||
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
|
||||
_ => {
|
||||
let inner_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: inner.span,
|
||||
});
|
||||
let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
|
||||
debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
|
||||
let err = self.demand_eqtype_pat_diag(
|
||||
pat.span,
|
||||
expected,
|
||||
ref_ty,
|
||||
pat_info.top_info,
|
||||
);
|
||||
if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
|
||||
// We already matched against a match-ergonmics inserted reference,
|
||||
// so we don't need to match against a reference from the original type.
|
||||
// Save this infor for use in lowering later
|
||||
self.typeck_results
|
||||
.borrow_mut()
|
||||
.skipped_ref_pats_mut()
|
||||
.insert(pat.hir_id);
|
||||
(expected, expected)
|
||||
} else {
|
||||
let inner_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: inner.span,
|
||||
});
|
||||
let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
|
||||
debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
|
||||
let err = self.demand_eqtype_pat_diag(
|
||||
pat.span,
|
||||
expected,
|
||||
ref_ty,
|
||||
pat_info.top_info,
|
||||
);
|
||||
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
self.borrow_pat_suggestion(&mut err, pat);
|
||||
err.emit();
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
self.borrow_pat_suggestion(&mut err, pat);
|
||||
err.emit();
|
||||
}
|
||||
(ref_ty, inner_ty)
|
||||
}
|
||||
(ref_ty, inner_ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
span: Span,
|
||||
body_id: hir::BodyId,
|
||||
body: &'tcx hir::Body<'tcx>,
|
||||
capture_clause: hir::CaptureBy,
|
||||
mut capture_clause: hir::CaptureBy,
|
||||
) {
|
||||
// Extract the type of the closure.
|
||||
let ty = self.node_ty(closure_hir_id);
|
||||
@ -259,6 +259,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
)
|
||||
.consume_body(body);
|
||||
|
||||
// If a coroutine is comes from a coroutine-closure that is `move`, but
|
||||
// the coroutine-closure was inferred to be `FnOnce` during signature
|
||||
// inference, then it's still possible that we try to borrow upvars from
|
||||
// the coroutine-closure because they are not used by the coroutine body
|
||||
// in a way that forces a move.
|
||||
//
|
||||
// This would lead to an impossible to satisfy situation, since `AsyncFnOnce`
|
||||
// coroutine bodies can't borrow from their parent closure. To fix this,
|
||||
// we force the inner coroutine to also be `move`. This only matters for
|
||||
// coroutine-closures that are `move` since otherwise they themselves will
|
||||
// be borrowing from the outer environment, so there's no self-borrows occuring.
|
||||
if let UpvarArgs::Coroutine(..) = args
|
||||
&& let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) =
|
||||
self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind")
|
||||
&& let parent_hir_id =
|
||||
self.tcx.local_def_id_to_hir_id(self.tcx.local_parent(closure_def_id))
|
||||
&& let parent_ty = self.node_ty(parent_hir_id)
|
||||
&& let Some(ty::ClosureKind::FnOnce) = self.closure_kind(parent_ty)
|
||||
{
|
||||
capture_clause = self.tcx.hir_node(parent_hir_id).expect_closure().capture_clause;
|
||||
}
|
||||
|
||||
debug!(
|
||||
"For closure={:?}, capture_information={:#?}",
|
||||
closure_def_id, delegate.capture_information
|
||||
@ -399,16 +421,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
|
||||
// Additionally, we can now constrain the coroutine's kind type.
|
||||
let ty::Coroutine(_, coroutine_args) =
|
||||
*self.typeck_results.borrow().expr_ty(body.value).kind()
|
||||
else {
|
||||
bug!();
|
||||
};
|
||||
self.demand_eqtype(
|
||||
span,
|
||||
coroutine_args.as_coroutine().kind_ty(),
|
||||
Ty::from_coroutine_closure_kind(self.tcx, closure_kind),
|
||||
);
|
||||
//
|
||||
// We only do this if `infer_kind`, because if we have constrained
|
||||
// the kind from closure signature inference, the kind inferred
|
||||
// for the inner coroutine may actually be more restrictive.
|
||||
if infer_kind {
|
||||
let ty::Coroutine(_, coroutine_args) =
|
||||
*self.typeck_results.borrow().expr_ty(body.value).kind()
|
||||
else {
|
||||
bug!();
|
||||
};
|
||||
self.demand_eqtype(
|
||||
span,
|
||||
coroutine_args.as_coroutine().kind_ty(),
|
||||
Ty::from_coroutine_closure_kind(self.tcx, closure_kind),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.log_closure_min_capture_info(closure_def_id, span);
|
||||
|
@ -345,6 +345,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
||||
_ => {}
|
||||
};
|
||||
|
||||
self.visit_skipped_ref_pats(p.hir_id);
|
||||
self.visit_pat_adjustments(p.span, p.hir_id);
|
||||
|
||||
self.visit_node_id(p.span, p.hir_id);
|
||||
@ -674,6 +675,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_skipped_ref_pats(&mut self, hir_id: hir::HirId) {
|
||||
if self.fcx.typeck_results.borrow_mut().skipped_ref_pats_mut().remove(hir_id) {
|
||||
debug!("node is a skipped ref pat");
|
||||
self.typeck_results.skipped_ref_pats_mut().insert(hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_liberated_fn_sigs(&mut self) {
|
||||
let fcx_typeck_results = self.fcx.typeck_results.borrow();
|
||||
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
|
||||
|
@ -96,6 +96,10 @@ pub struct TypeckResults<'tcx> {
|
||||
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
|
||||
pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// Set of reference patterns that match against a match-ergonomics inserted reference
|
||||
/// (as opposed to against a reference in the scrutinee type).
|
||||
skipped_ref_pats: ItemLocalSet,
|
||||
|
||||
/// Records the reasons that we picked the kind of each closure;
|
||||
/// not all closures are present in the map.
|
||||
closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
|
||||
@ -228,6 +232,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
adjustments: Default::default(),
|
||||
pat_binding_modes: Default::default(),
|
||||
pat_adjustments: Default::default(),
|
||||
skipped_ref_pats: Default::default(),
|
||||
closure_kind_origins: Default::default(),
|
||||
liberated_fn_sigs: Default::default(),
|
||||
fru_field_types: Default::default(),
|
||||
@ -435,6 +440,14 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
|
||||
}
|
||||
|
||||
pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> {
|
||||
LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats }
|
||||
}
|
||||
|
||||
pub fn skipped_ref_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
|
||||
LocalSetInContextMut { hir_owner: self.hir_owner, data: &mut self.skipped_ref_pats }
|
||||
}
|
||||
|
||||
/// Does the pattern recursively contain a `ref mut` binding in it?
|
||||
///
|
||||
/// This is used to determined whether a `deref` pattern should emit a `Deref`
|
||||
@ -629,6 +642,49 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct LocalSetInContext<'a> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a ItemLocalSet,
|
||||
}
|
||||
|
||||
impl<'a> LocalSetInContext<'a> {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.data.is_empty()
|
||||
}
|
||||
|
||||
pub fn contains(&self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.contains(&id.local_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LocalSetInContextMut<'a> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a mut ItemLocalSet,
|
||||
}
|
||||
|
||||
impl<'a> LocalSetInContextMut<'a> {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.data.is_empty()
|
||||
}
|
||||
|
||||
pub fn contains(&self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.contains(&id.local_id)
|
||||
}
|
||||
pub fn insert(&mut self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.insert(id.local_id)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.remove(&id.local_id)
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[derive(HashStable)]
|
||||
#[encodable]
|
||||
|
@ -65,7 +65,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
// we wrap the unadjusted pattern in `PatKind::Deref` repeatedly, consuming the
|
||||
// adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted
|
||||
// gets the least-dereferenced type).
|
||||
let unadjusted_pat = self.lower_pattern_unadjusted(pat);
|
||||
let unadjusted_pat = match pat.kind {
|
||||
hir::PatKind::Ref(inner, _)
|
||||
if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
|
||||
{
|
||||
self.lower_pattern_unadjusted(inner)
|
||||
}
|
||||
_ => self.lower_pattern_unadjusted(pat),
|
||||
};
|
||||
self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold(
|
||||
unadjusted_pat,
|
||||
|pat: Box<_>, ref_ty| {
|
||||
|
@ -91,15 +91,17 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty::Coroutine(_, coroutine_args) = *coroutine_ty.kind() else { bug!("{body:#?}") };
|
||||
// We don't need to generate a by-move coroutine if the kind of the coroutine is
|
||||
// already `FnOnce` -- that means that any upvars that the closure consumes have
|
||||
// already been taken by-value.
|
||||
let coroutine_kind = coroutine_args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap();
|
||||
if coroutine_kind == ty::ClosureKind::FnOnce {
|
||||
// We don't need to generate a by-move coroutine if the coroutine body was
|
||||
// produced by the `CoroutineKindShim`, since it's already by-move.
|
||||
if matches!(body.source.instance, ty::InstanceDef::CoroutineKindShim { .. }) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") };
|
||||
let args = args.as_coroutine();
|
||||
|
||||
let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap();
|
||||
|
||||
let parent_def_id = tcx.local_parent(coroutine_def_id);
|
||||
let ty::CoroutineClosure(_, parent_args) =
|
||||
*tcx.type_of(parent_def_id).instantiate_identity().kind()
|
||||
@ -128,6 +130,12 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
||||
// the outer closure body -- we need to change the coroutine to take the
|
||||
// upvar by value.
|
||||
if coroutine_capture.is_by_ref() && !parent_capture.is_by_ref() {
|
||||
assert_ne!(
|
||||
coroutine_kind,
|
||||
ty::ClosureKind::FnOnce,
|
||||
"`FnOnce` coroutine-closures return coroutines that capture from \
|
||||
their body; it will always result in a borrowck error!"
|
||||
);
|
||||
by_ref_fields.insert(FieldIdx::from_usize(num_args + idx));
|
||||
}
|
||||
|
||||
|
@ -1456,6 +1456,7 @@ symbols! {
|
||||
receiver,
|
||||
recursion_limit,
|
||||
reexport_test_harness_main,
|
||||
ref_pat_everywhere,
|
||||
ref_unwind_safe_trait,
|
||||
reference,
|
||||
reflect,
|
||||
|
@ -407,10 +407,6 @@ fn report_conflicting_impls<'tcx>(
|
||||
impl_span: Span,
|
||||
err: &mut Diag<'_, G>,
|
||||
) {
|
||||
if (overlap.trait_ref, overlap.self_ty).references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
||||
match tcx.span_of_impl(overlap.with_impl) {
|
||||
Ok(span) => {
|
||||
err.span_label(span, "first implementation here");
|
||||
@ -463,6 +459,11 @@ fn report_conflicting_impls<'tcx>(
|
||||
)
|
||||
});
|
||||
|
||||
// Don't report overlap errors if the header references error
|
||||
if let Err(err) = (overlap.trait_ref, overlap.self_ty).error_reported() {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
match used_to_be_allowed {
|
||||
None => {
|
||||
let reported = if overlap.with_impl.is_local()
|
||||
|
@ -714,8 +714,6 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
||||
// perfect and there may be ways to abuse the fact that we
|
||||
// ignore requirements with escaping bound vars. That's a
|
||||
// more general issue however.
|
||||
//
|
||||
// FIXME(eddyb) add the type to `walker` instead of recursing.
|
||||
let fn_sig = tcx.fn_sig(did).instantiate(tcx, args);
|
||||
fn_sig.output().skip_binder().visit_with(self);
|
||||
|
||||
|
@ -1038,6 +1038,7 @@ class RustBuild(object):
|
||||
sync_dirs = "--sync ./src/tools/cargo/Cargo.toml " \
|
||||
"--sync ./src/tools/rust-analyzer/Cargo.toml " \
|
||||
"--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \
|
||||
"--sync ./compiler/rustc_codegen_gcc/Cargo.toml " \
|
||||
"--sync ./src/bootstrap/Cargo.toml "
|
||||
eprint('ERROR: vendoring required, but vendor directory does not exist.')
|
||||
eprint(' Run `cargo vendor {}` to initialize the '
|
||||
|
@ -1011,6 +1011,8 @@ impl Step for PlainSourceTarball {
|
||||
.arg("--sync")
|
||||
.arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
|
||||
.arg("--sync")
|
||||
.arg(builder.src.join("./compiler/rustc_codegen_gcc/Cargo.toml"))
|
||||
.arg("--sync")
|
||||
.arg(builder.src.join("./src/bootstrap/Cargo.toml"))
|
||||
// Will read the libstd Cargo.toml
|
||||
// which uses the unstable `public-dependency` feature.
|
||||
|
@ -2102,12 +2102,10 @@ impl<'a> Builder<'a> {
|
||||
rustdocflags.arg("--cfg=parallel_compiler");
|
||||
}
|
||||
|
||||
// set rustc args passed from command line
|
||||
let rustc_args =
|
||||
self.config.cmd.rustc_args().iter().map(|s| s.to_string()).collect::<Vec<_>>();
|
||||
if !rustc_args.is_empty() {
|
||||
cargo.env("RUSTFLAGS", &rustc_args.join(" "));
|
||||
}
|
||||
// Pass the value of `--rustc-args` from test command. If it's not a test command, this won't set anything.
|
||||
self.config.cmd.rustc_args().iter().for_each(|v| {
|
||||
rustflags.arg(v);
|
||||
});
|
||||
|
||||
Cargo {
|
||||
command: cargo,
|
||||
|
@ -3926,11 +3926,17 @@ impl<'test> TestCx<'test> {
|
||||
cmd.env("IS_MSVC", "1")
|
||||
.env("IS_WINDOWS", "1")
|
||||
.env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
|
||||
.env("CC", format!("'{}' {}", self.config.cc, cflags))
|
||||
.env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
|
||||
// Note: we diverge from legacy run_make and don't lump `CC` the compiler and
|
||||
// default flags together.
|
||||
.env("CC_DEFAULT_FLAGS", &cflags)
|
||||
.env("CC", &self.config.cc)
|
||||
.env("CXX_DEFAULT_FLAGS", &cxxflags)
|
||||
.env("CXX", &self.config.cxx);
|
||||
} else {
|
||||
cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
|
||||
.env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
|
||||
cmd.env("CC_DEFAULT_FLAGS", &self.config.cflags)
|
||||
.env("CC", &self.config.cc)
|
||||
.env("CXX_DEFAULT_FLAGS", &self.config.cxxflags)
|
||||
.env("CXX", &self.config.cxx)
|
||||
.env("AR", &self.config.ar);
|
||||
|
||||
if self.config.target.contains("windows") {
|
||||
|
@ -88,4 +88,38 @@ async fn async_main() {
|
||||
};
|
||||
call_once(c).await;
|
||||
}
|
||||
|
||||
fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T {
|
||||
f
|
||||
}
|
||||
|
||||
// Capture something with `move`, but infer to `AsyncFnOnce`
|
||||
{
|
||||
let x = Hello(6);
|
||||
let c = force_fnonce(async move || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
|
||||
let x = &Hello(7);
|
||||
let c = force_fnonce(async move || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
}
|
||||
|
||||
// Capture something by-ref, but infer to `AsyncFnOnce`
|
||||
{
|
||||
let x = Hello(8);
|
||||
let c = force_fnonce(async || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
|
||||
let x = &Hello(9);
|
||||
let c = force_fnonce(async || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
}
|
||||
}
|
||||
|
@ -8,3 +8,7 @@ Hello(3)
|
||||
Hello(4)
|
||||
Hello(4)
|
||||
Hello(5)
|
||||
Hello(6)
|
||||
Hello(7)
|
||||
Hello(8)
|
||||
Hello(9)
|
||||
|
202
src/tools/run-make-support/src/cc.rs
Normal file
202
src/tools/run-make-support/src/cc.rs
Normal file
@ -0,0 +1,202 @@
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Output};
|
||||
|
||||
use crate::{bin_name, cygpath_windows, handle_failed_output, is_msvc, is_windows, tmp_dir, uname};
|
||||
|
||||
/// Construct a new platform-specific C compiler invocation.
|
||||
///
|
||||
/// WARNING: This means that what flags are accepted by the underlying C compiler is
|
||||
/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
|
||||
pub fn cc() -> Cc {
|
||||
Cc::new()
|
||||
}
|
||||
|
||||
/// A platform-specific C compiler invocation builder. The specific C compiler used is
|
||||
/// passed down from compiletest.
|
||||
#[derive(Debug)]
|
||||
pub struct Cc {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
impl Cc {
|
||||
/// Construct a new platform-specific C compiler invocation.
|
||||
///
|
||||
/// WARNING: This means that what flags are accepted by the underlying C compile is
|
||||
/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
|
||||
pub fn new() -> Self {
|
||||
let compiler = env::var("CC").unwrap();
|
||||
|
||||
let mut cmd = Command::new(compiler);
|
||||
|
||||
let default_cflags = env::var("CC_DEFAULT_FLAGS").unwrap();
|
||||
for flag in default_cflags.split(char::is_whitespace) {
|
||||
cmd.arg(flag);
|
||||
}
|
||||
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
/// Specify path of the input file.
|
||||
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||
self.cmd.arg(path.as_ref());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a *platform-and-compiler-specific* argument. Please consult the docs for the various
|
||||
/// possible C compilers on the various platforms to check which arguments are legal for
|
||||
/// which compiler.
|
||||
pub fn arg(&mut self, flag: &str) -> &mut Self {
|
||||
self.cmd.arg(flag);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add multiple *platform-and-compiler-specific* arguments. Please consult the docs for the
|
||||
/// various possible C compilers on the various platforms to check which arguments are legal
|
||||
/// for which compiler.
|
||||
pub fn args(&mut self, args: &[&str]) -> &mut Self {
|
||||
self.cmd.args(args);
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler. This assumes that the executable
|
||||
/// is under `$TMPDIR`.
|
||||
pub fn out_exe(&mut self, name: &str) -> &mut Self {
|
||||
// Ref: tools.mk (irrelevant lines omitted):
|
||||
//
|
||||
// ```makefile
|
||||
// ifdef IS_MSVC
|
||||
// OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
|
||||
// -Fo:`cygpath -w $(TMPDIR)/$(1).obj`
|
||||
// else
|
||||
// OUT_EXE=-o $(TMPDIR)/$(1)
|
||||
// endif
|
||||
// ```
|
||||
|
||||
if is_msvc() {
|
||||
let fe_path = cygpath_windows(tmp_dir().join(bin_name(name)));
|
||||
let fo_path = cygpath_windows(tmp_dir().join(format!("{name}.obj")));
|
||||
self.cmd.arg(format!("-Fe:{fe_path}"));
|
||||
self.cmd.arg(format!("-Fo:{fo_path}"));
|
||||
} else {
|
||||
self.cmd.arg("-o");
|
||||
self.cmd.arg(tmp_dir().join(name));
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Run the constructed C invocation command and assert that it is successfully run.
|
||||
#[track_caller]
|
||||
pub fn run(&mut self) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.cmd.output().unwrap();
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
/// Inspect what the underlying [`Command`] is up to the current construction.
|
||||
pub fn inspect(&mut self, f: impl FnOnce(&Command)) -> &mut Self {
|
||||
f(&self.cmd);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// `EXTRACFLAGS`
|
||||
pub fn extra_c_flags() -> Vec<&'static str> {
|
||||
// Adapted from tools.mk (trimmed):
|
||||
//
|
||||
// ```makefile
|
||||
// ifdef IS_WINDOWS
|
||||
// ifdef IS_MSVC
|
||||
// EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib ntdll.lib synchronization.lib
|
||||
// else
|
||||
// EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt -lntdll -lsynchronization
|
||||
// endif
|
||||
// else
|
||||
// ifeq ($(UNAME),Darwin)
|
||||
// EXTRACFLAGS := -lresolv
|
||||
// else
|
||||
// ifeq ($(UNAME),FreeBSD)
|
||||
// EXTRACFLAGS := -lm -lpthread -lgcc_s
|
||||
// else
|
||||
// ifeq ($(UNAME),SunOS)
|
||||
// EXTRACFLAGS := -lm -lpthread -lposix4 -lsocket -lresolv
|
||||
// else
|
||||
// ifeq ($(UNAME),OpenBSD)
|
||||
// EXTRACFLAGS := -lm -lpthread -lc++abi
|
||||
// else
|
||||
// EXTRACFLAGS := -lm -lrt -ldl -lpthread
|
||||
// endif
|
||||
// endif
|
||||
// endif
|
||||
// endif
|
||||
// endif
|
||||
// ```
|
||||
|
||||
if is_windows() {
|
||||
if is_msvc() {
|
||||
vec![
|
||||
"ws2_32.lib",
|
||||
"userenv.lib",
|
||||
"advapi32.lib",
|
||||
"bcrypt.lib",
|
||||
"ntdll.lib",
|
||||
"synchronization.lib",
|
||||
]
|
||||
} else {
|
||||
vec!["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"]
|
||||
}
|
||||
} else {
|
||||
match uname() {
|
||||
n if n.contains("Darwin") => vec!["-lresolv"],
|
||||
n if n.contains("FreeBSD") => vec!["-lm", "-lpthread", "-lgcc_s"],
|
||||
n if n.contains("SunOS") => {
|
||||
vec!["-lm", "-lpthread", "-lposix4", "-lsocket", "-lresolv"]
|
||||
}
|
||||
n if n.contains("OpenBSD") => vec!["-lm", "-lpthread", "-lc++abi"],
|
||||
_ => vec!["-lm", "-lrt", "-ldl", "-lpthread"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `EXTRACXXFLAGS`
|
||||
pub fn extra_cxx_flags() -> Vec<&'static str> {
|
||||
// Adapted from tools.mk (trimmed):
|
||||
//
|
||||
// ```makefile
|
||||
// ifdef IS_WINDOWS
|
||||
// ifdef IS_MSVC
|
||||
// else
|
||||
// EXTRACXXFLAGS := -lstdc++
|
||||
// endif
|
||||
// else
|
||||
// ifeq ($(UNAME),Darwin)
|
||||
// EXTRACXXFLAGS := -lc++
|
||||
// else
|
||||
// ifeq ($(UNAME),FreeBSD)
|
||||
// else
|
||||
// ifeq ($(UNAME),SunOS)
|
||||
// else
|
||||
// ifeq ($(UNAME),OpenBSD)
|
||||
// else
|
||||
// EXTRACXXFLAGS := -lstdc++
|
||||
// endif
|
||||
// endif
|
||||
// endif
|
||||
// endif
|
||||
// endif
|
||||
// ```
|
||||
if is_windows() {
|
||||
if is_msvc() { vec![] } else { vec!["-lstdc++"] }
|
||||
} else {
|
||||
match uname() {
|
||||
n if n.contains("Darwin") => vec!["-lc++"],
|
||||
_ => vec!["-lstdc++"],
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
pub mod cc;
|
||||
pub mod run;
|
||||
pub mod rustc;
|
||||
pub mod rustdoc;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Output;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Output};
|
||||
|
||||
pub use object;
|
||||
pub use wasmparser;
|
||||
|
||||
pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
|
||||
pub use run::{run, run_fail};
|
||||
pub use rustc::{aux_build, rustc, Rustc};
|
||||
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
|
||||
@ -18,6 +20,89 @@ pub fn tmp_dir() -> PathBuf {
|
||||
env::var_os("TMPDIR").unwrap().into()
|
||||
}
|
||||
|
||||
/// `TARGET`
|
||||
pub fn target() -> String {
|
||||
env::var("TARGET").unwrap()
|
||||
}
|
||||
|
||||
/// Check if target is windows-like.
|
||||
pub fn is_windows() -> bool {
|
||||
env::var_os("IS_WINDOWS").is_some()
|
||||
}
|
||||
|
||||
/// Check if target uses msvc.
|
||||
pub fn is_msvc() -> bool {
|
||||
env::var_os("IS_MSVC").is_some()
|
||||
}
|
||||
|
||||
/// Construct a path to a static library under `$TMPDIR` given the library name. This will return a
|
||||
/// path with `$TMPDIR` joined with platform-and-compiler-specific library name.
|
||||
pub fn static_lib(name: &str) -> PathBuf {
|
||||
tmp_dir().join(static_lib_name(name))
|
||||
}
|
||||
|
||||
/// Construct the static library name based on the platform.
|
||||
pub fn static_lib_name(name: &str) -> String {
|
||||
// See tools.mk (irrelevant lines omitted):
|
||||
//
|
||||
// ```makefile
|
||||
// ifeq ($(UNAME),Darwin)
|
||||
// STATICLIB = $(TMPDIR)/lib$(1).a
|
||||
// else
|
||||
// ifdef IS_WINDOWS
|
||||
// ifdef IS_MSVC
|
||||
// STATICLIB = $(TMPDIR)/$(1).lib
|
||||
// else
|
||||
// STATICLIB = $(TMPDIR)/lib$(1).a
|
||||
// endif
|
||||
// else
|
||||
// STATICLIB = $(TMPDIR)/lib$(1).a
|
||||
// endif
|
||||
// endif
|
||||
// ```
|
||||
assert!(!name.contains(char::is_whitespace), "name cannot contain whitespace");
|
||||
|
||||
if target().contains("msvc") { format!("{name}.lib") } else { format!("lib{name}.a") }
|
||||
}
|
||||
|
||||
/// Construct the binary name based on platform.
|
||||
pub fn bin_name(name: &str) -> String {
|
||||
if is_windows() { format!("{name}.exe") } else { name.to_string() }
|
||||
}
|
||||
|
||||
/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
|
||||
/// available on the platform!
|
||||
#[track_caller]
|
||||
pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let mut cygpath = Command::new("cygpath");
|
||||
cygpath.arg("-w");
|
||||
cygpath.arg(path.as_ref());
|
||||
let output = cygpath.output().unwrap();
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", cygpath), output, caller_line_number);
|
||||
}
|
||||
let s = String::from_utf8(output.stdout).unwrap();
|
||||
// cygpath -w can attach a newline
|
||||
s.trim().to_string()
|
||||
}
|
||||
|
||||
/// Run `uname`. This assumes that `uname` is available on the platform!
|
||||
#[track_caller]
|
||||
pub fn uname() -> String {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let mut uname = Command::new("uname");
|
||||
let output = uname.output().unwrap();
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", uname), output, caller_line_number);
|
||||
}
|
||||
String::from_utf8(output.stdout).unwrap()
|
||||
}
|
||||
|
||||
fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> ! {
|
||||
if output.status.success() {
|
||||
eprintln!("command incorrectly succeeded at line {caller_line_number}");
|
||||
|
@ -2,17 +2,14 @@ use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Output};
|
||||
|
||||
use super::handle_failed_output;
|
||||
use crate::is_windows;
|
||||
|
||||
fn run_common(bin_name: &str) -> (Command, Output) {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
|
||||
let bin_name =
|
||||
if target.contains("windows") { format!("{}.exe", bin_name) } else { bin_name.to_owned() };
|
||||
use super::{bin_name, handle_failed_output};
|
||||
|
||||
fn run_common(name: &str) -> (Command, Output) {
|
||||
let mut bin_path = PathBuf::new();
|
||||
bin_path.push(env::var("TMPDIR").unwrap());
|
||||
bin_path.push(&bin_name);
|
||||
bin_path.push(&bin_name(name));
|
||||
let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
|
||||
let mut cmd = Command::new(bin_path);
|
||||
cmd.env(&ld_lib_path_envvar, {
|
||||
@ -27,7 +24,7 @@ fn run_common(bin_name: &str) -> (Command, Output) {
|
||||
env::join_paths(paths.iter()).unwrap()
|
||||
});
|
||||
|
||||
if target.contains("windows") {
|
||||
if is_windows() {
|
||||
let mut paths = vec![];
|
||||
for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
|
||||
paths.push(p.to_path_buf());
|
||||
@ -42,11 +39,11 @@ fn run_common(bin_name: &str) -> (Command, Output) {
|
||||
|
||||
/// Run a built binary and make sure it succeeds.
|
||||
#[track_caller]
|
||||
pub fn run(bin_name: &str) -> Output {
|
||||
pub fn run(name: &str) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let (cmd, output) = run_common(bin_name);
|
||||
let (cmd, output) = run_common(name);
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
|
||||
}
|
||||
@ -55,11 +52,11 @@ pub fn run(bin_name: &str) -> Output {
|
||||
|
||||
/// Run a built binary and make sure it fails.
|
||||
#[track_caller]
|
||||
pub fn run_fail(bin_name: &str) -> Output {
|
||||
pub fn run_fail(name: &str) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let (cmd, output) = run_common(bin_name);
|
||||
let (cmd, output) = run_common(name);
|
||||
if output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ run-make/allocator-shim-circular-deps/Makefile
|
||||
run-make/allow-non-lint-warnings-cmdline/Makefile
|
||||
run-make/allow-warnings-cmdline-stability/Makefile
|
||||
run-make/archive-duplicate-names/Makefile
|
||||
run-make/arguments-non-c-like-enum/Makefile
|
||||
run-make/atomic-lock-free/Makefile
|
||||
run-make/bare-outfile/Makefile
|
||||
run-make/branch-protection-check-IBT/Makefile
|
||||
@ -131,7 +130,6 @@ run-make/issue-53964/Makefile
|
||||
run-make/issue-64153/Makefile
|
||||
run-make/issue-68794-textrel-on-minimal-lib/Makefile
|
||||
run-make/issue-69368/Makefile
|
||||
run-make/issue-7349/Makefile
|
||||
run-make/issue-83045/Makefile
|
||||
run-make/issue-83112-incr-test-moved-file/Makefile
|
||||
run-make/issue-84395-lto-embed-bitcode/Makefile
|
||||
|
@ -56,7 +56,7 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)
|
||||
Some((&["rustc_codegen_cranelift"], PERMITTED_CRANELIFT_DEPENDENCIES)),
|
||||
),
|
||||
// tidy-alphabetical-start
|
||||
//("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None), // FIXME uncomment once all deps are vendored
|
||||
("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None),
|
||||
//("library/backtrace", &[], None), // FIXME uncomment once rust-lang/backtrace#562 has been synced back to the rust repo
|
||||
//("library/portable-simd", &[], None), // FIXME uncomment once rust-lang/portable-simd#363 has been synced back to the rust repo
|
||||
//("library/stdarch", EXCEPTIONS_STDARCH, None), // FIXME uncomment once rust-lang/stdarch#1462 has been synced back to the rust repo
|
||||
@ -164,15 +164,12 @@ const EXCEPTIONS_CRANELIFT: ExceptionList = &[
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
|
||||
// FIXME uncomment once all deps are vendored
|
||||
/*
|
||||
const EXCEPTIONS_GCC: ExceptionList = &[
|
||||
// tidy-alphabetical-start
|
||||
("gccjit", "GPL-3.0"),
|
||||
("gccjit_sys", "GPL-3.0"),
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
*/
|
||||
|
||||
const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[
|
||||
("ryu", "Apache-2.0 OR BSL-1.0"), // through serde. BSL is not acceptble, but we use it under Apache-2.0
|
||||
|
33
tests/codegen/no-redundant-item-monomorphization.rs
Normal file
33
tests/codegen/no-redundant-item-monomorphization.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Test to make sure that inner functions within a polymorphic outer function
|
||||
// don't get re-codegened when the outer function is monomorphized. The test
|
||||
// code monomorphizes the outer functions several times, but the magic constants
|
||||
// used in the inner functions should each appear only once in the generated IR.
|
||||
|
||||
// issue: rust-lang/rust#7349
|
||||
//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0
|
||||
|
||||
// CHECK-COUNT-1: ret i32 8675309
|
||||
// CHECK-COUNT-1: ret i32 11235813
|
||||
|
||||
fn outer<T>() {
|
||||
#[allow(dead_code)]
|
||||
fn inner() -> u32 {
|
||||
8675309
|
||||
}
|
||||
inner();
|
||||
}
|
||||
|
||||
extern "C" fn outer_foreign<T>() {
|
||||
#[allow(dead_code)]
|
||||
fn inner() -> u32 {
|
||||
11235813
|
||||
}
|
||||
inner();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
outer::<isize>();
|
||||
outer::<usize>();
|
||||
outer_foreign::<isize>();
|
||||
outer_foreign::<usize>();
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) --crate-type=staticlib nonclike.rs
|
||||
$(CC) test.c $(call STATICLIB,nonclike) $(call OUT_EXE,test) \
|
||||
$(EXTRACFLAGS) $(EXTRACXXFLAGS)
|
||||
$(call RUN,test)
|
20
tests/run-make/arguments-non-c-like-enum/rmake.rs
Normal file
20
tests/run-make/arguments-non-c-like-enum/rmake.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//! Check that non-trivial `repr(C)` enum in Rust has valid C layout.
|
||||
//@ ignore-cross-compile
|
||||
|
||||
extern crate run_make_support;
|
||||
|
||||
use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib};
|
||||
|
||||
pub fn main() {
|
||||
use std::path::Path;
|
||||
|
||||
rustc().input("nonclike.rs").crate_type("staticlib").run();
|
||||
cc().input("test.c")
|
||||
.input(static_lib("nonclike"))
|
||||
.out_exe("test")
|
||||
.args(&extra_c_flags())
|
||||
.args(&extra_cxx_flags())
|
||||
.inspect(|cmd| eprintln!("{cmd:?}"))
|
||||
.run();
|
||||
run("test");
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
# Test to make sure that inner functions within a polymorphic outer function
|
||||
# don't get re-codegened when the outer function is monomorphized. The test
|
||||
# code monomorphizes the outer functions several times, but the magic constants
|
||||
# used in the inner functions should each appear only once in the generated IR.
|
||||
|
||||
all:
|
||||
$(RUSTC) foo.rs --emit=llvm-ir
|
||||
[ "$$(grep -c 'ret i32 8675309' "$(TMPDIR)/foo.ll")" -eq "1" ]
|
||||
[ "$$(grep -c 'ret i32 11235813' "$(TMPDIR)/foo.ll")" -eq "1" ]
|
@ -1,22 +0,0 @@
|
||||
fn outer<T>() {
|
||||
#[allow(dead_code)]
|
||||
fn inner() -> u32 {
|
||||
8675309
|
||||
}
|
||||
inner();
|
||||
}
|
||||
|
||||
extern "C" fn outer_foreign<T>() {
|
||||
#[allow(dead_code)]
|
||||
fn inner() -> u32 {
|
||||
11235813
|
||||
}
|
||||
inner();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
outer::<isize>();
|
||||
outer::<usize>();
|
||||
outer_foreign::<isize>();
|
||||
outer_foreign::<usize>();
|
||||
}
|
@ -79,4 +79,38 @@ async fn async_main() {
|
||||
};
|
||||
call_once(c).await;
|
||||
}
|
||||
|
||||
fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T {
|
||||
f
|
||||
}
|
||||
|
||||
// Capture something with `move`, but infer to `AsyncFnOnce`
|
||||
{
|
||||
let x = Hello(6);
|
||||
let c = force_fnonce(async move || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
|
||||
let x = &Hello(7);
|
||||
let c = force_fnonce(async move || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
}
|
||||
|
||||
// Capture something by-ref, but infer to `AsyncFnOnce`
|
||||
{
|
||||
let x = Hello(8);
|
||||
let c = force_fnonce(async || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
|
||||
let x = &Hello(9);
|
||||
let c = force_fnonce(async || {
|
||||
println!("{x:?}");
|
||||
});
|
||||
call_once(c).await;
|
||||
}
|
||||
}
|
||||
|
@ -8,3 +8,7 @@ Hello(3)
|
||||
Hello(4)
|
||||
Hello(4)
|
||||
Hello(5)
|
||||
Hello(6)
|
||||
Hello(7)
|
||||
Hello(8)
|
||||
Hello(9)
|
||||
|
@ -2,18 +2,22 @@
|
||||
|
||||
#![feature(async_closure)]
|
||||
|
||||
fn main() {
|
||||
fn needs_async_fn(_: impl async Fn()) {}
|
||||
fn needs_async_fn(_: impl async Fn()) {}
|
||||
|
||||
fn a() {
|
||||
let mut x = 1;
|
||||
needs_async_fn(async || {
|
||||
//~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut`
|
||||
//~^ ERROR cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
x += 1;
|
||||
});
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let x = String::new();
|
||||
needs_async_fn(move || async move {
|
||||
//~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
|
||||
println!("{x}");
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,26 +1,5 @@
|
||||
error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut`
|
||||
--> $DIR/wrong-fn-kind.rs:9:20
|
||||
|
|
||||
LL | needs_async_fn(async || {
|
||||
| -------------- -^^^^^^^
|
||||
| | |
|
||||
| _____|______________this closure implements `async FnMut`, not `async Fn`
|
||||
| | |
|
||||
| | required by a bound introduced by this call
|
||||
LL | |
|
||||
LL | | x += 1;
|
||||
| | - closure is `async FnMut` because it mutates the variable `x` here
|
||||
LL | | });
|
||||
| |_____- the requirement to implement `async Fn` derives from here
|
||||
|
|
||||
note: required by a bound in `needs_async_fn`
|
||||
--> $DIR/wrong-fn-kind.rs:6:31
|
||||
|
|
||||
LL | fn needs_async_fn(_: impl async Fn()) {}
|
||||
| ^^^^^^^^^^ required by this bound in `needs_async_fn`
|
||||
|
||||
error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
|
||||
--> $DIR/wrong-fn-kind.rs:15:20
|
||||
--> $DIR/wrong-fn-kind.rs:17:20
|
||||
|
|
||||
LL | needs_async_fn(move || async move {
|
||||
| -------------- -^^^^^^
|
||||
@ -35,11 +14,29 @@ LL | | });
|
||||
| |_____- the requirement to implement `async Fn` derives from here
|
||||
|
|
||||
note: required by a bound in `needs_async_fn`
|
||||
--> $DIR/wrong-fn-kind.rs:6:31
|
||||
--> $DIR/wrong-fn-kind.rs:5:27
|
||||
|
|
||||
LL | fn needs_async_fn(_: impl async Fn()) {}
|
||||
| ^^^^^^^^^^ required by this bound in `needs_async_fn`
|
||||
LL | fn needs_async_fn(_: impl async Fn()) {}
|
||||
| ^^^^^^^^^^ required by this bound in `needs_async_fn`
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/wrong-fn-kind.rs:9:29
|
||||
|
|
||||
LL | fn needs_async_fn(_: impl async Fn()) {}
|
||||
| --------------- change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | needs_async_fn(async || {
|
||||
| _____--------------_--------_^
|
||||
| | | |
|
||||
| | | in this closure
|
||||
| | expects `Fn` instead of `FnMut`
|
||||
LL | |
|
||||
LL | | x += 1;
|
||||
| | - mutable borrow occurs due to use of `x` in closure
|
||||
LL | | });
|
||||
| |_____^ cannot borrow as mutable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0525`.
|
||||
Some errors have detailed explanations: E0525, E0596.
|
||||
For more information about an error, try `rustc --explain E0525`.
|
||||
|
@ -0,0 +1,27 @@
|
||||
error[E0726]: implicit elided lifetime not allowed here
|
||||
--> $DIR/skip-reporting-if-references-err.rs:10:9
|
||||
|
|
||||
LL | impl<T> ToUnit for T {}
|
||||
| ^^^^^^ expected lifetime parameter
|
||||
|
|
||||
help: indicate the anonymous lifetime
|
||||
|
|
||||
LL | impl<T> ToUnit<'_> for T {}
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
|
||||
--> $DIR/skip-reporting-if-references-err.rs:15:29
|
||||
|
|
||||
LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
|
||||
|
||||
error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
|
||||
--> $DIR/skip-reporting-if-references-err.rs:15:18
|
||||
|
|
||||
LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0726.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
@ -0,0 +1,14 @@
|
||||
error[E0726]: implicit elided lifetime not allowed here
|
||||
--> $DIR/skip-reporting-if-references-err.rs:10:9
|
||||
|
|
||||
LL | impl<T> ToUnit for T {}
|
||||
| ^^^^^^ expected lifetime parameter
|
||||
|
|
||||
help: indicate the anonymous lifetime
|
||||
|
|
||||
LL | impl<T> ToUnit<'_> for T {}
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0726`.
|
19
tests/ui/coherence/skip-reporting-if-references-err.rs
Normal file
19
tests/ui/coherence/skip-reporting-if-references-err.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Regression test for #121006.
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
trait ToUnit<'a> {
|
||||
type Unit;
|
||||
}
|
||||
|
||||
impl<T> ToUnit for T {}
|
||||
//~^ ERROR implicit elided lifetime not allowed here
|
||||
|
||||
trait Overlap {}
|
||||
impl<U> Overlap for fn(U) {}
|
||||
impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
|
||||
//[current]~^ ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
|
||||
//[current]~| ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
|
||||
|
||||
fn main() {}
|
14
tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs
Normal file
14
tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs
Normal file
@ -0,0 +1,14 @@
|
||||
pub fn main() {
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
let _: u32 = x;
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_everywhere.rs:2:22
|
||||
|
|
||||
LL | if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
| ^^ --------------- this expression has type `&Option<&Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_everywhere.rs:6:17
|
||||
|
|
||||
LL | if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
| ^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
|
||||
| |
|
||||
| expected `Option<{integer}>`, found `&_`
|
||||
|
|
||||
= note: expected enum `Option<{integer}>`
|
||||
found reference `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_everywhere.rs:10:22
|
||||
|
|
||||
LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
| ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&mut _`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found mutable reference `&mut _`
|
||||
note: to declare a mutable binding use: `mut x`
|
||||
--> $DIR/feature-gate-ref_pat_everywhere.rs:10:22
|
||||
|
|
||||
LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
| ^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) {
|
||||
| ~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
16
tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs
Normal file
16
tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(ref_pat_everywhere)]
|
||||
pub fn main() {
|
||||
if let Some(&x) = Some(0) {
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let &Some(x) = &mut Some(0) {
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&x) = &mut Some(0) {
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
let _: u32 = x;
|
||||
}
|
||||
}
|
44
tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr
Normal file
44
tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr
Normal file
@ -0,0 +1,44 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_everywhere-mutability-mismatch.rs:4:17
|
||||
|
|
||||
LL | if let Some(&x) = Some(0) {
|
||||
| ^^ ------- this expression has type `Option<{integer}>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(x) = Some(0) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_everywhere-mutability-mismatch.rs:8:12
|
||||
|
|
||||
LL | if let &Some(x) = &mut Some(0) {
|
||||
| ^^^^^^^^ ------------ this expression has type `&mut Option<{integer}>`
|
||||
| |
|
||||
| types differ in mutability
|
||||
|
|
||||
= note: expected mutable reference `&mut Option<{integer}>`
|
||||
found reference `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_everywhere-mutability-mismatch.rs:12:17
|
||||
|
|
||||
LL | if let Some(&x) = &mut Some(0) {
|
||||
| ^^ ------------ this expression has type `&mut Option<{integer}>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(x) = &mut Some(0) {
|
||||
| ~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
18
tests/ui/match/ref_pat_everywhere.rs
Normal file
18
tests/ui/match/ref_pat_everywhere.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//@ run-pass
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(ref_pat_everywhere)]
|
||||
|
||||
pub fn main() {
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&x)) = &Some(&mut Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
}
|
@ -469,11 +469,11 @@ message = "Some changes occurred in need_type_info.rs"
|
||||
cc = ["@lcnr"]
|
||||
|
||||
[mentions."compiler/rustc_middle/src/ty/relate.rs"]
|
||||
message = "Type relation code was changed"
|
||||
message = "changes to the core type system"
|
||||
cc = ["@compiler-errors", "@lcnr"]
|
||||
|
||||
[mentions."compiler/rustc_infer/src/infer/relate"]
|
||||
message = "Type relation code was changed"
|
||||
message = "changes to the core type system"
|
||||
cc = ["@compiler-errors", "@lcnr"]
|
||||
|
||||
[mentions."compiler/rustc_middle/src/mir/interpret"]
|
||||
@ -484,6 +484,10 @@ cc = ["@rust-lang/miri"]
|
||||
message = "Some changes occurred to MIR optimizations"
|
||||
cc = ["@rust-lang/wg-mir-opt"]
|
||||
|
||||
[mentions."compiler/rustc_trait_selection/src/traits/wf.rs"]
|
||||
message = "changes to the core type system"
|
||||
cc = ["@compiler-errors", "@lcnr"]
|
||||
|
||||
[mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"]
|
||||
message = "Some changes occurred in `const_evaluatable.rs`"
|
||||
cc = ["@BoxyUwU"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user